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_ADDRESSING;
+ /* On real machines this value is dropped into LowMem. Since this
+ is userland, simply put this someplace that cpu_loop can find it. */
env->__excp_addr = address;
return 1;
}
/* Ensure to exit the TB after this call! */
static void trigger_pgm_exception(CPUS390XState *env, uint32_t code,
- uint32_t ilc)
+ uint32_t ilen)
{
env->exception_index = EXCP_PGM;
env->int_pgm_code = code;
- env->int_pgm_ilc = ilc;
+ env->int_pgm_ilen = ilen;
}
static int trans_bits(CPUS390XState *env, uint64_t mode)
static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
uint64_t mode)
{
- int ilc = ILC_LATER_INC_2;
+ int ilen = ILEN_LATER_INC;
int bits = trans_bits(env, mode) | 4;
DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
stq_phys(env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
- trigger_pgm_exception(env, PGM_PROTECTION, ilc);
+ trigger_pgm_exception(env, PGM_PROTECTION, ilen);
}
static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
uint32_t type, uint64_t asc, int rw)
{
- int ilc = ILC_LATER;
+ int ilen = ILEN_LATER;
int bits = trans_bits(env, asc);
+ /* Code accesses have an undefined ilc. */
if (rw == 2) {
- /* code has is undefined ilc */
- ilc = 2;
+ ilen = 2;
}
DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
stq_phys(env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
- trigger_pgm_exception(env, type, ilc);
+ trigger_pgm_exception(env, type, ilen);
}
static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
if (raddr > (ram_size + virtio_size)) {
DPRINTF("%s: aaddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__,
(uint64_t)aaddr, (uint64_t)ram_size);
- trigger_pgm_exception(env, PGM_ADDRESSING, ILC_LATER);
+ trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_LATER);
return 1;
}
lowcore = cpu_physical_memory_map(env->psa, &len, 1);
lowcore->svc_code = cpu_to_be16(env->int_svc_code);
- lowcore->svc_ilc = cpu_to_be16(env->int_svc_ilc);
+ lowcore->svc_ilen = cpu_to_be16(env->int_svc_ilen);
lowcore->svc_old_psw.mask = cpu_to_be64(get_psw_mask(env));
- lowcore->svc_old_psw.addr = cpu_to_be64(env->psw.addr + (env->int_svc_ilc));
+ lowcore->svc_old_psw.addr = cpu_to_be64(env->psw.addr + env->int_svc_ilen);
mask = be64_to_cpu(lowcore->svc_new_psw.mask);
addr = be64_to_cpu(lowcore->svc_new_psw.addr);
uint64_t mask, addr;
LowCore *lowcore;
hwaddr len = TARGET_PAGE_SIZE;
- int ilc = env->int_pgm_ilc;
+ int ilen = env->int_pgm_ilen;
- switch (ilc) {
- case ILC_LATER:
- ilc = get_ilc(cpu_ldub_code(env, env->psw.addr));
- break;
- case ILC_LATER_INC:
- ilc = get_ilc(cpu_ldub_code(env, env->psw.addr));
- env->psw.addr += ilc * 2;
+ switch (ilen) {
+ case ILEN_LATER:
+ ilen = get_ilen(cpu_ldub_code(env, env->psw.addr));
break;
- case ILC_LATER_INC_2:
- ilc = get_ilc(cpu_ldub_code(env, env->psw.addr)) * 2;
- env->psw.addr += ilc;
+ case ILEN_LATER_INC:
+ ilen = get_ilen(cpu_ldub_code(env, env->psw.addr));
+ env->psw.addr += ilen;
break;
+ default:
+ assert(ilen == 2 || ilen == 4 || ilen == 6);
}
- qemu_log_mask(CPU_LOG_INT, "%s: code=0x%x ilc=%d\n",
- __func__, env->int_pgm_code, ilc);
+ qemu_log_mask(CPU_LOG_INT, "%s: code=0x%x ilen=%d\n",
+ __func__, env->int_pgm_code, ilen);
lowcore = cpu_physical_memory_map(env->psa, &len, 1);
- lowcore->pgm_ilc = cpu_to_be16(ilc);
+ lowcore->pgm_ilen = cpu_to_be16(ilen);
lowcore->pgm_code = cpu_to_be16(env->int_pgm_code);
lowcore->program_old_psw.mask = cpu_to_be64(get_psw_mask(env));
lowcore->program_old_psw.addr = cpu_to_be64(env->psw.addr);
cpu_physical_memory_unmap(lowcore, len, 1, len);
DPRINTF("%s: %x %x %" PRIx64 " %" PRIx64 "\n", __func__,
- env->int_pgm_code, ilc, env->psw.mask,
+ env->int_pgm_code, ilen, env->psw.mask,
env->psw.addr);
load_psw(env, mask, addr);
* 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 */
}
}
-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);
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;
- debug_print_inst(env, 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);
- 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);
- /* 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(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)) {
- 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)
{
TCGv_i64 tmp;
break;
default:
LOG_DISAS("illegal e3 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 3);
+ gen_illegal_opcode(s);
break;
}
tcg_temp_free_i64(addr);
break;
default:
LOG_DISAS("illegal e5 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 3);
+ gen_illegal_opcode(s);
break;
}
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);
#ifndef CONFIG_USER_ONLY
case 0x2f: /* LCTLG R1,R3,D2(B2) [RSE] */
/* Load Control */
- check_privileged(env, s, ilc);
+ check_privileged(s);
tmp = get_address(s, 0, b2, d2);
tmp32_1 = tcg_const_i32(r1);
tmp32_2 = tcg_const_i32(r3);
break;
case 0x25: /* STCTG R1,R3,D2(B2) [RSE] */
/* Store Control */
- check_privileged(env, s, ilc);
+ check_privileged(s);
tmp = get_address(s, 0, b2, d2);
tmp32_1 = tcg_const_i32(r1);
tmp32_2 = tcg_const_i32(r3);
break;
default:
LOG_DISAS("illegal eb operation 0x%x\n", op);
- gen_illegal_opcode(env, s, ilc);
+ gen_illegal_opcode(s);
break;
}
}
break;
default:
LOG_DISAS("illegal ed operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 3);
+ gen_illegal_opcode(s);
return;
}
tcg_temp_free_i32(tmp_r1);
break;
default:
LOG_DISAS("illegal a5 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 2);
+ gen_illegal_opcode(s);
return;
}
}
break;
default:
LOG_DISAS("illegal a7 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 2);
+ gen_illegal_opcode(s);
return;
}
}
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
#ifndef CONFIG_USER_ONLY
case 0x02: /* STIDP D2(B2) [S] */
/* Store CPU ID */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
break;
case 0x04: /* SCK D2(B2) [S] */
/* Set Clock */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
break;
case 0x06: /* SCKC D2(B2) [S] */
/* Set Clock Comparator */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
break;
case 0x07: /* STCKC D2(B2) [S] */
/* Store Clock Comparator */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
break;
case 0x08: /* SPT D2(B2) [S] */
/* Set CPU Timer */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
break;
case 0x09: /* STPT D2(B2) [S] */
/* Store CPU Timer */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
break;
case 0x0a: /* SPKA D2(B2) [S] */
/* Set PSW Key from Address */
- check_privileged(env, 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();
break;
case 0x0d: /* PTLB [S] */
/* Purge TLB */
- check_privileged(env, s, ilc);
+ check_privileged(s);
gen_helper_ptlb(cpu_env);
break;
case 0x10: /* SPX D2(B2) [S] */
/* Set Prefix Register */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
break;
case 0x11: /* STPX D2(B2) [S] */
/* Store Prefix */
- check_privileged(env, 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();
break;
case 0x12: /* STAP D2(B2) [S] */
/* Store CPU Address */
- check_privileged(env, 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();
break;
case 0x21: /* IPTE R1,R2 [RRE] */
/* Invalidate PTE */
- check_privileged(env, s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp = load_reg(r1);
break;
case 0x29: /* ISKE R1,R2 [RRE] */
/* Insert Storage Key Extended */
- check_privileged(env, s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp = load_reg(r2);
break;
case 0x2a: /* RRBE R1,R2 [RRE] */
/* Set Storage Key Extended */
- check_privileged(env, s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp32_1 = load_reg32(r1);
break;
case 0x2b: /* SSKE R1,R2 [RRE] */
/* Set Storage Key Extended */
- check_privileged(env, s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp32_1 = load_reg32(r1);
break;
case 0x34: /* STCH ? */
/* Store Subchannel */
- check_privileged(env, s, ilc);
+ check_privileged(s);
gen_op_movi_cc(s, 3);
break;
case 0x46: /* STURA R1,R2 [RRE] */
/* Store Using Real Address */
- check_privileged(env, s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp32_1 = load_reg32(r1);
break;
case 0x50: /* CSP R1,R2 [RRE] */
/* Compare And Swap And Purge */
- check_privileged(env, s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp32_1 = tcg_const_i32(r1);
break;
case 0x5f: /* CHSC ? */
/* Channel Subsystem Call */
- check_privileged(env, s, ilc);
+ check_privileged(s);
gen_op_movi_cc(s, 3);
break;
case 0x78: /* STCKE D2(B2) [S] */
break;
case 0x79: /* SACF D2(B2) [S] */
/* Set Address Space Control Fast */
- check_privileged(env, 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_JUMP;
break;
case 0x7d: /* STSI D2,(B2) [S] */
- check_privileged(env, 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);
break;
case 0xb1: /* STFL D2(B2) [S] */
/* Store Facility List (CPU features) at 200 */
- check_privileged(env, 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));
break;
case 0xb2: /* LPSWE D2(B2) [S] */
/* Load PSW Extended */
- check_privileged(env, 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();
break;
case 0x20: /* SERVC R1,R2 [RRE] */
/* SCLP Service call (PV hypercall) */
- check_privileged(env, s, ilc);
+ check_privileged(s);
potential_page_fault(s);
tmp32_1 = load_reg32(r2);
tmp = load_reg(r1);
#endif
default:
LOG_DISAS("illegal b2 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, ilc);
+ gen_illegal_opcode(s);
break;
}
}
break;
default:
LOG_DISAS("illegal b3 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 2);
+ gen_illegal_opcode(s);
break;
}
break;
default:
LOG_DISAS("illegal b9 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 2);
+ gen_illegal_opcode(s);
break;
}
}
break;
default:
LOG_DISAS("illegal c0 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 3);
+ gen_illegal_opcode(s);
break;
}
}
break;
default:
LOG_DISAS("illegal c2 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 3);
+ gen_illegal_opcode(s);
break;
}
}
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(env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
- ilc = get_ilc(opc);
-
switch (opc) {
#ifndef CONFIG_USER_ONLY
case 0x01: /* SAM */
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);
+ tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilen));
+ 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(env, s->pc);
#ifndef CONFIG_USER_ONLY
case 0x80: /* SSM D2(B2) [S] */
/* Set System Mask */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
break;
case 0x82: /* LPSW D2(B2) [S] */
/* Load PSW */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
break;
case 0x83: /* DIAG R1,R3,D2 [RS] */
/* Diagnose call (KVM hypercall) */
- check_privileged(env, s, ilc);
+ check_privileged(s);
potential_page_fault(s);
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
#ifndef CONFIG_USER_ONLY
case 0xac: /* STNSM 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);
tmp = decode_si(s, insn, &i2, &b1, &d1);
tmp2 = tcg_temp_new_i64();
tcg_temp_free_i64(tmp2);
break;
case 0xae: /* SIGP R1,R3,D2(B2) [RS] */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
tcg_temp_free_i32(tmp32_1);
break;
case 0xb1: /* LRA R1,D2(X2, B2) [RX] */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code4(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
tmp32_1 = tcg_const_i32(r1);
#ifndef CONFIG_USER_ONLY
case 0xb6: /* STCTL R1,R3,D2(B2) [RS] */
/* Store Control */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
break;
case 0xb7: /* LCTL R1,R3,D2(B2) [RS] */
/* Load Control */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
#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(env, s, ilc);
+ check_privileged(s);
potential_page_fault(s);
insn = ld_code6(env, s->pc);
r1 = (insn >> 36) & 0xf;
#ifndef CONFIG_USER_ONLY
case 0xe5:
/* Test Protection */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code6(env, s->pc);
debug_insn(insn);
disas_e5(env, s, insn);
break;
default:
qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
- gen_illegal_opcode(env, s, ilc);
+ gen_illegal_opcode(s);
break;
}
}
DisasFields *f)
{
uint64_t insn, pc = s->pc;
- int op, op2;
+ int op, op2, ilen;
const DisasInsn *info;
insn = ld_code2(env, pc);
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;
break;
- case 2:
+ case 4:
insn = ld_code4(env, pc) << 32;
break;
- case 3:
+ case 6:
insn = (insn << 48) | (ld_code4(env, pc + 2) << 16);
break;
default:
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 (insn == NULL) {
disas_s390_insn(env, s);
int num_insns, max_insns;
CPUBreakpoint *bp;
ExitStatus status;
+ bool do_debug;
pc_start = tb->pc;
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 = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
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 = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
if (lj < j) {
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,
or exhaust instruction count, stop generation. */
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);