Make the user path more like the system path. Prepare for more kinds of runtime exceptions. Compute ILC from S->NEXT_PC, rather than passing it around.
Signed-off-by: Richard Henderson <r...@twiddle.net> --- linux-user/main.c | 133 +++++++++++++++++---------- target-s390x/cpu.h | 11 --- target-s390x/misc_helper.c | 10 ++- target-s390x/translate.c | 220 +++++++++++++++++---------------------------- 4 files changed, 174 insertions(+), 200 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 1a1c661..8f6f39b 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2935,71 +2935,108 @@ void cpu_loop(CPUAlphaState *env) #ifdef TARGET_S390X void cpu_loop(CPUS390XState *env) { - int trapnr; + int trapnr, n, sig; target_siginfo_t info; + target_ulong addr; while (1) { - trapnr = cpu_s390x_exec (env); - + trapnr = cpu_s390x_exec(env); switch (trapnr) { case EXCP_INTERRUPT: - /* just indicate that signals should be handled asap */ + /* Just indicate that signals should be handled asap. */ break; - case EXCP_DEBUG: - { - int sig; - sig = gdb_handlesig (env, TARGET_SIGTRAP); - if (sig) { - info.si_signo = sig; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, &info); - } + case EXCP_SVC: + n = env->int_svc_code; + if (!n) { + /* syscalls > 255 */ + n = env->regs[1]; } + env->psw.addr += env->int_svc_ilc; + env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3], + env->regs[4], env->regs[5], + env->regs[6], env->regs[7], 0, 0); break; - case EXCP_SVC: - { - int n = env->int_svc_code; - if (!n) { - /* syscalls > 255 */ - n = env->regs[1]; - } - env->psw.addr += env->int_svc_ilc; - env->regs[2] = do_syscall(env, n, - env->regs[2], - env->regs[3], - env->regs[4], - env->regs[5], - env->regs[6], - env->regs[7], - 0, 0); + + case EXCP_DEBUG: + sig = gdb_handlesig(env, TARGET_SIGTRAP); + if (sig) { + n = TARGET_TRAP_BRKPT; + goto do_signal_pc; } break; - case EXCP_ADDR: - { - info.si_signo = SIGSEGV; - info.si_errno = 0; + case EXCP_PGM: + n = env->int_pgm_code; + switch (n) { + case PGM_OPERATION: + case PGM_PRIVILEGED: + sig = SIGILL; + n = TARGET_ILL_ILLOPC; + goto do_signal_pc; + case PGM_PROTECTION: + case PGM_ADDRESSING: + sig = SIGSEGV; /* XXX: check env->error_code */ - info.si_code = TARGET_SEGV_MAPERR; - info._sifields._sigfault._addr = env->__excp_addr; - queue_signal(env, info.si_signo, &info); + n = TARGET_SEGV_MAPERR; + addr = env->__excp_addr; + goto do_signal; + case PGM_EXECUTE: + case PGM_SPECIFICATION: + case PGM_DATA: + case PGM_SPECIAL_OP: + case PGM_OPERAND: + sig = SIGILL; + n = TARGET_ILL_ILLOPN; + goto do_signal_pc; + case PGM_FIXPT_OVERFLOW: + sig = SIGFPE; + n = TARGET_FPE_INTOVF; + goto do_signal_pc; + case PGM_FIXPT_DIVIDE: + sig = SIGFPE; + n = TARGET_FPE_INTDIV; + goto do_signal_pc; + case PGM_HFP_EXP_OVERFLOW: + sig = SIGFPE; + n = TARGET_FPE_FLTOVF; + goto do_signal_pc; + case PGM_HFP_EXP_UNDERFLOW: + sig = SIGFPE; + n = TARGET_FPE_FLTUND; + goto do_signal_pc; + case PGM_HFP_SIGNIFICANCE: + sig = SIGFPE; + n = TARGET_FPE_FLTRES; + goto do_signal_pc; + case PGM_HFP_DIVIDE: + sig = SIGFPE; + n = TARGET_FPE_FLTDIV; + goto do_signal_pc; + case PGM_HFP_SQRT: + sig = SIGFPE; + n = TARGET_FPE_FLTINV; + goto do_signal_pc; + default: + fprintf(stderr, "Unhandled program exception: %#x\n", n); + cpu_dump_state(env, stderr, fprintf, 0); + exit(1); } break; - case EXCP_SPEC: - { - fprintf(stderr,"specification exception insn 0x%08x%04x\n", ldl(env->psw.addr), lduw(env->psw.addr + 4)); - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPC; - info._sifields._sigfault._addr = env->__excp_addr; - queue_signal(env, info.si_signo, &info); - } + + do_signal_pc: + addr = env->psw.addr; + do_signal: + info.si_signo = sig; + info.si_errno = 0; + info.si_code = n; + info._sifields._sigfault._addr = addr; + queue_signal(env, info.si_signo, &info); break; + default: - printf ("Unhandled trap: 0x%x\n", trapnr); + fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr); cpu_dump_state(env, stderr, fprintf, 0); - exit (1); + exit(1); } process_pending_signals (env); } diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 471fb91..17829b5 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -352,21 +352,10 @@ static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls) #include "exec-all.h" -#ifdef CONFIG_USER_ONLY - -#define EXCP_OPEX 1 /* operation exception (sigill) */ -#define EXCP_SVC 2 /* supervisor call (syscall) */ -#define EXCP_ADDR 5 /* addressing exception */ -#define EXCP_SPEC 6 /* specification exception */ - -#else - #define EXCP_EXT 1 /* external interrupt */ #define EXCP_SVC 2 /* supervisor call (syscall) */ #define EXCP_PGM 3 /* program interruption */ -#endif /* CONFIG_USER_ONLY */ - #define INTERRUPT_EXT (1 << 0) #define INTERRUPT_TOD (1 << 1) #define INTERRUPT_CPUTIMER (1 << 2) diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index f405b97..1502f15 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -86,10 +86,12 @@ void do_interrupt(CPUS390XState *env) int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong address, int rw, int mmu_idx) { - /* fprintf(stderr, "%s: address 0x%lx rw %d mmu_idx %d\n", - __func__, address, rw, mmu_idx); */ - env->exception_index = EXCP_ADDR; - /* FIXME: find out how this works on a real machine */ + env->exception_index = EXCP_PGM; + env->int_pgm_code = PGM_PROTECTION; + /* A real machine puts the address in LowCore, which the kernel + helpfully interprets for us. Since we've nothing similar + within the userland address space, invent something for use + within cpu_loop. */ env->__excp_addr = address; return 1; } diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 996d786..70e5d87 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -18,7 +18,6 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ -/* #define DEBUG_ILLEGAL_INSTRUCTIONS */ /* #define DEBUG_INLINE_BRANCHES */ #define S390X_DEBUG_DISAS /* #define S390X_DEBUG_DISAS_VERBOSE */ @@ -336,103 +335,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(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); tcg_temp_free_i32(tmp); - s->is_jmp = DISAS_EXCP; } -#else /* CONFIG_USER_ONLY */ - -static void debug_print_inst(DisasContext *s, int ilc) -{ -#ifdef DEBUG_ILLEGAL_INSTRUCTIONS - uint64_t inst = 0; - - switch (ilc & 3) { - case 1: - inst = ld_code2(s->pc); - break; - case 2: - inst = ld_code4(s->pc); - break; - case 3: - inst = ld_code6(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(DisasContext *s, int ilc, int code) +static void gen_program_exception(DisasContext *s, int code) { TCGv_i32 tmp; - debug_print_inst(s, ilc); - - /* remember what pgm exeption this was */ + /* Remember what pgm exeption this was. */ tmp = tcg_const_i32(code); tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code)); tcg_temp_free_i32(tmp); - tmp = tcg_const_i32(ilc); + tmp = tcg_const_i32(s->next_pc - s->pc); tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilc)); tcg_temp_free_i32(tmp); - /* advance past instruction */ - s->pc += (ilc * 2); + /* Advance past instruction. */ + s->pc = s->next_pc; update_psw_addr(s); - /* save off cc */ + /* Save off cc. */ 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; } - -static void gen_illegal_opcode(DisasContext *s, int ilc) -{ - gen_program_exception(s, ilc, PGM_SPECIFICATION); -} - -static void gen_privileged_exception(DisasContext *s, int ilc) +static inline void gen_illegal_opcode(DisasContext *s) { - gen_program_exception(s, ilc, PGM_PRIVILEGED); + gen_program_exception(s, PGM_SPECIFICATION); } -static void check_privileged(DisasContext *s, int ilc) +static inline void check_privileged(DisasContext *s) { if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) { - gen_privileged_exception(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) { TCGv_i64 tmp; @@ -1762,7 +1710,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2) break; default: LOG_DISAS("illegal e3 operation 0x%x\n", op); - gen_illegal_opcode(s, 3); + gen_illegal_opcode(s); break; } tcg_temp_free_i64(addr); @@ -1787,7 +1735,7 @@ static void disas_e5(DisasContext* s, uint64_t insn) break; default: LOG_DISAS("illegal e5 operation 0x%x\n", op); - gen_illegal_opcode(s, 3); + gen_illegal_opcode(s); break; } @@ -1801,7 +1749,6 @@ static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2) TCGv_i64 tmp, tmp2, tmp3, tmp4; TCGv_i32 tmp32_1, tmp32_2; int i, stm_len; - int ilc = 3; LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n", op, r1, r3, b2, d2); @@ -1939,7 +1886,7 @@ do_mh: #ifndef CONFIG_USER_ONLY case 0x2f: /* LCTLG R1,R3,D2(B2) [RSE] */ /* Load Control */ - check_privileged(s, ilc); + check_privileged(s); tmp = get_address(s, 0, b2, d2); tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); @@ -1951,7 +1898,7 @@ do_mh: break; case 0x25: /* STCTG R1,R3,D2(B2) [RSE] */ /* Store Control */ - check_privileged(s, ilc); + check_privileged(s); tmp = get_address(s, 0, b2, d2); tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); @@ -2028,7 +1975,7 @@ do_mh: break; default: LOG_DISAS("illegal eb operation 0x%x\n", op); - gen_illegal_opcode(s, ilc); + gen_illegal_opcode(s); break; } } @@ -2148,7 +2095,7 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2, break; default: LOG_DISAS("illegal ed operation 0x%x\n", op); - gen_illegal_opcode(s, 3); + gen_illegal_opcode(s); return; } tcg_temp_free_i32(tmp_r1); @@ -2304,7 +2251,7 @@ static void disas_a5(DisasContext *s, int op, int r1, int i2) break; default: LOG_DISAS("illegal a5 operation 0x%x\n", op); - gen_illegal_opcode(s, 2); + gen_illegal_opcode(s); return; } } @@ -2441,7 +2388,7 @@ static void disas_a7(DisasContext *s, int op, int r1, int i2) break; default: LOG_DISAS("illegal a7 operation 0x%x\n", op); - gen_illegal_opcode(s, 2); + gen_illegal_opcode(s); return; } } @@ -2451,7 +2398,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) TCGv_i64 tmp, tmp2, tmp3; TCGv_i32 tmp32_1, tmp32_2, tmp32_3; int r1, r2; - int ilc = 2; #ifndef CONFIG_USER_ONLY int r3, d2, b2; #endif @@ -2545,7 +2491,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) #ifndef CONFIG_USER_ONLY case 0x02: /* STIDP D2(B2) [S] */ /* Store CPU ID */ - check_privileged(s, ilc); + check_privileged(s); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2554,7 +2500,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x04: /* SCK D2(B2) [S] */ /* Set Clock */ - check_privileged(s, ilc); + check_privileged(s); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2573,7 +2519,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x06: /* SCKC D2(B2) [S] */ /* Set Clock Comparator */ - check_privileged(s, ilc); + check_privileged(s); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2582,7 +2528,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x07: /* STCKC D2(B2) [S] */ /* Store Clock Comparator */ - check_privileged(s, ilc); + check_privileged(s); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2591,7 +2537,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x08: /* SPT D2(B2) [S] */ /* Set CPU Timer */ - check_privileged(s, ilc); + check_privileged(s); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2600,7 +2546,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x09: /* STPT D2(B2) [S] */ /* Store CPU Timer */ - check_privileged(s, ilc); + check_privileged(s); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2609,7 +2555,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x0a: /* SPKA D2(B2) [S] */ /* Set PSW Key from Address */ - check_privileged(s, ilc); + check_privileged(s); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp2 = tcg_temp_new_i64(); @@ -2621,12 +2567,12 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x0d: /* PTLB [S] */ /* Purge TLB */ - check_privileged(s, ilc); + check_privileged(s); gen_helper_ptlb(cpu_env); break; case 0x10: /* SPX D2(B2) [S] */ /* Set Prefix Register */ - check_privileged(s, ilc); + check_privileged(s); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2635,7 +2581,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x11: /* STPX D2(B2) [S] */ /* Store Prefix */ - check_privileged(s, ilc); + check_privileged(s); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp2 = tcg_temp_new_i64(); @@ -2646,7 +2592,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x12: /* STAP D2(B2) [S] */ /* Store CPU Address */ - check_privileged(s, ilc); + check_privileged(s); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp2 = tcg_temp_new_i64(); @@ -2660,7 +2606,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x21: /* IPTE R1,R2 [RRE] */ /* Invalidate PTE */ - check_privileged(s, ilc); + check_privileged(s); r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; tmp = load_reg(r1); @@ -2671,7 +2617,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x29: /* ISKE R1,R2 [RRE] */ /* Insert Storage Key Extended */ - check_privileged(s, ilc); + check_privileged(s); r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; tmp = load_reg(r2); @@ -2683,7 +2629,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x2a: /* RRBE R1,R2 [RRE] */ /* Set Storage Key Extended */ - check_privileged(s, ilc); + check_privileged(s); r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; tmp32_1 = load_reg32(r1); @@ -2695,7 +2641,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x2b: /* SSKE R1,R2 [RRE] */ /* Set Storage Key Extended */ - check_privileged(s, ilc); + check_privileged(s); r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; tmp32_1 = load_reg32(r1); @@ -2706,12 +2652,12 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x34: /* STCH ? */ /* Store Subchannel */ - check_privileged(s, ilc); + check_privileged(s); gen_op_movi_cc(s, 3); break; case 0x46: /* STURA R1,R2 [RRE] */ /* Store Using Real Address */ - check_privileged(s, ilc); + check_privileged(s); r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; tmp32_1 = load_reg32(r1); @@ -2723,7 +2669,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x50: /* CSP R1,R2 [RRE] */ /* Compare And Swap And Purge */ - check_privileged(s, ilc); + check_privileged(s); r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; tmp32_1 = tcg_const_i32(r1); @@ -2735,7 +2681,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x5f: /* CHSC ? */ /* Channel Subsystem Call */ - check_privileged(s, ilc); + check_privileged(s); gen_op_movi_cc(s, 3); break; case 0x78: /* STCKE D2(B2) [S] */ @@ -2749,19 +2695,19 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x79: /* SACF D2(B2) [S] */ /* Store Clock Extended */ - check_privileged(s, ilc); + check_privileged(s); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); gen_helper_sacf(cpu_env, tmp); tcg_temp_free_i64(tmp); /* addressing mode has changed, so end the block */ - s->pc += ilc * 2; + s->pc = s->next_pc; update_psw_addr(s); s->is_jmp = DISAS_EXCP; break; case 0x7d: /* STSI D2,(B2) [S] */ - check_privileged(s, ilc); + check_privileged(s); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp32_1 = load_reg32(0); @@ -2787,7 +2733,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0xb1: /* STFL D2(B2) [S] */ /* Store Facility List (CPU features) at 200 */ - check_privileged(s, ilc); + check_privileged(s); tmp2 = tcg_const_i64(0xc0000000); tmp = tcg_const_i64(200); tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s)); @@ -2796,7 +2742,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0xb2: /* LPSWE D2(B2) [S] */ /* Load PSW Extended */ - check_privileged(s, ilc); + check_privileged(s); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp2 = tcg_temp_new_i64(); @@ -2813,7 +2759,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x20: /* SERVC R1,R2 [RRE] */ /* SCLP Service call (PV hypercall) */ - check_privileged(s, ilc); + check_privileged(s); potential_page_fault(s); tmp32_1 = load_reg32(r2); tmp = load_reg(r1); @@ -2825,7 +2771,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) #endif default: LOG_DISAS("illegal b2 operation 0x%x\n", op); - gen_illegal_opcode(s, ilc); + gen_illegal_opcode(s); break; } } @@ -3100,7 +3046,7 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) break; default: LOG_DISAS("illegal b3 operation 0x%x\n", op); - gen_illegal_opcode(s, 2); + gen_illegal_opcode(s); break; } @@ -3406,7 +3352,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2) break; default: LOG_DISAS("illegal b9 operation 0x%x\n", op); - gen_illegal_opcode(s, 2); + gen_illegal_opcode(s); break; } } @@ -3507,7 +3453,7 @@ static void disas_c0(DisasContext *s, int op, int r1, int i2) break; default: LOG_DISAS("illegal c0 operation 0x%x\n", op); - gen_illegal_opcode(s, 3); + gen_illegal_opcode(s); break; } } @@ -3540,7 +3486,7 @@ static void disas_c2(DisasContext *s, int op, int r1, int i2) break; default: LOG_DISAS("illegal c2 operation 0x%x\n", op); - gen_illegal_opcode(s, 3); + gen_illegal_opcode(s); break; } } @@ -3570,14 +3516,11 @@ static void disas_s390_insn(DisasContext *s) uint64_t insn; int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b; TCGv_i32 vl; - int ilc; int l1; opc = cpu_ldub_code(cpu_single_env, s->pc); LOG_DISAS("opc 0x%x\n", opc); - ilc = get_ilc(opc); - switch (opc) { #ifndef CONFIG_USER_ONLY case 0x01: /* SAM */ @@ -3630,15 +3573,13 @@ static void disas_s390_insn(DisasContext *s) update_psw_addr(s); gen_op_calc_cc(s); 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_2, cpu_env, offsetof(CPUS390XState, int_svc_ilc)); - gen_helper_exception(cpu_env, tmp32_3); + gen_exception(EXCP_SVC); s->is_jmp = DISAS_EXCP; tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); - tcg_temp_free_i32(tmp32_3); break; case 0xd: /* BASR R1,R2 [RR] */ insn = ld_code2(s->pc); @@ -4129,7 +4070,7 @@ static void disas_s390_insn(DisasContext *s) #ifndef CONFIG_USER_ONLY case 0x80: /* SSM D2(B2) [S] */ /* Set System Mask */ - check_privileged(s, ilc); + check_privileged(s); insn = ld_code4(s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); @@ -4145,7 +4086,7 @@ static void disas_s390_insn(DisasContext *s) break; case 0x82: /* LPSW D2(B2) [S] */ /* Load PSW */ - check_privileged(s, ilc); + check_privileged(s); insn = ld_code4(s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); @@ -4163,7 +4104,7 @@ static void disas_s390_insn(DisasContext *s) break; case 0x83: /* DIAG R1,R3,D2 [RS] */ /* Diagnose call (KVM hypercall) */ - check_privileged(s, ilc); + check_privileged(s); potential_page_fault(s); insn = ld_code4(s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); @@ -4381,7 +4322,7 @@ static void disas_s390_insn(DisasContext *s) #ifndef CONFIG_USER_ONLY case 0xac: /* STNSM D1(B1),I2 [SI] */ case 0xad: /* STOSM D1(B1),I2 [SI] */ - check_privileged(s, ilc); + check_privileged(s); insn = ld_code4(s->pc); tmp = decode_si(s, insn, &i2, &b1, &d1); tmp2 = tcg_temp_new_i64(); @@ -4397,7 +4338,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; case 0xae: /* SIGP R1,R3,D2(B2) [RS] */ - check_privileged(s, ilc); + check_privileged(s); insn = ld_code4(s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); @@ -4411,7 +4352,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_1); break; case 0xb1: /* LRA R1,D2(X2, B2) [RX] */ - check_privileged(s, ilc); + check_privileged(s); insn = ld_code4(s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp32_1 = tcg_const_i32(r1); @@ -4455,7 +4396,7 @@ static void disas_s390_insn(DisasContext *s) #ifndef CONFIG_USER_ONLY case 0xb6: /* STCTL R1,R3,D2(B2) [RS] */ /* Store Control */ - check_privileged(s, ilc); + check_privileged(s); insn = ld_code4(s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); @@ -4469,7 +4410,7 @@ static void disas_s390_insn(DisasContext *s) break; case 0xb7: /* LCTL R1,R3,D2(B2) [RS] */ /* Load Control */ - check_privileged(s, ilc); + check_privileged(s); insn = ld_code4(s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); @@ -4653,7 +4594,7 @@ static void disas_s390_insn(DisasContext *s) #ifndef CONFIG_USER_ONLY case 0xda: /* MVCP D1(R1,B1),D2(B2),R3 [SS] */ case 0xdb: /* MVCS D1(R1,B1),D2(B2),R3 [SS] */ - check_privileged(s, ilc); + check_privileged(s); potential_page_fault(s); insn = ld_code6(s->pc); r1 = (insn >> 36) & 0xf; @@ -4691,7 +4632,7 @@ static void disas_s390_insn(DisasContext *s) #ifndef CONFIG_USER_ONLY case 0xe5: /* Test Protection */ - check_privileged(s, ilc); + check_privileged(s); insn = ld_code6(s->pc); debug_insn(insn); disas_e5(s, insn); @@ -4721,7 +4662,7 @@ static void disas_s390_insn(DisasContext *s) break; default: qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc); - gen_illegal_opcode(s, ilc); + gen_illegal_opcode(s); break; } } @@ -5430,6 +5371,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env, int num_insns, max_insns; CPUBreakpoint *bp; ExitStatus status; + bool do_debug; pc_start = tb->pc; @@ -5441,7 +5383,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env, dc.tb = tb; dc.pc = pc_start; 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; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; @@ -5457,14 +5399,6 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env, gen_icount_start(); 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) { j = gen_opc_ptr - gen_opc_buf; if (lj < j) { @@ -5486,7 +5420,19 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env, tcg_gen_debug_insn_start(dc.pc); } - status = translate_one(&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(&dc); + } /* If we reach a page boundary, are single stepping, or exhaust instruction count, stop generation. */ @@ -5519,8 +5465,8 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env, so make sure the cc op type is in env */ gen_op_set_cc_op(&dc); } - if (env->singlestep_enabled) { - gen_debug(&dc); + if (do_debug) { + gen_exception(EXCP_DEBUG); } else { /* Generate the return instruction */ tcg_gen_exit_tb(0); -- 1.7.11.4