void helper_cmpxchg8b_unlocked(CPUX86State *env, target_ulong a0) { uintptr_t ra = GETPC(); uint64_t oldv, cmpv, newv; int eflags; eflags = cpu_cc_compute_all(env, CC_OP); cmpv = deposit64(env->regs[R_EAX], 32, 32, env->regs[R_EDX]); newv = deposit64(env->regs[R_EBX], 32, 32, env->regs[R_ECX]); oldv = cpu_ldq_data_ra(env, a0, ra); newv = (cmpv == oldv ? newv : oldv); /* always do the store */ cpu_stq_data_ra(env, a0, newv, ra); if (oldv == cmpv) { eflags |= CC_Z; } else { env->regs[R_EAX] = (uint32_t)oldv; env->regs[R_EDX] = (uint32_t)(oldv >> 32); eflags &= ~CC_Z; } CC_SRC = eflags; }
static void imx_gpio_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { IMXGPIOState *s = IMX_GPIO(opaque); DPRINTF("(%s, value = 0x%"PRIx32")\n", imx_gpio_reg_name(offset), (uint32_t)value); switch (offset) { case DR_ADDR: s->dr = value; imx_gpio_set_all_output_lines(s); break; case GDIR_ADDR: s->gdir = value; imx_gpio_set_all_output_lines(s); imx_gpio_set_all_int_lines(s); break; case ICR1_ADDR: s->icr = deposit64(s->icr, 0, 32, value); imx_gpio_set_all_int_lines(s); break; case ICR2_ADDR: s->icr = deposit64(s->icr, 32, 32, value); imx_gpio_set_all_int_lines(s); break; case IMR_ADDR: s->imr = value; imx_gpio_update_int(s); break; case ISR_ADDR: s->isr |= ~value; imx_gpio_set_all_int_lines(s); break; case EDGE_SEL_ADDR: if (s->has_edge_sel) { s->edge_sel = value; imx_gpio_set_all_int_lines(s); } else { qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: EDGE_SEL register not " "present on this version of GPIO device\n", TYPE_IMX_GPIO, __func__); } break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad register at offset %d\n", TYPE_IMX_GPIO, __func__, (int)offset); break; } return; }
uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices, uint32_t rn, uint32_t numregs) { /* Helper function for SIMD TBL and TBX. We have to do the table * lookup part for the 64 bits worth of indices we're passed in. * result is the initial results vector (either zeroes for TBL * or some guest values for TBX), rn the register number where * the table starts, and numregs the number of registers in the table. * We return the results of the lookups. */ int shift; for (shift = 0; shift < 64; shift += 8) { int index = extract64(indices, shift, 8); if (index < 16 * numregs) { /* Convert index (a byte offset into the virtual table * which is a series of 128-bit vectors concatenated) * into the correct vfp.regs[] element plus a bit offset * into that element, bearing in mind that the table * can wrap around from V31 to V0. */ int elt = (rn * 2 + (index >> 3)) % 64; int bitidx = (index & 7) * 8; uint64_t val = extract64(env->vfp.regs[elt], bitidx, 8); result = deposit64(result, shift, 8, val); } }
static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level) { BCM2835ICState *s = opaque; assert(irq >= 0 && irq < 64); s->gpu_irq_level = deposit64(s->gpu_irq_level, irq, 1, level != 0); bcm2835_ic_update(s); }
static void ronaldo_sdhci_slottype_handler(void *opaque, int n, int level) { SDHCIState *ss = SYSBUS_SDHCI(opaque); RonaldoSDHCIState *s = RONALDO_SDHCI(opaque); assert(n == 0); ss->capareg = deposit64(ss->capareg, 30, 2, level); ss->card = extract64(ss->capareg, 30, 2) ? s->mmc_card : s->sd_card; sd_set_cb(ss->card, ss->ro_cb, ss->eject_cb); }
void helper_cmpxchg8b(CPUX86State *env, target_ulong a0) { #ifdef CONFIG_ATOMIC64 uint64_t oldv, cmpv, newv; int eflags; eflags = cpu_cc_compute_all(env, CC_OP); cmpv = deposit64(env->regs[R_EAX], 32, 32, env->regs[R_EDX]); newv = deposit64(env->regs[R_EBX], 32, 32, env->regs[R_ECX]); #ifdef CONFIG_USER_ONLY { uint64_t *haddr = g2h(a0); cmpv = cpu_to_le64(cmpv); newv = cpu_to_le64(newv); oldv = atomic_cmpxchg__nocheck(haddr, cmpv, newv); oldv = le64_to_cpu(oldv); } #else { uintptr_t ra = GETPC(); int mem_idx = cpu_mmu_index(env, false); TCGMemOpIdx oi = make_memop_idx(MO_TEQ, mem_idx); oldv = helper_atomic_cmpxchgq_le_mmu(env, a0, cmpv, newv, oi, ra); } #endif if (oldv == cmpv) { eflags |= CC_Z; } else { env->regs[R_EAX] = (uint32_t)oldv; env->regs[R_EDX] = (uint32_t)(oldv >> 32); eflags &= ~CC_Z; } CC_SRC = eflags; #else cpu_loop_exit_atomic(ENV_GET_CPU(env), GETPC()); #endif /* CONFIG_ATOMIC64 */ }
static void smmuv3_init_regs(SMMUv3State *s) { /** * IDR0: stage1 only, AArch64 only, coherent access, 16b ASID, * multi-level stream table */ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, S1P, 1); /* stage 1 supported */ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TTF, 2); /* AArch64 PTW only */ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, COHACC, 1); /* IO coherent */ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, ASID16, 1); /* 16-bit ASID */ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TTENDIAN, 2); /* little endian */ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, STALL_MODEL, 1); /* No stall */ /* terminated transaction will always be aborted/error returned */ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TERM_MODEL, 1); /* 2-level stream table supported */ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, STLEVEL, 1); s->idr[1] = FIELD_DP32(s->idr[1], IDR1, SIDSIZE, SMMU_IDR1_SIDSIZE); s->idr[1] = FIELD_DP32(s->idr[1], IDR1, EVENTQS, SMMU_EVENTQS); s->idr[1] = FIELD_DP32(s->idr[1], IDR1, CMDQS, SMMU_CMDQS); /* 4K and 64K granule support */ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1); s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN64K, 1); s->idr[5] = FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS); /* 44 bits */ s->cmdq.base = deposit64(s->cmdq.base, 0, 5, SMMU_CMDQS); s->cmdq.prod = 0; s->cmdq.cons = 0; s->cmdq.entry_size = sizeof(struct Cmd); s->eventq.base = deposit64(s->eventq.base, 0, 5, SMMU_EVENTQS); s->eventq.prod = 0; s->eventq.cons = 0; s->eventq.entry_size = sizeof(struct Evt); s->features = 0; s->sid_split = 0; }
uint32_t HELPER(stfle)(CPUS390XState *env, uint64_t addr) { uint64_t words[MAX_STFL_WORDS]; unsigned count_m1 = env->regs[0] & 0xff; unsigned max_m1 = do_stfle(env, words); unsigned i; for (i = 0; i <= count_m1; ++i) { cpu_stq_data(env, addr + 8 * i, words[i]); } env->regs[0] = deposit64(env->regs[0], 0, 8, max_m1); return (count_m1 >= max_m1 ? 0 : 3); }
static void s390_vec_sar(S390Vector *d, const S390Vector *a, uint64_t count) { uint64_t tmp; if (count == 0) { d->doubleword[0] = a->doubleword[0]; d->doubleword[1] = a->doubleword[1]; } else if (count == 64) { d->doubleword[1] = a->doubleword[0]; d->doubleword[0] = 0; } else if (count < 64) { tmp = a->doubleword[1] >> count; d->doubleword[1] = deposit64(tmp, 64 - count, count, a->doubleword[0]); d->doubleword[0] = (int64_t)a->doubleword[0] >> count; } else {
void s390_realize_cpu_model(CPUState *cs, Error **errp) { S390CPUClass *xcc = S390_CPU_GET_CLASS(cs); S390CPU *cpu = S390_CPU(cs); const S390CPUModel *max_model; if (xcc->kvm_required && !kvm_enabled()) { error_setg(errp, "CPU definition requires KVM"); return; } if (!cpu->model) { /* no host model support -> perform compatibility stuff */ apply_cpu_model(NULL, errp); return; } max_model = get_max_cpu_model(errp); if (*errp) { error_prepend(errp, "CPU models are not available: "); return; } /* copy over properties that can vary */ cpu->model->lowest_ibc = max_model->lowest_ibc; cpu->model->cpu_id = max_model->cpu_id; cpu->model->cpu_id_format = max_model->cpu_id_format; cpu->model->cpu_ver = max_model->cpu_ver; check_consistency(cpu->model); check_compatibility(max_model, cpu->model, errp); if (*errp) { return; } apply_cpu_model(cpu->model, errp); cpu->env.cpuid = s390_cpuid_from_cpu_model(cpu->model); if (tcg_enabled()) { /* basic mode, write the cpu address into the first 4 bit of the ID */ cpu->env.cpuid = deposit64(cpu->env.cpuid, 54, 4, cpu->env.cpu_num); } }
int s390_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) { S390CPU *cpu = S390_CPU(cs); CPUS390XState *env = &cpu->env; uint64_t val; int cc_op; switch (n) { case S390_PSWM_REGNUM: if (tcg_enabled()) { cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, env->cc_vr); val = deposit64(env->psw.mask, 44, 2, cc_op); return gdb_get_regl(mem_buf, val); } return gdb_get_regl(mem_buf, env->psw.mask); case S390_PSWA_REGNUM: return gdb_get_regl(mem_buf, env->psw.addr); case S390_R0_REGNUM ... S390_R15_REGNUM: return gdb_get_regl(mem_buf, env->regs[n - S390_R0_REGNUM]); } return 0; }
/* CPUClass::reset() */ static void arm_cpu_reset(CPUState *s) { ARMCPU *cpu = ARM_CPU(s); ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu); CPUARMState *env = &cpu->env; acc->parent_reset(s); memset(env, 0, offsetof(CPUARMState, features)); g_hash_table_foreach(cpu->cp_regs, cp_reg_reset, cpu); g_hash_table_foreach(cpu->cp_regs, cp_reg_check_reset, cpu); env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid; env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0; env->vfp.xregs[ARM_VFP_MVFR1] = cpu->mvfr1; env->vfp.xregs[ARM_VFP_MVFR2] = cpu->mvfr2; cpu->powered_off = cpu->start_powered_off; s->halted = cpu->start_powered_off; if (arm_feature(env, ARM_FEATURE_IWMMXT)) { env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q'; } if (arm_feature(env, ARM_FEATURE_AARCH64)) { /* 64 bit CPUs always start in 64 bit mode */ env->aarch64 = 1; #if defined(CONFIG_USER_ONLY) env->pstate = PSTATE_MODE_EL0t; /* Userspace expects access to DC ZVA, CTL_EL0 and the cache ops */ env->cp15.sctlr_el[1] |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE; /* and to the FP/Neon instructions */ env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 2, 3); #else /* Reset into the highest available EL */ if (arm_feature(env, ARM_FEATURE_EL3)) { env->pstate = PSTATE_MODE_EL3h; } else if (arm_feature(env, ARM_FEATURE_EL2)) { env->pstate = PSTATE_MODE_EL2h; } else { env->pstate = PSTATE_MODE_EL1h; } env->pc = cpu->rvbar; #endif } else { #if defined(CONFIG_USER_ONLY) /* Userspace expects access to cp10 and cp11 for FP/Neon */ env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 4, 0xf); #endif } #if defined(CONFIG_USER_ONLY) env->uncached_cpsr = ARM_CPU_MODE_USR; /* For user mode we must enable access to coprocessors */ env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30; if (arm_feature(env, ARM_FEATURE_IWMMXT)) { env->cp15.c15_cpar = 3; } else if (arm_feature(env, ARM_FEATURE_XSCALE)) { env->cp15.c15_cpar = 1; } #else /* SVC mode with interrupts disabled. */ env->uncached_cpsr = ARM_CPU_MODE_SVC; env->daif = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F; /* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is * clear at reset. Initial SP and PC are loaded from ROM. */ if (IS_M(env)) { uint32_t initial_msp; /* Loaded from 0x0 */ uint32_t initial_pc; /* Loaded from 0x4 */ uint8_t *rom; env->daif &= ~PSTATE_I; rom = rom_ptr(0); if (rom) { /* Address zero is covered by ROM which hasn't yet been * copied into physical memory. */ initial_msp = ldl_p(rom); initial_pc = ldl_p(rom + 4); } else { /* Address zero not covered by a ROM blob, or the ROM blob * is in non-modifiable memory and this is a second reset after * it got copied into memory. In the latter case, rom_ptr * will return a NULL pointer and we should use ldl_phys instead. */ initial_msp = ldl_phys(s->as, 0); initial_pc = ldl_phys(s->as, 4); } env->regs[13] = initial_msp & 0xFFFFFFFC; env->regs[15] = initial_pc & ~1; env->thumb = initial_pc & 1; } /* AArch32 has a hard highvec setting of 0xFFFF0000. If we are currently * executing as AArch32 then check if highvecs are enabled and * adjust the PC accordingly. */ if (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_V) { env->regs[15] = 0xFFFF0000; } env->vfp.xregs[ARM_VFP_FPEXC] = 0; #endif set_flush_to_zero(1, &env->vfp.standard_fp_status); set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status); set_default_nan_mode(1, &env->vfp.standard_fp_status); set_float_detect_tininess(float_tininess_before_rounding, &env->vfp.fp_status); set_float_detect_tininess(float_tininess_before_rounding, &env->vfp.standard_fp_status); tlb_flush(s, 1); #ifndef CONFIG_USER_ONLY if (kvm_enabled()) { kvm_arm_reset_vcpu(cpu); } #endif hw_breakpoint_update_all(cpu); hw_watchpoint_update_all(cpu); }
/* CPUClass::reset() */ static void arm_cpu_reset(CPUState *s) { ARMCPU *cpu = ARM_CPU(s); ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu); CPUARMState *env = &cpu->env; acc->parent_reset(s); memset(env, 0, offsetof(CPUARMState, features)); g_hash_table_foreach(cpu->cp_regs, cp_reg_reset, cpu); env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid; env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0; env->vfp.xregs[ARM_VFP_MVFR1] = cpu->mvfr1; env->vfp.xregs[ARM_VFP_MVFR2] = cpu->mvfr2; if (arm_feature(env, ARM_FEATURE_IWMMXT)) { env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q'; } if (arm_feature(env, ARM_FEATURE_AARCH64)) { /* 64 bit CPUs always start in 64 bit mode */ env->aarch64 = 1; #if defined(CONFIG_USER_ONLY) env->pstate = PSTATE_MODE_EL0t; /* Userspace expects access to CTL_EL0 and the cache ops */ env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI; /* and to the FP/Neon instructions */ env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 2, 3); #else env->pstate = PSTATE_MODE_EL1h; env->pc = cpu->rvbar; #endif } else { #if defined(CONFIG_USER_ONLY) /* Userspace expects access to cp10 and cp11 for FP/Neon */ env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 4, 0xf); #endif } #if defined(CONFIG_USER_ONLY) env->uncached_cpsr = ARM_CPU_MODE_USR; /* For user mode we must enable access to coprocessors */ env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30; if (arm_feature(env, ARM_FEATURE_IWMMXT)) { env->cp15.c15_cpar = 3; } else if (arm_feature(env, ARM_FEATURE_XSCALE)) { env->cp15.c15_cpar = 1; } #else /* SVC mode with interrupts disabled. */ env->uncached_cpsr = ARM_CPU_MODE_SVC; env->daif = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F; /* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is clear at reset. Initial SP and PC are loaded from ROM. */ if (IS_M(env)) { uint32_t pc; uint8_t *rom; env->daif &= ~PSTATE_I; rom = rom_ptr(0); if (rom) { /* We should really use ldl_phys here, in case the guest modified flash and reset itself. However images loaded via -kernel have not been copied yet, so load the values directly from there. */ env->regs[13] = ldl_p(rom) & 0xFFFFFFFC; pc = ldl_p(rom + 4); env->thumb = pc & 1; env->regs[15] = pc & ~1; } } if (env->cp15.c1_sys & SCTLR_V) { env->regs[15] = 0xFFFF0000; } env->vfp.xregs[ARM_VFP_FPEXC] = 0; #endif set_flush_to_zero(1, &env->vfp.standard_fp_status); set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status); set_default_nan_mode(1, &env->vfp.standard_fp_status); set_float_detect_tininess(float_tininess_before_rounding, &env->vfp.fp_status); set_float_detect_tininess(float_tininess_before_rounding, &env->vfp.standard_fp_status); tlb_flush(s, 1); /* Reset is a state change for some CPUARMState fields which we * bake assumptions about into translated code, so we need to * tb_flush(). */ tb_flush(env); #ifndef CONFIG_USER_ONLY if (kvm_enabled()) { kvm_arm_reset_vcpu(cpu); } #endif }