s->is_jmp = DISAS_WFI;
break;
case 2: /* wfe */
+ gen_set_pc_im(s, s->pc);
+ s->is_jmp = DISAS_WFE;
+ break;
case 4: /* sev */
case 5: /* sevl */
/* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
break;
}
case NEON_2RM_VRECPE:
- gen_helper_recpe_u32(tmp, tmp, cpu_env);
+ {
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+ gen_helper_recpe_u32(tmp, tmp, fpstatus);
+ tcg_temp_free_ptr(fpstatus);
break;
+ }
case NEON_2RM_VRSQRTE:
- gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
+ {
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+ gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
+ tcg_temp_free_ptr(fpstatus);
break;
+ }
case NEON_2RM_VRECPE_F:
- gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
+ {
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+ gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
+ tcg_temp_free_ptr(fpstatus);
break;
+ }
case NEON_2RM_VRSQRTE_F:
- gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
+ {
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+ gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
+ tcg_temp_free_ptr(fpstatus);
break;
+ }
case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
gen_vfp_sito(0, 1);
break;
store_reg(s, 14, tmp2);
gen_bx(s, tmp);
break;
+ case 0x4:
+ {
+ /* crc32/crc32c */
+ uint32_t c = extract32(insn, 8, 4);
+
+ /* Check this CPU supports ARMv8 CRC instructions.
+ * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
+ * Bits 8, 10 and 11 should be zero.
+ */
+ if (!arm_feature(env, ARM_FEATURE_CRC) || op1 == 0x3 ||
+ (c & 0xd) != 0) {
+ goto illegal_op;
+ }
+
+ rn = extract32(insn, 16, 4);
+ rd = extract32(insn, 12, 4);
+
+ tmp = load_reg(s, rn);
+ tmp2 = load_reg(s, rm);
+ tmp3 = tcg_const_i32(1 << op1);
+ if (c & 0x2) {
+ gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
+ } else {
+ gen_helper_crc32(tmp, tmp, tmp2, tmp3);
+ }
+ tcg_temp_free_i32(tmp2);
+ tcg_temp_free_i32(tmp3);
+ store_reg(s, rd, tmp);
+ break;
+ }
case 0x5: /* saturating add/subtract */
ARCH(5TE);
rd = (insn >> 12) & 0xf;
case 0x18: /* clz */
gen_helper_clz(tmp, tmp);
break;
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ {
+ /* crc32/crc32c */
+ uint32_t sz = op & 0x3;
+ uint32_t c = op & 0x8;
+
+ if (!arm_feature(env, ARM_FEATURE_CRC)) {
+ goto illegal_op;
+ }
+
+ tmp2 = load_reg(s, rm);
+ tmp3 = tcg_const_i32(1 << sz);
+ if (c) {
+ gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
+ } else {
+ gen_helper_crc32(tmp, tmp, tmp2, tmp3);
+ }
+ tcg_temp_free_i32(tmp2);
+ tcg_temp_free_i32(tmp3);
+ break;
+ }
default:
goto illegal_op;
}
dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
dc->cp_regs = cpu->cp_regs;
dc->current_pl = arm_current_pl(env);
+ dc->features = env->features;
cpu_F0s = tcg_temp_new_i32();
cpu_F1s = tcg_temp_new_i32();
}
#endif
- if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
- QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+ if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+ QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
gen_exception_insn(dc, 0, EXCP_DEBUG);
/* Advance PC so that clearing the breakpoint will
if (dc->condjmp) {
/* FIXME: This can theoretically happen with self-modifying
code. */
- cpu_abort(env, "IO on conditional branch instruction");
+ cpu_abort(cs, "IO on conditional branch instruction");
}
gen_io_end();
}
case DISAS_WFI:
gen_helper_wfi(cpu_env);
break;
+ case DISAS_WFE:
+ gen_helper_wfe(cpu_env);
+ break;
case DISAS_SWI:
gen_exception(EXCP_SWI);
break;