|
@@ -18,7 +18,6 @@
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
*/
|
|
|
|
|
|
-/* #define DEBUG_ILLEGAL_INSTRUCTIONS */
|
|
|
|
/* #define DEBUG_INLINE_BRANCHES */
|
|
/* #define DEBUG_INLINE_BRANCHES */
|
|
#define S390X_DEBUG_DISAS
|
|
#define S390X_DEBUG_DISAS
|
|
/* #define S390X_DEBUG_DISAS_VERBOSE */
|
|
/* #define S390X_DEBUG_DISAS_VERBOSE */
|
|
@@ -338,105 +337,52 @@ static inline int get_mem_index(DisasContext *s)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static inline void gen_debug(DisasContext *s)
|
|
|
|
|
|
+static void gen_exception(int excp)
|
|
{
|
|
{
|
|
- TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
|
|
|
|
- update_psw_addr(s);
|
|
|
|
- gen_op_calc_cc(s);
|
|
|
|
- gen_helper_exception(cpu_env, tmp);
|
|
|
|
- tcg_temp_free_i32(tmp);
|
|
|
|
- s->is_jmp = DISAS_EXCP;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-#ifdef CONFIG_USER_ONLY
|
|
|
|
-
|
|
|
|
-static void gen_illegal_opcode(CPUS390XState *env, DisasContext *s, int ilc)
|
|
|
|
-{
|
|
|
|
- TCGv_i32 tmp = tcg_const_i32(EXCP_SPEC);
|
|
|
|
- update_psw_addr(s);
|
|
|
|
- gen_op_calc_cc(s);
|
|
|
|
|
|
+ TCGv_i32 tmp = tcg_const_i32(excp);
|
|
gen_helper_exception(cpu_env, tmp);
|
|
gen_helper_exception(cpu_env, tmp);
|
|
tcg_temp_free_i32(tmp);
|
|
tcg_temp_free_i32(tmp);
|
|
- s->is_jmp = DISAS_EXCP;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-#else /* CONFIG_USER_ONLY */
|
|
|
|
-
|
|
|
|
-static void debug_print_inst(CPUS390XState *env, DisasContext *s, int ilc)
|
|
|
|
-{
|
|
|
|
-#ifdef DEBUG_ILLEGAL_INSTRUCTIONS
|
|
|
|
- uint64_t inst = 0;
|
|
|
|
-
|
|
|
|
- switch (ilc & 3) {
|
|
|
|
- case 1:
|
|
|
|
- inst = ld_code2(env, s->pc);
|
|
|
|
- break;
|
|
|
|
- case 2:
|
|
|
|
- inst = ld_code4(env, s->pc);
|
|
|
|
- break;
|
|
|
|
- case 3:
|
|
|
|
- inst = ld_code6(env, s->pc);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- fprintf(stderr, "Illegal instruction [%d at %016" PRIx64 "]: 0x%016"
|
|
|
|
- PRIx64 "\n", ilc, s->pc, inst);
|
|
|
|
-#endif
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void gen_program_exception(CPUS390XState *env, DisasContext *s, int ilc,
|
|
|
|
- int code)
|
|
|
|
|
|
+static void gen_program_exception(DisasContext *s, int code)
|
|
{
|
|
{
|
|
TCGv_i32 tmp;
|
|
TCGv_i32 tmp;
|
|
|
|
|
|
- debug_print_inst(env, s, ilc);
|
|
|
|
-
|
|
|
|
- /* remember what pgm exeption this was */
|
|
|
|
|
|
+ /* Remember what pgm exeption this was. */
|
|
tmp = tcg_const_i32(code);
|
|
tmp = tcg_const_i32(code);
|
|
tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
|
|
tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
|
|
tcg_temp_free_i32(tmp);
|
|
tcg_temp_free_i32(tmp);
|
|
|
|
|
|
- tmp = tcg_const_i32(ilc);
|
|
|
|
- tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilc));
|
|
|
|
|
|
+ tmp = tcg_const_i32(s->next_pc - s->pc);
|
|
|
|
+ tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilen));
|
|
tcg_temp_free_i32(tmp);
|
|
tcg_temp_free_i32(tmp);
|
|
|
|
|
|
- /* advance past instruction */
|
|
|
|
- s->pc += (ilc * 2);
|
|
|
|
|
|
+ /* Advance past instruction. */
|
|
|
|
+ s->pc = s->next_pc;
|
|
update_psw_addr(s);
|
|
update_psw_addr(s);
|
|
|
|
|
|
- /* save off cc */
|
|
|
|
|
|
+ /* Save off cc. */
|
|
gen_op_calc_cc(s);
|
|
gen_op_calc_cc(s);
|
|
|
|
|
|
- /* trigger exception */
|
|
|
|
- tmp = tcg_const_i32(EXCP_PGM);
|
|
|
|
- gen_helper_exception(cpu_env, tmp);
|
|
|
|
- tcg_temp_free_i32(tmp);
|
|
|
|
|
|
+ /* Trigger exception. */
|
|
|
|
+ gen_exception(EXCP_PGM);
|
|
|
|
|
|
- /* end TB here */
|
|
|
|
|
|
+ /* End TB here. */
|
|
s->is_jmp = DISAS_EXCP;
|
|
s->is_jmp = DISAS_EXCP;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-static void gen_illegal_opcode(CPUS390XState *env, DisasContext *s, int ilc)
|
|
|
|
|
|
+static inline void gen_illegal_opcode(DisasContext *s)
|
|
{
|
|
{
|
|
- gen_program_exception(env, s, ilc, PGM_SPECIFICATION);
|
|
|
|
|
|
+ gen_program_exception(s, PGM_SPECIFICATION);
|
|
}
|
|
}
|
|
|
|
|
|
-static void gen_privileged_exception(CPUS390XState *env, DisasContext *s,
|
|
|
|
- int ilc)
|
|
|
|
-{
|
|
|
|
- gen_program_exception(env, s, ilc, PGM_PRIVILEGED);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void check_privileged(CPUS390XState *env, DisasContext *s, int ilc)
|
|
|
|
|
|
+static inline void check_privileged(DisasContext *s)
|
|
{
|
|
{
|
|
if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) {
|
|
if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) {
|
|
- gen_privileged_exception(env, s, ilc);
|
|
|
|
|
|
+ gen_program_exception(s, PGM_PRIVILEGED);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-#endif /* CONFIG_USER_ONLY */
|
|
|
|
-
|
|
|
|
static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
|
|
static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
|
|
{
|
|
{
|
|
TCGv_i64 tmp;
|
|
TCGv_i64 tmp;
|
|
@@ -1769,7 +1715,7 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
LOG_DISAS("illegal e3 operation 0x%x\n", op);
|
|
LOG_DISAS("illegal e3 operation 0x%x\n", op);
|
|
- gen_illegal_opcode(env, s, 3);
|
|
|
|
|
|
+ gen_illegal_opcode(s);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
tcg_temp_free_i64(addr);
|
|
tcg_temp_free_i64(addr);
|
|
@@ -1794,7 +1740,7 @@ static void disas_e5(CPUS390XState *env, DisasContext* s, uint64_t insn)
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
LOG_DISAS("illegal e5 operation 0x%x\n", op);
|
|
LOG_DISAS("illegal e5 operation 0x%x\n", op);
|
|
- gen_illegal_opcode(env, s, 3);
|
|
|
|
|
|
+ gen_illegal_opcode(s);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1809,7 +1755,6 @@ static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
|
|
TCGv_i64 tmp, tmp2, tmp3, tmp4;
|
|
TCGv_i64 tmp, tmp2, tmp3, tmp4;
|
|
TCGv_i32 tmp32_1, tmp32_2;
|
|
TCGv_i32 tmp32_1, tmp32_2;
|
|
int i, stm_len;
|
|
int i, stm_len;
|
|
- int ilc = 3;
|
|
|
|
|
|
|
|
LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
|
|
LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
|
|
op, r1, r3, b2, d2);
|
|
op, r1, r3, b2, d2);
|
|
@@ -1947,7 +1892,7 @@ do_mh:
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
case 0x2f: /* LCTLG R1,R3,D2(B2) [RSE] */
|
|
case 0x2f: /* LCTLG R1,R3,D2(B2) [RSE] */
|
|
/* Load Control */
|
|
/* Load Control */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp32_1 = tcg_const_i32(r1);
|
|
tmp32_1 = tcg_const_i32(r1);
|
|
tmp32_2 = tcg_const_i32(r3);
|
|
tmp32_2 = tcg_const_i32(r3);
|
|
@@ -1959,7 +1904,7 @@ do_mh:
|
|
break;
|
|
break;
|
|
case 0x25: /* STCTG R1,R3,D2(B2) [RSE] */
|
|
case 0x25: /* STCTG R1,R3,D2(B2) [RSE] */
|
|
/* Store Control */
|
|
/* Store Control */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp32_1 = tcg_const_i32(r1);
|
|
tmp32_1 = tcg_const_i32(r1);
|
|
tmp32_2 = tcg_const_i32(r3);
|
|
tmp32_2 = tcg_const_i32(r3);
|
|
@@ -2036,7 +1981,7 @@ do_mh:
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
LOG_DISAS("illegal eb operation 0x%x\n", op);
|
|
LOG_DISAS("illegal eb operation 0x%x\n", op);
|
|
- gen_illegal_opcode(env, s, ilc);
|
|
|
|
|
|
+ gen_illegal_opcode(s);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -2156,7 +2101,7 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
LOG_DISAS("illegal ed operation 0x%x\n", op);
|
|
LOG_DISAS("illegal ed operation 0x%x\n", op);
|
|
- gen_illegal_opcode(env, s, 3);
|
|
|
|
|
|
+ gen_illegal_opcode(s);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
tcg_temp_free_i32(tmp_r1);
|
|
tcg_temp_free_i32(tmp_r1);
|
|
@@ -2313,7 +2258,7 @@ static void disas_a5(CPUS390XState *env, DisasContext *s, int op, int r1,
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
LOG_DISAS("illegal a5 operation 0x%x\n", op);
|
|
LOG_DISAS("illegal a5 operation 0x%x\n", op);
|
|
- gen_illegal_opcode(env, s, 2);
|
|
|
|
|
|
+ gen_illegal_opcode(s);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -2451,7 +2396,7 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
LOG_DISAS("illegal a7 operation 0x%x\n", op);
|
|
LOG_DISAS("illegal a7 operation 0x%x\n", op);
|
|
- gen_illegal_opcode(env, s, 2);
|
|
|
|
|
|
+ gen_illegal_opcode(s);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -2462,7 +2407,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
TCGv_i64 tmp, tmp2, tmp3;
|
|
TCGv_i64 tmp, tmp2, tmp3;
|
|
TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
|
|
TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
|
|
int r1, r2;
|
|
int r1, r2;
|
|
- int ilc = 2;
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
int r3, d2, b2;
|
|
int r3, d2, b2;
|
|
#endif
|
|
#endif
|
|
@@ -2556,7 +2500,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
case 0x02: /* STIDP D2(B2) [S] */
|
|
case 0x02: /* STIDP D2(B2) [S] */
|
|
/* Store CPU ID */
|
|
/* Store CPU ID */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
potential_page_fault(s);
|
|
potential_page_fault(s);
|
|
@@ -2565,7 +2509,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x04: /* SCK D2(B2) [S] */
|
|
case 0x04: /* SCK D2(B2) [S] */
|
|
/* Set Clock */
|
|
/* Set Clock */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
potential_page_fault(s);
|
|
potential_page_fault(s);
|
|
@@ -2584,7 +2528,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x06: /* SCKC D2(B2) [S] */
|
|
case 0x06: /* SCKC D2(B2) [S] */
|
|
/* Set Clock Comparator */
|
|
/* Set Clock Comparator */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
potential_page_fault(s);
|
|
potential_page_fault(s);
|
|
@@ -2593,7 +2537,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x07: /* STCKC D2(B2) [S] */
|
|
case 0x07: /* STCKC D2(B2) [S] */
|
|
/* Store Clock Comparator */
|
|
/* Store Clock Comparator */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
potential_page_fault(s);
|
|
potential_page_fault(s);
|
|
@@ -2602,7 +2546,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x08: /* SPT D2(B2) [S] */
|
|
case 0x08: /* SPT D2(B2) [S] */
|
|
/* Set CPU Timer */
|
|
/* Set CPU Timer */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
potential_page_fault(s);
|
|
potential_page_fault(s);
|
|
@@ -2611,7 +2555,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x09: /* STPT D2(B2) [S] */
|
|
case 0x09: /* STPT D2(B2) [S] */
|
|
/* Store CPU Timer */
|
|
/* Store CPU Timer */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
potential_page_fault(s);
|
|
potential_page_fault(s);
|
|
@@ -2620,7 +2564,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x0a: /* SPKA D2(B2) [S] */
|
|
case 0x0a: /* SPKA D2(B2) [S] */
|
|
/* Set PSW Key from Address */
|
|
/* Set PSW Key from Address */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp2 = tcg_temp_new_i64();
|
|
tmp2 = tcg_temp_new_i64();
|
|
@@ -2632,12 +2576,12 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x0d: /* PTLB [S] */
|
|
case 0x0d: /* PTLB [S] */
|
|
/* Purge TLB */
|
|
/* Purge TLB */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
gen_helper_ptlb(cpu_env);
|
|
gen_helper_ptlb(cpu_env);
|
|
break;
|
|
break;
|
|
case 0x10: /* SPX D2(B2) [S] */
|
|
case 0x10: /* SPX D2(B2) [S] */
|
|
/* Set Prefix Register */
|
|
/* Set Prefix Register */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
potential_page_fault(s);
|
|
potential_page_fault(s);
|
|
@@ -2646,7 +2590,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x11: /* STPX D2(B2) [S] */
|
|
case 0x11: /* STPX D2(B2) [S] */
|
|
/* Store Prefix */
|
|
/* Store Prefix */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp2 = tcg_temp_new_i64();
|
|
tmp2 = tcg_temp_new_i64();
|
|
@@ -2657,7 +2601,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x12: /* STAP D2(B2) [S] */
|
|
case 0x12: /* STAP D2(B2) [S] */
|
|
/* Store CPU Address */
|
|
/* Store CPU Address */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp2 = tcg_temp_new_i64();
|
|
tmp2 = tcg_temp_new_i64();
|
|
@@ -2671,7 +2615,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x21: /* IPTE R1,R2 [RRE] */
|
|
case 0x21: /* IPTE R1,R2 [RRE] */
|
|
/* Invalidate PTE */
|
|
/* Invalidate PTE */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
r1 = (insn >> 4) & 0xf;
|
|
r1 = (insn >> 4) & 0xf;
|
|
r2 = insn & 0xf;
|
|
r2 = insn & 0xf;
|
|
tmp = load_reg(r1);
|
|
tmp = load_reg(r1);
|
|
@@ -2682,7 +2626,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x29: /* ISKE R1,R2 [RRE] */
|
|
case 0x29: /* ISKE R1,R2 [RRE] */
|
|
/* Insert Storage Key Extended */
|
|
/* Insert Storage Key Extended */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
r1 = (insn >> 4) & 0xf;
|
|
r1 = (insn >> 4) & 0xf;
|
|
r2 = insn & 0xf;
|
|
r2 = insn & 0xf;
|
|
tmp = load_reg(r2);
|
|
tmp = load_reg(r2);
|
|
@@ -2694,7 +2638,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x2a: /* RRBE R1,R2 [RRE] */
|
|
case 0x2a: /* RRBE R1,R2 [RRE] */
|
|
/* Set Storage Key Extended */
|
|
/* Set Storage Key Extended */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
r1 = (insn >> 4) & 0xf;
|
|
r1 = (insn >> 4) & 0xf;
|
|
r2 = insn & 0xf;
|
|
r2 = insn & 0xf;
|
|
tmp32_1 = load_reg32(r1);
|
|
tmp32_1 = load_reg32(r1);
|
|
@@ -2706,7 +2650,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x2b: /* SSKE R1,R2 [RRE] */
|
|
case 0x2b: /* SSKE R1,R2 [RRE] */
|
|
/* Set Storage Key Extended */
|
|
/* Set Storage Key Extended */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
r1 = (insn >> 4) & 0xf;
|
|
r1 = (insn >> 4) & 0xf;
|
|
r2 = insn & 0xf;
|
|
r2 = insn & 0xf;
|
|
tmp32_1 = load_reg32(r1);
|
|
tmp32_1 = load_reg32(r1);
|
|
@@ -2717,12 +2661,12 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x34: /* STCH ? */
|
|
case 0x34: /* STCH ? */
|
|
/* Store Subchannel */
|
|
/* Store Subchannel */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
gen_op_movi_cc(s, 3);
|
|
gen_op_movi_cc(s, 3);
|
|
break;
|
|
break;
|
|
case 0x46: /* STURA R1,R2 [RRE] */
|
|
case 0x46: /* STURA R1,R2 [RRE] */
|
|
/* Store Using Real Address */
|
|
/* Store Using Real Address */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
r1 = (insn >> 4) & 0xf;
|
|
r1 = (insn >> 4) & 0xf;
|
|
r2 = insn & 0xf;
|
|
r2 = insn & 0xf;
|
|
tmp32_1 = load_reg32(r1);
|
|
tmp32_1 = load_reg32(r1);
|
|
@@ -2734,7 +2678,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x50: /* CSP R1,R2 [RRE] */
|
|
case 0x50: /* CSP R1,R2 [RRE] */
|
|
/* Compare And Swap And Purge */
|
|
/* Compare And Swap And Purge */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
r1 = (insn >> 4) & 0xf;
|
|
r1 = (insn >> 4) & 0xf;
|
|
r2 = insn & 0xf;
|
|
r2 = insn & 0xf;
|
|
tmp32_1 = tcg_const_i32(r1);
|
|
tmp32_1 = tcg_const_i32(r1);
|
|
@@ -2746,7 +2690,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x5f: /* CHSC ? */
|
|
case 0x5f: /* CHSC ? */
|
|
/* Channel Subsystem Call */
|
|
/* Channel Subsystem Call */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
gen_op_movi_cc(s, 3);
|
|
gen_op_movi_cc(s, 3);
|
|
break;
|
|
break;
|
|
case 0x78: /* STCKE D2(B2) [S] */
|
|
case 0x78: /* STCKE D2(B2) [S] */
|
|
@@ -2760,19 +2704,19 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x79: /* SACF D2(B2) [S] */
|
|
case 0x79: /* SACF D2(B2) [S] */
|
|
/* Set Address Space Control Fast */
|
|
/* Set Address Space Control Fast */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
potential_page_fault(s);
|
|
potential_page_fault(s);
|
|
gen_helper_sacf(cpu_env, tmp);
|
|
gen_helper_sacf(cpu_env, tmp);
|
|
tcg_temp_free_i64(tmp);
|
|
tcg_temp_free_i64(tmp);
|
|
/* addressing mode has changed, so end the block */
|
|
/* addressing mode has changed, so end the block */
|
|
- s->pc += ilc * 2;
|
|
|
|
|
|
+ s->pc = s->next_pc;
|
|
update_psw_addr(s);
|
|
update_psw_addr(s);
|
|
s->is_jmp = DISAS_JUMP;
|
|
s->is_jmp = DISAS_JUMP;
|
|
break;
|
|
break;
|
|
case 0x7d: /* STSI D2,(B2) [S] */
|
|
case 0x7d: /* STSI D2,(B2) [S] */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp32_1 = load_reg32(0);
|
|
tmp32_1 = load_reg32(0);
|
|
@@ -2798,7 +2742,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0xb1: /* STFL D2(B2) [S] */
|
|
case 0xb1: /* STFL D2(B2) [S] */
|
|
/* Store Facility List (CPU features) at 200 */
|
|
/* Store Facility List (CPU features) at 200 */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
tmp2 = tcg_const_i64(0xc0000000);
|
|
tmp2 = tcg_const_i64(0xc0000000);
|
|
tmp = tcg_const_i64(200);
|
|
tmp = tcg_const_i64(200);
|
|
tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
|
|
tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
|
|
@@ -2807,7 +2751,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0xb2: /* LPSWE D2(B2) [S] */
|
|
case 0xb2: /* LPSWE D2(B2) [S] */
|
|
/* Load PSW Extended */
|
|
/* Load PSW Extended */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp2 = tcg_temp_new_i64();
|
|
tmp2 = tcg_temp_new_i64();
|
|
@@ -2824,7 +2768,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
break;
|
|
break;
|
|
case 0x20: /* SERVC R1,R2 [RRE] */
|
|
case 0x20: /* SERVC R1,R2 [RRE] */
|
|
/* SCLP Service call (PV hypercall) */
|
|
/* SCLP Service call (PV hypercall) */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
potential_page_fault(s);
|
|
potential_page_fault(s);
|
|
tmp32_1 = load_reg32(r2);
|
|
tmp32_1 = load_reg32(r2);
|
|
tmp = load_reg(r1);
|
|
tmp = load_reg(r1);
|
|
@@ -2836,7 +2780,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
|
#endif
|
|
#endif
|
|
default:
|
|
default:
|
|
LOG_DISAS("illegal b2 operation 0x%x\n", op);
|
|
LOG_DISAS("illegal b2 operation 0x%x\n", op);
|
|
- gen_illegal_opcode(env, s, ilc);
|
|
|
|
|
|
+ gen_illegal_opcode(s);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -3112,7 +3056,7 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
LOG_DISAS("illegal b3 operation 0x%x\n", op);
|
|
LOG_DISAS("illegal b3 operation 0x%x\n", op);
|
|
- gen_illegal_opcode(env, s, 2);
|
|
|
|
|
|
+ gen_illegal_opcode(s);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3419,7 +3363,7 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
LOG_DISAS("illegal b9 operation 0x%x\n", op);
|
|
LOG_DISAS("illegal b9 operation 0x%x\n", op);
|
|
- gen_illegal_opcode(env, s, 2);
|
|
|
|
|
|
+ gen_illegal_opcode(s);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -3525,7 +3469,7 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
LOG_DISAS("illegal c0 operation 0x%x\n", op);
|
|
LOG_DISAS("illegal c0 operation 0x%x\n", op);
|
|
- gen_illegal_opcode(env, s, 3);
|
|
|
|
|
|
+ gen_illegal_opcode(s);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -3559,7 +3503,7 @@ static void disas_c2(CPUS390XState *env, DisasContext *s, int op, int r1,
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
LOG_DISAS("illegal c2 operation 0x%x\n", op);
|
|
LOG_DISAS("illegal c2 operation 0x%x\n", op);
|
|
- gen_illegal_opcode(env, s, 3);
|
|
|
|
|
|
+ gen_illegal_opcode(s);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -3589,14 +3533,11 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
|
uint64_t insn;
|
|
uint64_t insn;
|
|
int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
|
|
int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
|
|
TCGv_i32 vl;
|
|
TCGv_i32 vl;
|
|
- int ilc;
|
|
|
|
int l1;
|
|
int l1;
|
|
|
|
|
|
opc = cpu_ldub_code(env, s->pc);
|
|
opc = cpu_ldub_code(env, s->pc);
|
|
LOG_DISAS("opc 0x%x\n", opc);
|
|
LOG_DISAS("opc 0x%x\n", opc);
|
|
|
|
|
|
- ilc = get_ilc(opc);
|
|
|
|
-
|
|
|
|
switch (opc) {
|
|
switch (opc) {
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
case 0x01: /* SAM */
|
|
case 0x01: /* SAM */
|
|
@@ -3649,15 +3590,13 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
|
update_psw_addr(s);
|
|
update_psw_addr(s);
|
|
gen_op_calc_cc(s);
|
|
gen_op_calc_cc(s);
|
|
tmp32_1 = tcg_const_i32(i);
|
|
tmp32_1 = tcg_const_i32(i);
|
|
- tmp32_2 = tcg_const_i32(ilc * 2);
|
|
|
|
- tmp32_3 = tcg_const_i32(EXCP_SVC);
|
|
|
|
|
|
+ tmp32_2 = tcg_const_i32(s->next_pc - s->pc);
|
|
tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, int_svc_code));
|
|
tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, int_svc_code));
|
|
- tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilc));
|
|
|
|
- gen_helper_exception(cpu_env, tmp32_3);
|
|
|
|
|
|
+ tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilen));
|
|
|
|
+ gen_exception(EXCP_SVC);
|
|
s->is_jmp = DISAS_EXCP;
|
|
s->is_jmp = DISAS_EXCP;
|
|
tcg_temp_free_i32(tmp32_1);
|
|
tcg_temp_free_i32(tmp32_1);
|
|
tcg_temp_free_i32(tmp32_2);
|
|
tcg_temp_free_i32(tmp32_2);
|
|
- tcg_temp_free_i32(tmp32_3);
|
|
|
|
break;
|
|
break;
|
|
case 0xd: /* BASR R1,R2 [RR] */
|
|
case 0xd: /* BASR R1,R2 [RR] */
|
|
insn = ld_code2(env, s->pc);
|
|
insn = ld_code2(env, s->pc);
|
|
@@ -4148,7 +4087,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
case 0x80: /* SSM D2(B2) [S] */
|
|
case 0x80: /* SSM D2(B2) [S] */
|
|
/* Set System Mask */
|
|
/* Set System Mask */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
insn = ld_code4(env, s->pc);
|
|
insn = ld_code4(env, s->pc);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
@@ -4164,7 +4103,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
|
break;
|
|
break;
|
|
case 0x82: /* LPSW D2(B2) [S] */
|
|
case 0x82: /* LPSW D2(B2) [S] */
|
|
/* Load PSW */
|
|
/* Load PSW */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
insn = ld_code4(env, s->pc);
|
|
insn = ld_code4(env, s->pc);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
@@ -4184,7 +4123,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
|
break;
|
|
break;
|
|
case 0x83: /* DIAG R1,R3,D2 [RS] */
|
|
case 0x83: /* DIAG R1,R3,D2 [RS] */
|
|
/* Diagnose call (KVM hypercall) */
|
|
/* Diagnose call (KVM hypercall) */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
potential_page_fault(s);
|
|
potential_page_fault(s);
|
|
insn = ld_code4(env, s->pc);
|
|
insn = ld_code4(env, s->pc);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
@@ -4402,7 +4341,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
case 0xac: /* STNSM D1(B1),I2 [SI] */
|
|
case 0xac: /* STNSM D1(B1),I2 [SI] */
|
|
case 0xad: /* STOSM D1(B1),I2 [SI] */
|
|
case 0xad: /* STOSM D1(B1),I2 [SI] */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
insn = ld_code4(env, s->pc);
|
|
insn = ld_code4(env, s->pc);
|
|
tmp = decode_si(s, insn, &i2, &b1, &d1);
|
|
tmp = decode_si(s, insn, &i2, &b1, &d1);
|
|
tmp2 = tcg_temp_new_i64();
|
|
tmp2 = tcg_temp_new_i64();
|
|
@@ -4418,7 +4357,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
|
tcg_temp_free_i64(tmp2);
|
|
tcg_temp_free_i64(tmp2);
|
|
break;
|
|
break;
|
|
case 0xae: /* SIGP R1,R3,D2(B2) [RS] */
|
|
case 0xae: /* SIGP R1,R3,D2(B2) [RS] */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
insn = ld_code4(env, s->pc);
|
|
insn = ld_code4(env, s->pc);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
@@ -4432,7 +4371,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
|
tcg_temp_free_i32(tmp32_1);
|
|
tcg_temp_free_i32(tmp32_1);
|
|
break;
|
|
break;
|
|
case 0xb1: /* LRA R1,D2(X2, B2) [RX] */
|
|
case 0xb1: /* LRA R1,D2(X2, B2) [RX] */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
insn = ld_code4(env, s->pc);
|
|
insn = ld_code4(env, s->pc);
|
|
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
|
|
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
|
|
tmp32_1 = tcg_const_i32(r1);
|
|
tmp32_1 = tcg_const_i32(r1);
|
|
@@ -4476,7 +4415,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
case 0xb6: /* STCTL R1,R3,D2(B2) [RS] */
|
|
case 0xb6: /* STCTL R1,R3,D2(B2) [RS] */
|
|
/* Store Control */
|
|
/* Store Control */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
insn = ld_code4(env, s->pc);
|
|
insn = ld_code4(env, s->pc);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
@@ -4490,7 +4429,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
|
break;
|
|
break;
|
|
case 0xb7: /* LCTL R1,R3,D2(B2) [RS] */
|
|
case 0xb7: /* LCTL R1,R3,D2(B2) [RS] */
|
|
/* Load Control */
|
|
/* Load Control */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
insn = ld_code4(env, s->pc);
|
|
insn = ld_code4(env, s->pc);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
tmp = get_address(s, 0, b2, d2);
|
|
@@ -4674,7 +4613,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
case 0xda: /* MVCP D1(R1,B1),D2(B2),R3 [SS] */
|
|
case 0xda: /* MVCP D1(R1,B1),D2(B2),R3 [SS] */
|
|
case 0xdb: /* MVCS D1(R1,B1),D2(B2),R3 [SS] */
|
|
case 0xdb: /* MVCS D1(R1,B1),D2(B2),R3 [SS] */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
potential_page_fault(s);
|
|
potential_page_fault(s);
|
|
insn = ld_code6(env, s->pc);
|
|
insn = ld_code6(env, s->pc);
|
|
r1 = (insn >> 36) & 0xf;
|
|
r1 = (insn >> 36) & 0xf;
|
|
@@ -4712,7 +4651,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
case 0xe5:
|
|
case 0xe5:
|
|
/* Test Protection */
|
|
/* Test Protection */
|
|
- check_privileged(env, s, ilc);
|
|
|
|
|
|
+ check_privileged(s);
|
|
insn = ld_code6(env, s->pc);
|
|
insn = ld_code6(env, s->pc);
|
|
debug_insn(insn);
|
|
debug_insn(insn);
|
|
disas_e5(env, s, insn);
|
|
disas_e5(env, s, insn);
|
|
@@ -4742,7 +4681,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
|
|
qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
|
|
- gen_illegal_opcode(env, s, ilc);
|
|
|
|
|
|
+ gen_illegal_opcode(s);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -5273,19 +5212,22 @@ static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s,
|
|
DisasFields *f)
|
|
DisasFields *f)
|
|
{
|
|
{
|
|
uint64_t insn, pc = s->pc;
|
|
uint64_t insn, pc = s->pc;
|
|
- int op, op2;
|
|
|
|
|
|
+ int op, op2, ilen;
|
|
const DisasInsn *info;
|
|
const DisasInsn *info;
|
|
|
|
|
|
insn = ld_code2(env, pc);
|
|
insn = ld_code2(env, pc);
|
|
op = (insn >> 8) & 0xff;
|
|
op = (insn >> 8) & 0xff;
|
|
- switch (get_ilc(op)) {
|
|
|
|
- case 1:
|
|
|
|
|
|
+ ilen = get_ilen(op);
|
|
|
|
+ s->next_pc = s->pc + ilen;
|
|
|
|
+
|
|
|
|
+ switch (ilen) {
|
|
|
|
+ case 2:
|
|
insn = insn << 48;
|
|
insn = insn << 48;
|
|
break;
|
|
break;
|
|
- case 2:
|
|
|
|
|
|
+ case 4:
|
|
insn = ld_code4(env, pc) << 32;
|
|
insn = ld_code4(env, pc) << 32;
|
|
break;
|
|
break;
|
|
- case 3:
|
|
|
|
|
|
+ case 6:
|
|
insn = (insn << 48) | (ld_code4(env, pc + 2) << 16);
|
|
insn = (insn << 48) | (ld_code4(env, pc + 2) << 16);
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
@@ -5361,9 +5303,6 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
|
|
|
|
|
|
insn = extract_insn(env, s, &f);
|
|
insn = extract_insn(env, s, &f);
|
|
|
|
|
|
- /* Instruction length is encoded in the opcode */
|
|
|
|
- s->next_pc = s->pc + get_ilc(f.op) * 2;
|
|
|
|
-
|
|
|
|
/* If not found, try the old interpreter. This includes ILLOPC. */
|
|
/* If not found, try the old interpreter. This includes ILLOPC. */
|
|
if (insn == NULL) {
|
|
if (insn == NULL) {
|
|
disas_s390_insn(env, s);
|
|
disas_s390_insn(env, s);
|
|
@@ -5452,6 +5391,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
|
|
int num_insns, max_insns;
|
|
int num_insns, max_insns;
|
|
CPUBreakpoint *bp;
|
|
CPUBreakpoint *bp;
|
|
ExitStatus status;
|
|
ExitStatus status;
|
|
|
|
+ bool do_debug;
|
|
|
|
|
|
pc_start = tb->pc;
|
|
pc_start = tb->pc;
|
|
|
|
|
|
@@ -5463,7 +5403,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
|
|
dc.tb = tb;
|
|
dc.tb = tb;
|
|
dc.pc = pc_start;
|
|
dc.pc = pc_start;
|
|
dc.cc_op = CC_OP_DYNAMIC;
|
|
dc.cc_op = CC_OP_DYNAMIC;
|
|
- dc.singlestep_enabled = env->singlestep_enabled;
|
|
|
|
|
|
+ do_debug = dc.singlestep_enabled = env->singlestep_enabled;
|
|
dc.is_jmp = DISAS_NEXT;
|
|
dc.is_jmp = DISAS_NEXT;
|
|
|
|
|
|
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
|
|
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
|
|
@@ -5479,14 +5419,6 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
|
|
gen_icount_start();
|
|
gen_icount_start();
|
|
|
|
|
|
do {
|
|
do {
|
|
- if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
|
|
|
|
- QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
|
|
|
|
- if (bp->pc == dc.pc) {
|
|
|
|
- gen_debug(&dc);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
if (search_pc) {
|
|
if (search_pc) {
|
|
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
|
|
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
|
|
if (lj < j) {
|
|
if (lj < j) {
|
|
@@ -5508,7 +5440,19 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
|
|
tcg_gen_debug_insn_start(dc.pc);
|
|
tcg_gen_debug_insn_start(dc.pc);
|
|
}
|
|
}
|
|
|
|
|
|
- status = translate_one(env, &dc);
|
|
|
|
|
|
+ status = NO_EXIT;
|
|
|
|
+ if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
|
|
|
|
+ QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
|
|
|
|
+ if (bp->pc == dc.pc) {
|
|
|
|
+ status = EXIT_PC_STALE;
|
|
|
|
+ do_debug = true;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (status == NO_EXIT) {
|
|
|
|
+ status = translate_one(env, &dc);
|
|
|
|
+ }
|
|
|
|
|
|
/* If we reach a page boundary, are single stepping,
|
|
/* If we reach a page boundary, are single stepping,
|
|
or exhaust instruction count, stop generation. */
|
|
or exhaust instruction count, stop generation. */
|
|
@@ -5541,8 +5485,8 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
|
|
so make sure the cc op type is in env */
|
|
so make sure the cc op type is in env */
|
|
gen_op_set_cc_op(&dc);
|
|
gen_op_set_cc_op(&dc);
|
|
}
|
|
}
|
|
- if (env->singlestep_enabled) {
|
|
|
|
- gen_debug(&dc);
|
|
|
|
|
|
+ if (do_debug) {
|
|
|
|
+ gen_exception(EXCP_DEBUG);
|
|
} else {
|
|
} else {
|
|
/* Generate the return instruction */
|
|
/* Generate the return instruction */
|
|
tcg_gen_exit_tb(0);
|
|
tcg_gen_exit_tb(0);
|