diff options
Diffstat (limited to 'target')
48 files changed, 611 insertions, 536 deletions
diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c index 2b856930fb..f9de5164e5 100644 --- a/target/arm/arm-powerctl.c +++ b/target/arm/arm-powerctl.c @@ -120,11 +120,8 @@ static void arm_set_cpu_on_async_work(CPUState *target_cpu_state, if (info->target_aa64) { target_cpu->env.xregs[0] = info->context_id; - target_cpu->env.thumb = false; } else { target_cpu->env.regs[0] = info->context_id; - target_cpu->env.thumb = info->entry & 1; - info->entry &= 0xfffffffe; } /* Start the new CPU at the requested address */ diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 7e1f3dd637..3874dc9875 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -40,8 +40,31 @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value) { ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; - cpu->env.regs[15] = value; + if (is_a64(env)) { + env->pc = value; + env->thumb = 0; + } else { + env->regs[15] = value & ~1; + env->thumb = value & 1; + } +} + +static void arm_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + + /* + * It's OK to look at env for the current mode here, because it's + * never possible for an AArch64 TB to chain to an AArch32 TB. + */ + if (is_a64(env)) { + env->pc = tb->pc; + } else { + env->regs[15] = tb->pc; + } } static bool arm_cpu_has_work(CPUState *cs) @@ -162,6 +185,9 @@ static void arm_cpu_reset(CPUState *s) 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; + /* Enable all PAC keys. */ + env->cp15.sctlr_el[1] |= (SCTLR_EnIA | SCTLR_EnIB | + SCTLR_EnDA | SCTLR_EnDB); /* Enable all PAC instructions */ env->cp15.hcr_el2 |= HCR_API; env->cp15.scr_el3 |= SCR_API; @@ -836,6 +862,13 @@ static void arm_cpu_finalizefn(Object *obj) QLIST_REMOVE(hook, node); g_free(hook); } +#ifndef CONFIG_USER_ONLY + if (cpu->pmu_timer) { + timer_del(cpu->pmu_timer); + timer_deinit(cpu->pmu_timer); + timer_free(cpu->pmu_timer); + } +#endif } static void arm_cpu_realizefn(DeviceState *dev, Error **errp) @@ -1039,13 +1072,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) unset_feature(env, ARM_FEATURE_PMU); } if (arm_feature(env, ARM_FEATURE_PMU)) { - cpu->pmceid0 = get_pmceid(&cpu->env, 0); - cpu->pmceid1 = get_pmceid(&cpu->env, 1); + pmu_init(cpu); if (!kvm_enabled()) { arm_register_pre_el_change_hook(cpu, &pmu_pre_el_change, 0); arm_register_el_change_hook(cpu, &pmu_post_el_change, 0); } + +#ifndef CONFIG_USER_ONLY + cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, arm_pmu_timer_cb, + cpu); +#endif } else { cpu->id_aa64dfr0 &= ~0xf00; cpu->pmceid0 = 0; @@ -2088,6 +2125,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) cc->cpu_exec_interrupt = arm_cpu_exec_interrupt; cc->dump_state = arm_cpu_dump_state; cc->set_pc = arm_cpu_set_pc; + cc->synchronize_from_tb = arm_cpu_synchronize_from_tb; cc->gdb_read_register = arm_cpu_gdb_read_register; cc->gdb_write_register = arm_cpu_gdb_write_register; #ifdef CONFIG_USER_ONLY diff --git a/target/arm/cpu.h b/target/arm/cpu.h index ff81db420d..a68bcc9fed 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -746,6 +746,11 @@ struct ARMCPU { /* Timers used by the generic (architected) timer */ QEMUTimer *gt_timer[NUM_GTIMERS]; + /* + * Timer used by the PMU. Its state is restored after migration by + * pmu_op_finish() - it does not need other handling during migration + */ + QEMUTimer *pmu_timer; /* GPIO outputs for generic timer */ qemu_irq gt_timer_outputs[NUM_GTIMERS]; /* GPIO output for GICv3 maintenance interrupt signal */ @@ -1005,6 +1010,11 @@ void pmccntr_op_finish(CPUARMState *env); void pmu_op_start(CPUARMState *env); void pmu_op_finish(CPUARMState *env); +/* + * Called when a PMU counter is due to overflow + */ +void arm_pmu_timer_cb(void *opaque); + /** * Functions to register as EL change hooks for PMU mode filtering */ @@ -1012,14 +1022,13 @@ void pmu_pre_el_change(ARMCPU *cpu, void *ignored); void pmu_post_el_change(ARMCPU *cpu, void *ignored); /* - * get_pmceid - * @env: CPUARMState - * @which: which PMCEID register to return (0 or 1) + * pmu_init + * @cpu: ARMCPU * - * Return the PMCEID[01]_EL0 register values corresponding to the counters - * which are supported given the current configuration + * Initialize the CPU's PMCEID[01]_EL0 registers and associated internal state + * for the current configuration */ -uint64_t get_pmceid(CPUARMState *env, unsigned which); +void pmu_init(ARMCPU *cpu); /* SCTLR bit meanings. Several bits have been reused in newer * versions of the architecture; in that case we define constants @@ -2503,7 +2512,7 @@ bool write_cpustate_to_list(ARMCPU *cpu); #if defined(TARGET_AARCH64) # define TARGET_PHYS_ADDR_SPACE_BITS 48 -# define TARGET_VIRT_ADDR_SPACE_BITS 64 +# define TARGET_VIRT_ADDR_SPACE_BITS 48 #else # define TARGET_PHYS_ADDR_SPACE_BITS 40 # define TARGET_VIRT_ADDR_SPACE_BITS 32 diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index e9bc461c36..7107ec8d7e 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -281,38 +281,6 @@ static void cpu_max_set_sve_vq(Object *obj, Visitor *v, const char *name, error_propagate(errp, err); } -#ifdef CONFIG_USER_ONLY -static void cpu_max_get_packey(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - ARMCPU *cpu = ARM_CPU(obj); - const uint64_t *bit = opaque; - bool enabled = (cpu->env.cp15.sctlr_el[1] & *bit) != 0; - - visit_type_bool(v, name, &enabled, errp); -} - -static void cpu_max_set_packey(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - ARMCPU *cpu = ARM_CPU(obj); - Error *err = NULL; - const uint64_t *bit = opaque; - bool enabled; - - visit_type_bool(v, name, &enabled, errp); - - if (!err) { - if (enabled) { - cpu->env.cp15.sctlr_el[1] |= *bit; - } else { - cpu->env.cp15.sctlr_el[1] &= ~*bit; - } - } - error_propagate(errp, err); -} -#endif - /* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); * otherwise, a CPU with as many features enabled as our emulation supports. * The version of '-cpu max' for qemu-system-arm is defined in cpu.c; @@ -388,34 +356,6 @@ static void aarch64_max_initfn(Object *obj) */ cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */ cpu->dcz_blocksize = 7; /* 512 bytes */ - - /* - * Note that Linux will enable enable all of the keys at once. - * But doing it this way will allow experimentation beyond that. - */ - { - static const uint64_t apia_bit = SCTLR_EnIA; - static const uint64_t apib_bit = SCTLR_EnIB; - static const uint64_t apda_bit = SCTLR_EnDA; - static const uint64_t apdb_bit = SCTLR_EnDB; - - object_property_add(obj, "apia", "bool", cpu_max_get_packey, - cpu_max_set_packey, NULL, - (void *)&apia_bit, &error_fatal); - object_property_add(obj, "apib", "bool", cpu_max_get_packey, - cpu_max_set_packey, NULL, - (void *)&apib_bit, &error_fatal); - object_property_add(obj, "apda", "bool", cpu_max_get_packey, - cpu_max_set_packey, NULL, - (void *)&apda_bit, &error_fatal); - object_property_add(obj, "apdb", "bool", cpu_max_get_packey, - cpu_max_set_packey, NULL, - (void *)&apdb_bit, &error_fatal); - - /* Enable all PAC keys by default. */ - cpu->env.cp15.sctlr_el[1] |= SCTLR_EnIA | SCTLR_EnIB; - cpu->env.cp15.sctlr_el[1] |= SCTLR_EnDA | SCTLR_EnDB; - } #endif cpu->sve_max_vq = ARM_MAX_VQ; @@ -480,20 +420,6 @@ static void aarch64_cpu_finalizefn(Object *obj) { } -static void aarch64_cpu_set_pc(CPUState *cs, vaddr value) -{ - ARMCPU *cpu = ARM_CPU(cs); - /* It's OK to look at env for the current mode here, because it's - * never possible for an AArch64 TB to chain to an AArch32 TB. - * (Otherwise we would need to use synchronize_from_tb instead.) - */ - if (is_a64(&cpu->env)) { - cpu->env.pc = value; - } else { - cpu->env.regs[15] = value; - } -} - static gchar *aarch64_gdb_arch_name(CPUState *cs) { return g_strdup("aarch64"); @@ -504,7 +430,6 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data) CPUClass *cc = CPU_CLASS(oc); cc->cpu_exec_interrupt = arm_cpu_exec_interrupt; - cc->set_pc = aarch64_cpu_set_pc; cc->gdb_read_register = aarch64_cpu_gdb_read_register; cc->gdb_write_register = aarch64_cpu_gdb_write_register; cc->gdb_num_core_regs = 34; diff --git a/target/arm/helper.c b/target/arm/helper.c index 92666e5208..d070879894 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -977,6 +977,7 @@ static const ARMCPRegInfo v6_cp_reginfo[] = { /* Definitions for the PMU registers */ #define PMCRN_MASK 0xf800 #define PMCRN_SHIFT 11 +#define PMCRLC 0x40 #define PMCRDP 0x10 #define PMCRD 0x8 #define PMCRC 0x4 @@ -1020,6 +1021,13 @@ typedef struct pm_event { * counters hold a difference from the return value from this function */ uint64_t (*get_count)(CPUARMState *); + /* + * Return how many nanoseconds it will take (at a minimum) for count events + * to occur. A negative value indicates the counter will never overflow, or + * that the counter has otherwise arranged for the overflow bit to be set + * and the PMU interrupt to be raised on overflow. + */ + int64_t (*ns_per_count)(uint64_t); } pm_event; static bool event_always_supported(CPUARMState *env) @@ -1036,6 +1044,11 @@ static uint64_t swinc_get_count(CPUARMState *env) return 0; } +static int64_t swinc_ns_per(uint64_t ignored) +{ + return -1; +} + /* * Return the underlying cycle count for the PMU cycle counters. If we're in * usermode, simply return 0. @@ -1051,6 +1064,11 @@ static uint64_t cycles_get_count(CPUARMState *env) } #ifndef CONFIG_USER_ONLY +static int64_t cycles_ns_per(uint64_t cycles) +{ + return (ARM_CPU_FREQ / NANOSECONDS_PER_SECOND) * cycles; +} + static bool instructions_supported(CPUARMState *env) { return use_icount == 1 /* Precise instruction counting */; @@ -1060,21 +1078,29 @@ static uint64_t instructions_get_count(CPUARMState *env) { return (uint64_t)cpu_get_icount_raw(); } + +static int64_t instructions_ns_per(uint64_t icount) +{ + return cpu_icount_to_ns((int64_t)icount); +} #endif static const pm_event pm_events[] = { { .number = 0x000, /* SW_INCR */ .supported = event_always_supported, .get_count = swinc_get_count, + .ns_per_count = swinc_ns_per, }, #ifndef CONFIG_USER_ONLY { .number = 0x008, /* INST_RETIRED, Instruction architecturally executed */ .supported = instructions_supported, .get_count = instructions_get_count, + .ns_per_count = instructions_ns_per, }, { .number = 0x011, /* CPU_CYCLES, Cycle */ .supported = event_always_supported, .get_count = cycles_get_count, + .ns_per_count = cycles_ns_per, } #endif }; @@ -1090,22 +1116,24 @@ static const pm_event pm_events[] = { static uint16_t supported_event_map[MAX_EVENT_ID + 1]; /* - * Called upon initialization to build PMCEID0_EL0 or PMCEID1_EL0 (indicated by - * 'which'). We also use it to build a map of ARM event numbers to indices in - * our pm_events array. + * Called upon CPU initialization to initialize PMCEID[01]_EL0 and build a map + * of ARM event numbers to indices in our pm_events array. * * Note: Events in the 0x40XX range are not currently supported. */ -uint64_t get_pmceid(CPUARMState *env, unsigned which) +void pmu_init(ARMCPU *cpu) { - uint64_t pmceid = 0; unsigned int i; - assert(which <= 1); - + /* + * Empty supported_event_map and cpu->pmceid[01] before adding supported + * events to them + */ for (i = 0; i < ARRAY_SIZE(supported_event_map); i++) { supported_event_map[i] = UNSUPPORTED_EVENT; } + cpu->pmceid0 = 0; + cpu->pmceid1 = 0; for (i = 0; i < ARRAY_SIZE(pm_events); i++) { const pm_event *cnt = &pm_events[i]; @@ -1113,13 +1141,16 @@ uint64_t get_pmceid(CPUARMState *env, unsigned which) /* We do not currently support events in the 0x40xx range */ assert(cnt->number <= 0x3f); - if ((cnt->number & 0x20) == (which << 6) && - cnt->supported(env)) { - pmceid |= (1 << (cnt->number & 0x1f)); + if (cnt->supported(&cpu->env)) { supported_event_map[cnt->number] = i; + uint64_t event_mask = 1 << (cnt->number & 0x1f); + if (cnt->number & 0x20) { + cpu->pmceid1 |= event_mask; + } else { + cpu->pmceid0 |= event_mask; + } } } - return pmceid; } /* @@ -1288,6 +1319,13 @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter) return enabled && !prohibited && !filtered; } +static void pmu_update_irq(CPUARMState *env) +{ + ARMCPU *cpu = arm_env_get_cpu(env); + qemu_set_irq(cpu->pmu_interrupt, (env->cp15.c9_pmcr & PMCRE) && + (env->cp15.c9_pminten & env->cp15.c9_pmovsr)); +} + /* * Ensure c15_ccnt is the guest-visible count so that operations such as * enabling/disabling the counter or filtering, modifying the count itself, @@ -1305,7 +1343,16 @@ void pmccntr_op_start(CPUARMState *env) eff_cycles /= 64; } - env->cp15.c15_ccnt = eff_cycles - env->cp15.c15_ccnt_delta; + uint64_t new_pmccntr = eff_cycles - env->cp15.c15_ccnt_delta; + + uint64_t overflow_mask = env->cp15.c9_pmcr & PMCRLC ? \ + 1ull << 63 : 1ull << 31; + if (env->cp15.c15_ccnt & ~new_pmccntr & overflow_mask) { + env->cp15.c9_pmovsr |= (1 << 31); + pmu_update_irq(env); + } + + env->cp15.c15_ccnt = new_pmccntr; } env->cp15.c15_ccnt_delta = cycles; } @@ -1318,13 +1365,27 @@ void pmccntr_op_start(CPUARMState *env) void pmccntr_op_finish(CPUARMState *env) { if (pmu_counter_enabled(env, 31)) { - uint64_t prev_cycles = env->cp15.c15_ccnt_delta; +#ifndef CONFIG_USER_ONLY + /* Calculate when the counter will next overflow */ + uint64_t remaining_cycles = -env->cp15.c15_ccnt; + if (!(env->cp15.c9_pmcr & PMCRLC)) { + remaining_cycles = (uint32_t)remaining_cycles; + } + int64_t overflow_in = cycles_ns_per(remaining_cycles); + if (overflow_in > 0) { + int64_t overflow_at = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + overflow_in; + ARMCPU *cpu = arm_env_get_cpu(env); + timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at); + } +#endif + + uint64_t prev_cycles = env->cp15.c15_ccnt_delta; if (env->cp15.c9_pmcr & PMCRD) { /* Increment once every 64 processor clock cycles */ prev_cycles /= 64; } - env->cp15.c15_ccnt_delta = prev_cycles - env->cp15.c15_ccnt; } } @@ -1340,8 +1401,13 @@ static void pmevcntr_op_start(CPUARMState *env, uint8_t counter) } if (pmu_counter_enabled(env, counter)) { - env->cp15.c14_pmevcntr[counter] = - count - env->cp15.c14_pmevcntr_delta[counter]; + uint32_t new_pmevcntr = count - env->cp15.c14_pmevcntr_delta[counter]; + + if (env->cp15.c14_pmevcntr[counter] & ~new_pmevcntr & INT32_MIN) { + env->cp15.c9_pmovsr |= (1 << counter); + pmu_update_irq(env); + } + env->cp15.c14_pmevcntr[counter] = new_pmevcntr; } env->cp15.c14_pmevcntr_delta[counter] = count; } @@ -1349,6 +1415,21 @@ static void pmevcntr_op_start(CPUARMState *env, uint8_t counter) static void pmevcntr_op_finish(CPUARMState *env, uint8_t counter) { if (pmu_counter_enabled(env, counter)) { +#ifndef CONFIG_USER_ONLY + uint16_t event = env->cp15.c14_pmevtyper[counter] & PMXEVTYPER_EVTCOUNT; + uint16_t event_idx = supported_event_map[event]; + uint64_t delta = UINT32_MAX - + (uint32_t)env->cp15.c14_pmevcntr[counter] + 1; + int64_t overflow_in = pm_events[event_idx].ns_per_count(delta); + + if (overflow_in > 0) { + int64_t overflow_at = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + overflow_in; + ARMCPU *cpu = arm_env_get_cpu(env); + timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at); + } +#endif + env->cp15.c14_pmevcntr_delta[counter] -= env->cp15.c14_pmevcntr[counter]; } @@ -1382,6 +1463,20 @@ void pmu_post_el_change(ARMCPU *cpu, void *ignored) pmu_op_finish(&cpu->env); } +void arm_pmu_timer_cb(void *opaque) +{ + ARMCPU *cpu = opaque; + + /* + * Update all the counter values based on the current underlying counts, + * triggering interrupts to be raised, if necessary. pmu_op_finish() also + * has the effect of setting the cpu->pmu_timer to the next earliest time a + * counter may expire. + */ + pmu_op_start(&cpu->env); + pmu_op_finish(&cpu->env); +} + static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -1418,7 +1513,20 @@ static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri, /* counter is SW_INCR */ (env->cp15.c14_pmevtyper[i] & PMXEVTYPER_EVTCOUNT) == 0x0) { pmevcntr_op_start(env, i); - env->cp15.c14_pmevcntr[i]++; + + /* + * Detect if this write causes an overflow since we can't predict + * PMSWINC overflows like we can for other events + */ + uint32_t new_pmswinc = env->cp15.c14_pmevcntr[i] + 1; + + if (env->cp15.c14_pmevcntr[i] & ~new_pmswinc & INT32_MIN) { + env->cp15.c9_pmovsr |= (1 << i); + pmu_update_irq(env); + } + + env->cp15.c14_pmevcntr[i] = new_pmswinc; + pmevcntr_op_finish(env, i); } } @@ -1503,6 +1611,7 @@ static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri, { value &= pmu_counter_mask(env); env->cp15.c9_pmovsr &= ~value; + pmu_update_irq(env); } static void pmovsset_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -1510,6 +1619,7 @@ static void pmovsset_write(CPUARMState *env, const ARMCPRegInfo *ri, { value &= pmu_counter_mask(env); env->cp15.c9_pmovsr |= value; + pmu_update_irq(env); } static void pmevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -1696,6 +1806,7 @@ static void pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri, /* We have no event counters so only the C bit can be changed */ value &= pmu_counter_mask(env); env->cp15.c9_pminten |= value; + pmu_update_irq(env); } static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -1703,6 +1814,7 @@ static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri, { value &= pmu_counter_mask(env); env->cp15.c9_pminten &= ~value; + pmu_update_irq(env); } static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -1747,6 +1859,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) if (cpu_isar_feature(aa64_lor, cpu)) { valid_mask |= SCR_TLOR; } + if (cpu_isar_feature(aa64_pauth, cpu)) { + valid_mask |= SCR_API | SCR_APK; + } /* Clear all-context RES0 bits. */ value &= valid_mask; @@ -1841,7 +1956,7 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten), .writefn = pmcntenclr_write }, { .name = "PMOVSR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 3, - .access = PL0_RW, + .access = PL0_RW, .type = ARM_CP_IO, .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmovsr), .accessfn = pmreg_access, .writefn = pmovsr_write, @@ -1849,16 +1964,18 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { { .name = "PMOVSCLR_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 3, .access = PL0_RW, .accessfn = pmreg_access, - .type = ARM_CP_ALIAS, + .type = ARM_CP_ALIAS | ARM_CP_IO, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr), .writefn = pmovsr_write, .raw_writefn = raw_write }, { .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4, - .access = PL0_W, .accessfn = pmreg_access_swinc, .type = ARM_CP_NO_RAW, + .access = PL0_W, .accessfn = pmreg_access_swinc, + .type = ARM_CP_NO_RAW | ARM_CP_IO, .writefn = pmswinc_write }, { .name = "PMSWINC_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 4, - .access = PL0_W, .accessfn = pmreg_access_swinc, .type = ARM_CP_NO_RAW, + .access = PL0_W, .accessfn = pmreg_access_swinc, + .type = ARM_CP_NO_RAW | ARM_CP_IO, .writefn = pmswinc_write }, { .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5, .access = PL0_RW, .type = ARM_CP_ALIAS, @@ -2045,14 +2162,14 @@ static const ARMCPRegInfo pmovsset_cp_reginfo[] = { /* PMOVSSET is not implemented in v7 before v7ve */ { .name = "PMOVSSET", .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 3, .access = PL0_RW, .accessfn = pmreg_access, - .type = ARM_CP_ALIAS, + .type = ARM_CP_ALIAS | ARM_CP_IO, .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmovsr), .writefn = pmovsset_write, .raw_writefn = raw_write }, { .name = "PMOVSSET_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 14, .opc2 = 3, .access = PL0_RW, .accessfn = pmreg_access, - .type = ARM_CP_ALIAS, + .type = ARM_CP_ALIAS | ARM_CP_IO, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr), .writefn = pmovsset_write, .raw_writefn = raw_write }, @@ -4444,6 +4561,9 @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) if (cpu_isar_feature(aa64_lor, cpu)) { valid_mask |= HCR_TLOR; } + if (cpu_isar_feature(aa64_pauth, cpu)) { + valid_mask |= HCR_API | HCR_APK; + } /* Clear RES0 bits. */ value &= valid_mask; @@ -10447,7 +10567,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, uint64_t ttbr; hwaddr descaddr, indexmask, indexmask_grainsize; uint32_t tableattrs; - target_ulong page_size, top_bits; + target_ulong page_size; uint32_t attrs; int32_t stride; int addrsize, inputsize; @@ -10487,12 +10607,19 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, * We determined the region when collecting the parameters, but we * have not yet validated that the address is valid for the region. * Extract the top bits and verify that they all match select. - */ - top_bits = sextract64(address, inputsize, addrsize - inputsize); - if (-top_bits != param.select || (param.select && !ttbr1_valid)) { - /* In the gap between the two regions, this is a Translation fault */ - fault_type = ARMFault_Translation; - goto do_fault; + * + * For aa32, if inputsize == addrsize, then we have selected the + * region by exclusion in aa32_va_parameters and there is no more + * validation to do here. + */ + if (inputsize < addrsize) { + target_ulong top_bits = sextract64(address, inputsize, + addrsize - inputsize); + if (-top_bits != param.select || (param.select && !ttbr1_valid)) { + /* The gap between the two regions is a Translation fault */ + fault_type = ARMFault_Translation; + goto do_fault; + } } if (param.using64k) { @@ -11071,17 +11198,18 @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address, } } } + break; + } - /* The IDAU will override the SAU lookup results if it specifies - * higher security than the SAU does. - */ - if (!idau_ns) { - if (sattrs->ns || (!idau_nsc && sattrs->nsc)) { - sattrs->ns = false; - sattrs->nsc = idau_nsc; - } + /* + * The IDAU will override the SAU lookup results if it specifies + * higher security than the SAU does. + */ + if (!idau_ns) { + if (sattrs->ns || (!idau_nsc && sattrs->nsc)) { + sattrs->ns = false; + sattrs->nsc = idau_nsc; } - break; } } diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 4d28a27c3b..a1997e3ae2 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -2036,7 +2036,7 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn) if (!dc_isar_feature(aa64_pauth, s)) { goto do_unallocated; } - if (op3 != 2 || op3 != 3) { + if ((op3 & ~1) != 2) { goto do_unallocated; } if (s->pauth_active) { @@ -2144,7 +2144,11 @@ static void disas_b_exc_sys(DisasContext *s, uint32_t insn) break; case 0x6a: /* Exception generation / System */ if (insn & (1 << 24)) { - disas_system(s, insn); + if (extract32(insn, 22, 2) == 0) { + disas_system(s, insn); + } else { + unallocated_encoding(s); + } } else { disas_exc(s, insn); } @@ -2799,7 +2803,7 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn, } else { if (size == 3 && opc == 2) { /* PRFM - prefetch */ - if (is_unpriv) { + if (idx != 0) { unallocated_encoding(s); return; } @@ -3245,6 +3249,7 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn) { int rt = extract32(insn, 0, 5); int rn = extract32(insn, 5, 5); + int rm = extract32(insn, 16, 5); int size = extract32(insn, 10, 2); int opcode = extract32(insn, 12, 4); bool is_store = !extract32(insn, 22, 1); @@ -3264,6 +3269,11 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn) return; } + if (!is_postidx && rm != 0) { + unallocated_encoding(s); + return; + } + /* From the shared decode logic */ switch (opcode) { case 0x0: @@ -3363,7 +3373,6 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn) } if (is_postidx) { - int rm = extract32(insn, 16, 5); if (rm == 31) { tcg_gen_mov_i64(tcg_rn, tcg_addr); } else { @@ -3400,6 +3409,7 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn) { int rt = extract32(insn, 0, 5); int rn = extract32(insn, 5, 5); + int rm = extract32(insn, 16, 5); int size = extract32(insn, 10, 2); int S = extract32(insn, 12, 1); int opc = extract32(insn, 13, 3); @@ -3415,6 +3425,15 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn) int ebytes, xs; TCGv_i64 tcg_addr, tcg_rn, tcg_ebytes; + if (extract32(insn, 31, 1)) { + unallocated_encoding(s); + return; + } + if (!is_postidx && rm != 0) { + unallocated_encoding(s); + return; + } + switch (scale) { case 3: if (!is_load || S) { @@ -3492,7 +3511,6 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn) } if (is_postidx) { - int rm = extract32(insn, 16, 5); if (rm == 31) { tcg_gen_mov_i64(tcg_rn, tcg_addr); } else { @@ -4183,6 +4201,7 @@ static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn) int imm3 = extract32(insn, 10, 3); int option = extract32(insn, 13, 3); int rm = extract32(insn, 16, 5); + int opt = extract32(insn, 22, 2); bool setflags = extract32(insn, 29, 1); bool sub_op = extract32(insn, 30, 1); bool sf = extract32(insn, 31, 1); @@ -4191,7 +4210,7 @@ static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn) TCGv_i64 tcg_rd; TCGv_i64 tcg_result; - if (imm3 > 4) { + if (imm3 > 4 || opt != 0) { unallocated_encoding(s); return; } @@ -5617,11 +5636,17 @@ static void handle_fp_fcvt(DisasContext *s, int opcode, */ static void disas_fp_1src(DisasContext *s, uint32_t insn) { + int mos = extract32(insn, 29, 3); int type = extract32(insn, 22, 2); int opcode = extract32(insn, 15, 6); int rn = extract32(insn, 5, 5); int rd = extract32(insn, 0, 5); + if (mos) { + unallocated_encoding(s); + return; + } + switch (opcode) { case 0x4: case 0x5: case 0x7: { @@ -5848,13 +5873,14 @@ static void handle_fp_2src_half(DisasContext *s, int opcode, */ static void disas_fp_2src(DisasContext *s, uint32_t insn) { + int mos = extract32(insn, 29, 3); int type = extract32(insn, 22, 2); int rd = extract32(insn, 0, 5); int rn = extract32(insn, 5, 5); int rm = extract32(insn, 16, 5); int opcode = extract32(insn, 12, 4); - if (opcode > 8) { + if (opcode > 8 || mos) { unallocated_encoding(s); return; } @@ -6009,6 +6035,7 @@ static void handle_fp_3src_half(DisasContext *s, bool o0, bool o1, */ static void disas_fp_3src(DisasContext *s, uint32_t insn) { + int mos = extract32(insn, 29, 3); int type = extract32(insn, 22, 2); int rd = extract32(insn, 0, 5); int rn = extract32(insn, 5, 5); @@ -6017,6 +6044,11 @@ static void disas_fp_3src(DisasContext *s, uint32_t insn) bool o0 = extract32(insn, 15, 1); bool o1 = extract32(insn, 21, 1); + if (mos) { + unallocated_encoding(s); + return; + } + switch (type) { case 0: if (!fp_access_check(s)) { @@ -6086,12 +6118,19 @@ uint64_t vfp_expand_imm(int size, uint8_t imm8) static void disas_fp_imm(DisasContext *s, uint32_t insn) { int rd = extract32(insn, 0, 5); + int imm5 = extract32(insn, 5, 5); int imm8 = extract32(insn, 13, 8); int type = extract32(insn, 22, 2); + int mos = extract32(insn, 29, 3); uint64_t imm; TCGv_i64 tcg_res; TCGMemOp sz; + if (mos || imm5) { + unallocated_encoding(s); + return; + } + switch (type) { case 0: sz = MO_32; @@ -12602,7 +12641,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn) break; case 0x0e: /* SDOT */ case 0x1e: /* UDOT */ - if (size != MO_32 || !dc_isar_feature(aa64_dp, s)) { + if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_dp, s)) { unallocated_encoding(s); return; } @@ -12611,7 +12650,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn) case 0x13: /* FCMLA #90 */ case 0x15: /* FCMLA #180 */ case 0x17: /* FCMLA #270 */ - if (!dc_isar_feature(aa64_fcma, s)) { + if (is_scalar || !dc_isar_feature(aa64_fcma, s)) { unallocated_encoding(s); return; } @@ -12641,7 +12680,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn) case 2: /* complex fp */ /* Each indexable element is a complex pair. */ - size <<= 1; + size += 1; switch (size) { case MO_32: if (h && !is_q) { diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 2f5412592d..7483daef58 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -2503,7 +2503,7 @@ static X86CPUDefinition builtin_x86_defs[] = { .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 85, - .stepping = 5, + .stepping = 6, .features[FEAT_1_EDX] = CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | @@ -2801,6 +2801,8 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, + .features[FEAT_SVM] = + CPUID_SVM_NPT | CPUID_SVM_NRIPSAVE, /* no xsaveopt! */ .xlevel = 0x8000001A, .model_id = "AMD Opteron 62xx class CPU", @@ -2831,6 +2833,8 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, + .features[FEAT_SVM] = + CPUID_SVM_NPT | CPUID_SVM_NRIPSAVE, /* no xsaveopt! */ .xlevel = 0x8000001A, .model_id = "AMD Opteron 63xx class CPU", @@ -2877,6 +2881,8 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_XSAVE_XGETBV1, .features[FEAT_6_EAX] = CPUID_6_EAX_ARAT, + .features[FEAT_SVM] = + CPUID_SVM_NPT | CPUID_SVM_NRIPSAVE, .xlevel = 0x8000001E, .model_id = "AMD EPYC Processor", .cache_info = &epyc_cache_info, @@ -2925,6 +2931,8 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_XSAVE_XGETBV1, .features[FEAT_6_EAX] = CPUID_6_EAX_ARAT, + .features[FEAT_SVM] = + CPUID_SVM_NPT | CPUID_SVM_NRIPSAVE, .xlevel = 0x8000001E, .model_id = "AMD EPYC Processor (with IBPB)", .cache_info = &epyc_cache_info, diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index e193022c03..689b585027 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -13,10 +13,10 @@ * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see <http://www.gnu.org/licenses/>. + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. * * This file contain code under public domain from the hvdos project: * https://github.com/mist64/hvdos diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index b288a3864e..f154565117 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -7,12 +7,12 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <http://www.gnu.org/licenses/>. diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c index 6eeffdf9bb..b35489ba4e 100644 --- a/target/m68k/fpu_helper.c +++ b/target/m68k/fpu_helper.c @@ -7,12 +7,12 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <http://www.gnu.org/licenses/>. diff --git a/target/m68k/gdbstub.c b/target/m68k/gdbstub.c index 99e5be8132..fd2bb46c42 100644 --- a/target/m68k/gdbstub.c +++ b/target/m68k/gdbstub.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/m68k/helper.c b/target/m68k/helper.c index 917d46efcc..3e26d337bf 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -7,12 +7,12 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <http://www.gnu.org/licenses/>. diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c index 8d09ed91c4..76f439985a 100644 --- a/target/m68k/op_helper.c +++ b/target/m68k/op_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 752e46ef63..6217a683f1 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -7,12 +7,12 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <http://www.gnu.org/licenses/>. diff --git a/target/mips/cpu.h b/target/mips/cpu.h index c4da7dfbfd..473d26d6ff 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1173,7 +1173,7 @@ int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc); #define CPU_RESOLVING_TYPE TYPE_MIPS_CPU bool cpu_supports_cps_smp(const char *cpu_type); -bool cpu_supports_isa(const char *cpu_type, unsigned int isa); +bool cpu_supports_isa(const char *cpu_type, uint64_t isa); void cpu_set_exception_base(int vp_index, target_ulong address); /* mips_int.c */ diff --git a/target/mips/translate.c b/target/mips/translate.c index ab307c410c..e9b5d1d860 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -3714,7 +3714,7 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt, } static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset, - uint32_t reg1, uint32_t reg2) + uint32_t reg1, uint32_t reg2, bool eva) { TCGv taddr = tcg_temp_local_new(); TCGv lladdr = tcg_temp_local_new(); @@ -3742,7 +3742,7 @@ static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset, tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp)); tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval, - ctx->mem_idx, MO_64); + eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64); if (reg1 != 0) { tcg_gen_movi_tl(cpu_gpr[reg1], 1); } @@ -18460,10 +18460,9 @@ enum { /* extraction utilities */ -#define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7) -#define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7) -#define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op) -#define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7) +#define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7) +#define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7) +#define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7) #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f) #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f) @@ -18502,16 +18501,6 @@ static inline int decode_gpr_gpr4_zero(int r) } -/* extraction utilities */ - -#define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7) -#define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7) -#define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op) -#define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7) -#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f) -#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f) - - static void gen_adjust_sp(DisasContext *ctx, int u) { gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u); @@ -18570,8 +18559,8 @@ static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count, static void gen_pool16c_nanomips_insn(DisasContext *ctx) { - int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode)); - int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode)); + int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode)); + int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); switch (extract32(ctx->opcode, 2, 2)) { case NM_NOT16: @@ -19769,6 +19758,10 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc, goto out; } + /* branch completion */ + clear_branch_hflags(ctx); + ctx->base.is_jmp = DISAS_NORETURN; + if (bcond_compute == 0) { /* Uncoditional compact branch */ gen_goto_tb(ctx, 0, ctx->btarget); @@ -19809,6 +19802,10 @@ static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs, tcg_gen_movi_tl(t1, ctx->base.pc_next + 4); gen_op_addr_add(ctx, btarget, t1, t0); + /* branch completion */ + clear_branch_hflags(ctx); + ctx->base.is_jmp = DISAS_NORETURN; + /* unconditional branch to register */ tcg_gen_mov_tl(cpu_PC, btarget); tcg_gen_lookup_and_goto_ptr(); @@ -19947,6 +19944,10 @@ static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc, goto out; } + /* branch completion */ + clear_branch_hflags(ctx); + ctx->base.is_jmp = DISAS_NORETURN; + /* Generating branch here as compact branches don't have delay slot */ gen_goto_tb(ctx, 1, ctx->btarget); gen_set_label(fs); @@ -21561,7 +21562,8 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) break; case NM_SCWP: check_xnp(ctx); - gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5)); + gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5), + false); break; } break; @@ -21665,7 +21667,8 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) check_xnp(ctx); check_eva(ctx); check_cp0_enabled(ctx); - gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5)); + gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5), + true); break; default: generate_exception_end(ctx, EXCP_RI); @@ -21872,9 +21875,9 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx) { uint32_t op; - int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode)); - int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode)); - int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode)); + int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode)); + int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); + int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode)); int offset; int imm; @@ -22037,7 +22040,7 @@ static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx) break; case NM_SB16: rt = decode_gpr_gpr3_src_store( - NANOMIPS_EXTRACT_RD(ctx->opcode)); + NANOMIPS_EXTRACT_RT3(ctx->opcode)); gen_st(ctx, OPC_SB, rt, rs, offset); break; case NM_LBU16: @@ -22056,7 +22059,7 @@ static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx) break; case NM_SH16: rt = decode_gpr_gpr3_src_store( - NANOMIPS_EXTRACT_RD(ctx->opcode)); + NANOMIPS_EXTRACT_RT3(ctx->opcode)); gen_st(ctx, OPC_SH, rt, rs, offset); break; case NM_LHU16: @@ -22111,14 +22114,14 @@ static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx) break; case NM_SW16: rt = decode_gpr_gpr3_src_store( - NANOMIPS_EXTRACT_RD(ctx->opcode)); - rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode)); + NANOMIPS_EXTRACT_RT3(ctx->opcode)); + rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); offset = extract32(ctx->opcode, 0, 4) << 2; gen_st(ctx, OPC_SW, rt, rs, offset); break; case NM_SWGP16: rt = decode_gpr_gpr3_src_store( - NANOMIPS_EXTRACT_RD(ctx->opcode)); + NANOMIPS_EXTRACT_RT3(ctx->opcode)); offset = extract32(ctx->opcode, 0, 7) << 2; gen_st(ctx, OPC_SW, rt, 28, offset); break; @@ -29894,7 +29897,7 @@ bool cpu_supports_cps_smp(const char *cpu_type) return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0; } -bool cpu_supports_isa(const char *cpu_type, unsigned int isa) +bool cpu_supports_isa(const char *cpu_type, uint64_t isa) { const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type)); return (mcc->cpu_def->insn_flags & isa) != 0; diff --git a/target/mips/translate_init.inc.c b/target/mips/translate_init.inc.c index acab097820..bf559aff08 100644 --- a/target/mips/translate_init.inc.c +++ b/target/mips/translate_init.inc.c @@ -722,6 +722,46 @@ const mips_def_t mips_defs[] = .mmu_type = MMU_TYPE_R4000, }, { + .name = "I6500", + .CP0_PRid = 0x1B000, + .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AR) | (0x2 << CP0C0_AT) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) | + (2 << CP0C1_IS) | (5 << CP0C1_IL) | (3 << CP0C1_IA) | + (2 << CP0C1_DS) | (5 << CP0C1_DL) | (3 << CP0C1_DA) | + (0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP), + .CP0_Config2 = MIPS_CONFIG2, + .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | + (1 << CP0C3_CMGCR) | (1 << CP0C3_MSAP) | + (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | + (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt), + .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (3 << CP0C4_IE) | + (1 << CP0C4_AE) | (0xfc << CP0C4_KScrExist), + .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_VP) | + (1 << CP0C5_LLB) | (1 << CP0C5_MRP), + .CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_SBRI) | + (1 << CP0C5_FRE) | (1 << CP0C5_UFE), + .CP0_LLAddr_rw_bitmask = 0, + .CP0_LLAddr_shift = 0, + .SYNCI_Step = 64, + .CCRes = 2, + .CP0_Status_rw_bitmask = 0x30D8FFFF, + .CP0_PageGrain = (1 << CP0PG_IEC) | (1 << CP0PG_XIE) | + (1U << CP0PG_RIE), + .CP0_PageGrain_rw_bitmask = (1 << CP0PG_ELPA), + .CP0_EBaseWG_rw_bitmask = (1 << CP0EBase_WG), + .CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_HAS2008) | (1 << FCR0_F64) | + (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | + (1 << FCR0_S) | (0x03 << FCR0_PRID) | (0x0 << FCR0_REV), + .CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008), + .CP1_fcr31_rw_bitmask = 0x0103FFFF, + .MSAIR = 0x03 << MSAIR_ProcID, + .SEGBITS = 48, + .PABITS = 48, + .insn_flags = CPU_MIPS64R6 | ASE_MSA, + .mmu_type = MMU_TYPE_R4000, + }, + { .name = "Loongson-2E", .CP0_PRid = 0x6302, /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size. */ diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c index fb7cb5c507..541b2a66c7 100644 --- a/target/openrisc/cpu.c +++ b/target/openrisc/cpu.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/openrisc/exception.h b/target/openrisc/exception.h index 4ec56b4653..c9c4e471d2 100644 --- a/target/openrisc/exception.h +++ b/target/openrisc/exception.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/openrisc/gdbstub.c b/target/openrisc/gdbstub.c index f9af6507f3..43b1a18d4b 100644 --- a/target/openrisc/gdbstub.c +++ b/target/openrisc/gdbstub.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h index 9db9bf3963..96d79a8113 100644 --- a/target/openrisc/helper.h +++ b/target/openrisc/helper.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/openrisc/interrupt_helper.c b/target/openrisc/interrupt_helper.c index 9c5489f5f7..ab4ea88b69 100644 --- a/target/openrisc/interrupt_helper.c +++ b/target/openrisc/interrupt_helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index b66a45c1e0..05f66c455b 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index c089914d6a..89680f882d 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index a62ff60414..2c22292e7f 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1178,9 +1178,6 @@ do { \ typedef struct PPCVirtualHypervisor PPCVirtualHypervisor; typedef struct PPCVirtualHypervisorClass PPCVirtualHypervisorClass; -struct XiveTCTX; -struct ICPState; - /** * PowerPCCPU: * @env: #CPUPPCState @@ -1198,8 +1195,6 @@ struct PowerPCCPU { int vcpu_id; uint32_t compat_pvr; PPCVirtualHypervisor *vhyp; - struct ICPState *icp; - struct XiveTCTX *tctx; void *machine_data; int32_t node_id; /* NUMA node this CPU belongs to */ PPCHash64Options *hash64_opts; diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index 598731d47a..8efc283388 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -389,14 +389,6 @@ target_ulong helper_602_mfrom(target_ulong arg) /*****************************************************************************/ /* Altivec extension helpers */ #if defined(HOST_WORDS_BIGENDIAN) -#define HI_IDX 0 -#define LO_IDX 1 -#else -#define HI_IDX 1 -#define LO_IDX 0 -#endif - -#if defined(HOST_WORDS_BIGENDIAN) #define VECTOR_FOR_INORDER_I(index, element) \ for (index = 0; index < ARRAY_SIZE(r->element); index++) #else @@ -451,8 +443,8 @@ void helper_lvsl(ppc_avr_t *r, target_ulong sh) { int i, j = (sh & 0xf); - VECTOR_FOR_INORDER_I(i, u8) { - r->u8[i] = j++; + for (i = 0; i < ARRAY_SIZE(r->u8); i++) { + r->VsrB(i) = j++; } } @@ -460,18 +452,14 @@ void helper_lvsr(ppc_avr_t *r, target_ulong sh) { int i, j = 0x10 - (sh & 0xf); - VECTOR_FOR_INORDER_I(i, u8) { - r->u8[i] = j++; + for (i = 0; i < ARRAY_SIZE(r->u8); i++) { + r->VsrB(i) = j++; } } void helper_mtvscr(CPUPPCState *env, ppc_avr_t *r) { -#if defined(HOST_WORDS_BIGENDIAN) - env->vscr = r->u32[3]; -#else - env->vscr = r->u32[0]; -#endif + env->vscr = r->VsrW(3); set_flush_to_zero(vscr_nj, &env->vec_status); } @@ -514,8 +502,8 @@ void helper_vprtybq(ppc_avr_t *r, ppc_avr_t *b) res ^= res >> 32; res ^= res >> 16; res ^= res >> 8; - r->u64[LO_IDX] = res & 1; - r->u64[HI_IDX] = 0; + r->VsrD(1) = res & 1; + r->VsrD(0) = 0; } #define VARITH_DO(name, op, element) \ @@ -878,8 +866,8 @@ target_ulong helper_vclzlsbb(ppc_avr_t *r) { target_ulong count = 0; int i; - VECTOR_FOR_INORDER_I(i, u8) { - if (r->u8[i] & 0x01) { + for (i = 0; i < ARRAY_SIZE(r->u8); i++) { + if (r->VsrB(i) & 0x01) { break; } count++; @@ -891,12 +879,8 @@ target_ulong helper_vctzlsbb(ppc_avr_t *r) { target_ulong count = 0; int i; -#if defined(HOST_WORDS_BIGENDIAN) for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) { -#else - for (i = 0; i < ARRAY_SIZE(r->u8); i++) { -#endif - if (r->u8[i] & 0x01) { + if (r->VsrB(i) & 0x01) { break; } count++; @@ -976,43 +960,27 @@ void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) } } -#define VMRG_DO(name, element, highp) \ - void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ - { \ - ppc_avr_t result; \ - int i; \ - size_t n_elems = ARRAY_SIZE(r->element); \ - \ - for (i = 0; i < n_elems / 2; i++) { \ - if (highp) { \ - result.element[i*2+HI_IDX] = a->element[i]; \ - result.element[i*2+LO_IDX] = b->element[i]; \ - } else { \ - result.element[n_elems - i * 2 - (1 + HI_IDX)] = \ - b->element[n_elems - i - 1]; \ - result.element[n_elems - i * 2 - (1 + LO_IDX)] = \ - a->element[n_elems - i - 1]; \ - } \ - } \ - *r = result; \ - } -#if defined(HOST_WORDS_BIGENDIAN) -#define MRGHI 0 -#define MRGLO 1 -#else -#define MRGHI 1 -#define MRGLO 0 -#endif -#define VMRG(suffix, element) \ - VMRG_DO(mrgl##suffix, element, MRGHI) \ - VMRG_DO(mrgh##suffix, element, MRGLO) -VMRG(b, u8) -VMRG(h, u16) -VMRG(w, u32) +#define VMRG_DO(name, element, access, ofs) \ + void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ + { \ + ppc_avr_t result; \ + int i, half = ARRAY_SIZE(r->element) / 2; \ + \ + for (i = 0; i < half; i++) { \ + result.access(i * 2 + 0) = a->access(i + ofs); \ + result.access(i * 2 + 1) = b->access(i + ofs); \ + } \ + *r = result; \ + } + +#define VMRG(suffix, element, access) \ + VMRG_DO(mrgl##suffix, element, access, half) \ + VMRG_DO(mrgh##suffix, element, access, 0) +VMRG(b, u8, VsrB) +VMRG(h, u16, VsrH) +VMRG(w, u32, VsrW) #undef VMRG_DO #undef VMRG -#undef MRGHI -#undef MRGLO void helper_vmsummbm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) @@ -1120,33 +1088,39 @@ void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, } } -#define VMUL_DO(name, mul_element, prod_element, cast, evenp) \ +#define VMUL_DO_EVN(name, mul_element, mul_access, prod_access, cast) \ void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ { \ int i; \ \ - VECTOR_FOR_INORDER_I(i, prod_element) { \ - if (evenp) { \ - r->prod_element[i] = \ - (cast)a->mul_element[i * 2 + HI_IDX] * \ - (cast)b->mul_element[i * 2 + HI_IDX]; \ - } else { \ - r->prod_element[i] = \ - (cast)a->mul_element[i * 2 + LO_IDX] * \ - (cast)b->mul_element[i * 2 + LO_IDX]; \ - } \ + for (i = 0; i < ARRAY_SIZE(r->mul_element); i += 2) { \ + r->prod_access(i >> 1) = (cast)a->mul_access(i) * \ + (cast)b->mul_access(i); \ + } \ + } + +#define VMUL_DO_ODD(name, mul_element, mul_access, prod_access, cast) \ + void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ + { \ + int i; \ + \ + for (i = 0; i < ARRAY_SIZE(r->mul_element); i += 2) { \ + r->prod_access(i >> 1) = (cast)a->mul_access(i + 1) * \ + (cast)b->mul_access(i + 1); \ } \ } -#define VMUL(suffix, mul_element, prod_element, cast) \ - VMUL_DO(mule##suffix, mul_element, prod_element, cast, 1) \ - VMUL_DO(mulo##suffix, mul_element, prod_element, cast, 0) -VMUL(sb, s8, s16, int16_t) -VMUL(sh, s16, s32, int32_t) -VMUL(sw, s32, s64, int64_t) -VMUL(ub, u8, u16, uint16_t) -VMUL(uh, u16, u32, uint32_t) -VMUL(uw, u32, u64, uint64_t) -#undef VMUL_DO + +#define VMUL(suffix, mul_element, mul_access, prod_access, cast) \ + VMUL_DO_EVN(mule##suffix, mul_element, mul_access, prod_access, cast) \ + VMUL_DO_ODD(mulo##suffix, mul_element, mul_access, prod_access, cast) +VMUL(sb, s8, VsrSB, VsrSH, int16_t) +VMUL(sh, s16, VsrSH, VsrSW, int32_t) +VMUL(sw, s32, VsrSW, VsrSD, int64_t) +VMUL(ub, u8, VsrB, VsrH, uint16_t) +VMUL(uh, u16, VsrH, VsrW, uint32_t) +VMUL(uw, u32, VsrW, VsrD, uint64_t) +#undef VMUL_DO_EVN +#undef VMUL_DO_ODD #undef VMUL void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, @@ -1155,18 +1129,14 @@ void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t result; int i; - VECTOR_FOR_INORDER_I(i, u8) { - int s = c->u8[i] & 0x1f; -#if defined(HOST_WORDS_BIGENDIAN) + for (i = 0; i < ARRAY_SIZE(r->u8); i++) { + int s = c->VsrB(i) & 0x1f; int index = s & 0xf; -#else - int index = 15 - (s & 0xf); -#endif if (s & 0x10) { - result.u8[i] = b->u8[index]; + result.VsrB(i) = b->VsrB(index); } else { - result.u8[i] = a->u8[index]; + result.VsrB(i) = a->VsrB(index); } } *r = result; @@ -1178,18 +1148,14 @@ void helper_vpermr(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t result; int i; - VECTOR_FOR_INORDER_I(i, u8) { - int s = c->u8[i] & 0x1f; -#if defined(HOST_WORDS_BIGENDIAN) + for (i = 0; i < ARRAY_SIZE(r->u8); i++) { + int s = c->VsrB(i) & 0x1f; int index = 15 - (s & 0xf); -#else - int index = s & 0xf; -#endif if (s & 0x10) { - result.u8[i] = a->u8[index]; + result.VsrB(i) = a->VsrB(index); } else { - result.u8[i] = b->u8[index]; + result.VsrB(i) = b->VsrB(index); } } *r = result; @@ -1239,8 +1205,8 @@ void helper_vbpermq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) } } - r->u64[HI_IDX] = perm; - r->u64[LO_IDX] = 0; + r->VsrD(0) = perm; + r->VsrD(1) = 0; } #undef VBPERMQ_INDEX @@ -1569,25 +1535,25 @@ void helper_vpmsumd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) ppc_avr_t prod[2]; VECTOR_FOR_INORDER_I(i, u64) { - prod[i].u64[LO_IDX] = prod[i].u64[HI_IDX] = 0; + prod[i].VsrD(1) = prod[i].VsrD(0) = 0; for (j = 0; j < 64; j++) { if (a->u64[i] & (1ull<<j)) { ppc_avr_t bshift; if (j == 0) { - bshift.u64[HI_IDX] = 0; - bshift.u64[LO_IDX] = b->u64[i]; + bshift.VsrD(0) = 0; + bshift.VsrD(1) = b->u64[i]; } else { - bshift.u64[HI_IDX] = b->u64[i] >> (64-j); - bshift.u64[LO_IDX] = b->u64[i] << j; + bshift.VsrD(0) = b->u64[i] >> (64 - j); + bshift.VsrD(1) = b->u64[i] << j; } - prod[i].u64[LO_IDX] ^= bshift.u64[LO_IDX]; - prod[i].u64[HI_IDX] ^= bshift.u64[HI_IDX]; + prod[i].VsrD(1) ^= bshift.VsrD(1); + prod[i].VsrD(0) ^= bshift.VsrD(0); } } } - r->u64[LO_IDX] = prod[0].u64[LO_IDX] ^ prod[1].u64[LO_IDX]; - r->u64[HI_IDX] = prod[0].u64[HI_IDX] ^ prod[1].u64[HI_IDX]; + r->VsrD(1) = prod[0].VsrD(1) ^ prod[1].VsrD(1); + r->VsrD(0) = prod[0].VsrD(0) ^ prod[1].VsrD(0); #endif } @@ -1805,7 +1771,7 @@ VEXTU_X_DO(vextuwrx, 32, 0) #define VSHIFT(suffix, leftp) \ void helper_vs##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ { \ - int shift = b->u8[LO_IDX*15] & 0x7; \ + int shift = b->VsrB(15) & 0x7; \ int doit = 1; \ int i; \ \ @@ -1816,15 +1782,15 @@ VEXTU_X_DO(vextuwrx, 32, 0) if (shift == 0) { \ *r = *a; \ } else if (leftp) { \ - uint64_t carry = a->u64[LO_IDX] >> (64 - shift); \ + uint64_t carry = a->VsrD(1) >> (64 - shift); \ \ - r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry; \ - r->u64[LO_IDX] = a->u64[LO_IDX] << shift; \ + r->VsrD(0) = (a->VsrD(0) << shift) | carry; \ + r->VsrD(1) = a->VsrD(1) << shift; \ } else { \ - uint64_t carry = a->u64[HI_IDX] << (64 - shift); \ + uint64_t carry = a->VsrD(0) << (64 - shift); \ \ - r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry; \ - r->u64[HI_IDX] = a->u64[HI_IDX] >> shift; \ + r->VsrD(1) = (a->VsrD(1) >> shift) | carry; \ + r->VsrD(0) = a->VsrD(0) >> shift; \ } \ } \ } @@ -1886,31 +1852,20 @@ void helper_vsldoi(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift) int i; ppc_avr_t result; -#if defined(HOST_WORDS_BIGENDIAN) for (i = 0; i < ARRAY_SIZE(r->u8); i++) { int index = sh + i; if (index > 0xf) { - result.u8[i] = b->u8[index - 0x10]; - } else { - result.u8[i] = a->u8[index]; - } - } -#else - for (i = 0; i < ARRAY_SIZE(r->u8); i++) { - int index = (16 - sh) + i; - if (index > 0xf) { - result.u8[i] = a->u8[index - 0x10]; + result.VsrB(i) = b->VsrB(index - 0x10); } else { - result.u8[i] = b->u8[index]; + result.VsrB(i) = a->VsrB(index); } } -#endif *r = result; } void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { - int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf; + int sh = (b->VsrB(0xf) >> 3) & 0xf; #if defined(HOST_WORDS_BIGENDIAN) memmove(&r->u8[0], &a->u8[sh], 16 - sh); @@ -1923,25 +1878,20 @@ void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) /* Experimental testing shows that hardware masks the immediate. */ #define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1)) -#if defined(HOST_WORDS_BIGENDIAN) #define SPLAT_ELEMENT(element) _SPLAT_MASKED(element) -#else -#define SPLAT_ELEMENT(element) \ - (ARRAY_SIZE(r->element) - 1 - _SPLAT_MASKED(element)) -#endif -#define VSPLT(suffix, element) \ +#define VSPLT(suffix, element, access) \ void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \ { \ - uint32_t s = b->element[SPLAT_ELEMENT(element)]; \ + uint32_t s = b->access(SPLAT_ELEMENT(element)); \ int i; \ \ for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ - r->element[i] = s; \ + r->access(i) = s; \ } \ } -VSPLT(b, u8) -VSPLT(h, u16) -VSPLT(w, u32) +VSPLT(b, u8, VsrB) +VSPLT(h, u16, VsrH) +VSPLT(w, u32, VsrW) #undef VSPLT #undef SPLAT_ELEMENT #undef _SPLAT_MASKED @@ -2002,17 +1952,10 @@ void helper_xxextractuw(CPUPPCState *env, target_ulong xtn, getVSR(xbn, &xb, env); memset(&xt, 0, sizeof(xt)); -#if defined(HOST_WORDS_BIGENDIAN) ext_index = index; for (i = 0; i < es; i++, ext_index++) { - xt.u8[8 - es + i] = xb.u8[ext_index % 16]; - } -#else - ext_index = 15 - index; - for (i = es - 1; i >= 0; i--, ext_index--) { - xt.u8[8 + i] = xb.u8[ext_index % 16]; + xt.VsrB(8 - es + i) = xb.VsrB(ext_index % 16); } -#endif putVSR(xtn, &xt, env); } @@ -2027,41 +1970,34 @@ void helper_xxinsertw(CPUPPCState *env, target_ulong xtn, getVSR(xbn, &xb, env); getVSR(xtn, &xt, env); -#if defined(HOST_WORDS_BIGENDIAN) ins_index = index; for (i = 0; i < es && ins_index < 16; i++, ins_index++) { - xt.u8[ins_index] = xb.u8[8 - es + i]; + xt.VsrB(ins_index) = xb.VsrB(8 - es + i); } -#else - ins_index = 15 - index; - for (i = es - 1; i >= 0 && ins_index >= 0; i--, ins_index--) { - xt.u8[ins_index] = xb.u8[8 + i]; - } -#endif putVSR(xtn, &xt, env); } -#define VEXT_SIGNED(name, element, mask, cast, recast) \ +#define VEXT_SIGNED(name, element, cast) \ void helper_##name(ppc_avr_t *r, ppc_avr_t *b) \ { \ int i; \ - VECTOR_FOR_INORDER_I(i, element) { \ - r->element[i] = (recast)((cast)(b->element[i] & mask)); \ + for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ + r->element[i] = (cast)b->element[i]; \ } \ } -VEXT_SIGNED(vextsb2w, s32, UINT8_MAX, int8_t, int32_t) -VEXT_SIGNED(vextsb2d, s64, UINT8_MAX, int8_t, int64_t) -VEXT_SIGNED(vextsh2w, s32, UINT16_MAX, int16_t, int32_t) -VEXT_SIGNED(vextsh2d, s64, UINT16_MAX, int16_t, int64_t) -VEXT_SIGNED(vextsw2d, s64, UINT32_MAX, int32_t, int64_t) +VEXT_SIGNED(vextsb2w, s32, int8_t) +VEXT_SIGNED(vextsb2d, s64, int8_t) +VEXT_SIGNED(vextsh2w, s32, int16_t) +VEXT_SIGNED(vextsh2d, s64, int16_t) +VEXT_SIGNED(vextsw2d, s64, int32_t) #undef VEXT_SIGNED #define VNEG(name, element) \ void helper_##name(ppc_avr_t *r, ppc_avr_t *b) \ { \ int i; \ - VECTOR_FOR_INORDER_I(i, element) { \ + for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ r->element[i] = -b->element[i]; \ } \ } @@ -2106,7 +2042,7 @@ VSR(d, u64, 0x3F) void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { - int sh = (b->u8[LO_IDX * 0xf] >> 3) & 0xf; + int sh = (b->VsrB(0xf) >> 3) & 0xf; #if defined(HOST_WORDS_BIGENDIAN) memmove(&r->u8[sh], &a->u8[0], 16 - sh); @@ -2133,17 +2069,13 @@ void helper_vsumsws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) ppc_avr_t result; int sat = 0; -#if defined(HOST_WORDS_BIGENDIAN) - upper = ARRAY_SIZE(r->s32)-1; -#else - upper = 0; -#endif - t = (int64_t)b->s32[upper]; + upper = ARRAY_SIZE(r->s32) - 1; + t = (int64_t)b->VsrSW(upper); for (i = 0; i < ARRAY_SIZE(r->s32); i++) { - t += a->s32[i]; - result.s32[i] = 0; + t += a->VsrSW(i); + result.VsrSW(i) = 0; } - result.s32[upper] = cvtsdsw(t, &sat); + result.VsrSW(upper) = cvtsdsw(t, &sat); *r = result; if (sat) { @@ -2157,19 +2089,15 @@ void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) ppc_avr_t result; int sat = 0; -#if defined(HOST_WORDS_BIGENDIAN) upper = 1; -#else - upper = 0; -#endif for (i = 0; i < ARRAY_SIZE(r->u64); i++) { - int64_t t = (int64_t)b->s32[upper + i * 2]; + int64_t t = (int64_t)b->VsrSW(upper + i * 2); - result.u64[i] = 0; + result.VsrW(i) = 0; for (j = 0; j < ARRAY_SIZE(r->u64); j++) { - t += a->s32[2 * i + j]; + t += a->VsrSW(2 * i + j); } - result.s32[upper + i * 2] = cvtsdsw(t, &sat); + result.VsrSW(upper + i * 2) = cvtsdsw(t, &sat); } *r = result; @@ -2294,7 +2222,7 @@ VUPK(lsw, s64, s32, UPKLO) { \ int i; \ \ - VECTOR_FOR_INORDER_I(i, element) { \ + for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ r->element[i] = name(b->element[i]); \ } \ } @@ -2362,13 +2290,13 @@ static inline void avr_qw_not(ppc_avr_t *t, ppc_avr_t a) static int avr_qw_cmpu(ppc_avr_t a, ppc_avr_t b) { - if (a.u64[HI_IDX] < b.u64[HI_IDX]) { + if (a.VsrD(0) < b.VsrD(0)) { return -1; - } else if (a.u64[HI_IDX] > b.u64[HI_IDX]) { + } else if (a.VsrD(0) > b.VsrD(0)) { return 1; - } else if (a.u64[LO_IDX] < b.u64[LO_IDX]) { + } else if (a.VsrD(1) < b.VsrD(1)) { return -1; - } else if (a.u64[LO_IDX] > b.u64[LO_IDX]) { + } else if (a.VsrD(1) > b.VsrD(1)) { return 1; } else { return 0; @@ -2377,17 +2305,17 @@ static int avr_qw_cmpu(ppc_avr_t a, ppc_avr_t b) static void avr_qw_add(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b) { - t->u64[LO_IDX] = a.u64[LO_IDX] + b.u64[LO_IDX]; - t->u64[HI_IDX] = a.u64[HI_IDX] + b.u64[HI_IDX] + - (~a.u64[LO_IDX] < b.u64[LO_IDX]); + t->VsrD(1) = a.VsrD(1) + b.VsrD(1); + t->VsrD(0) = a.VsrD(0) + b.VsrD(0) + + (~a.VsrD(1) < b.VsrD(1)); } static int avr_qw_addc(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b) { ppc_avr_t not_a; - t->u64[LO_IDX] = a.u64[LO_IDX] + b.u64[LO_IDX]; - t->u64[HI_IDX] = a.u64[HI_IDX] + b.u64[HI_IDX] + - (~a.u64[LO_IDX] < b.u64[LO_IDX]); + t->VsrD(1) = a.VsrD(1) + b.VsrD(1); + t->VsrD(0) = a.VsrD(0) + b.VsrD(0) + + (~a.VsrD(1) < b.VsrD(1)); avr_qw_not(¬_a, a); return avr_qw_cmpu(not_a, b) < 0; } @@ -2409,11 +2337,11 @@ void helper_vaddeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) r->u128 = a->u128 + b->u128 + (c->u128 & 1); #else - if (c->u64[LO_IDX] & 1) { + if (c->VsrD(1) & 1) { ppc_avr_t tmp; - tmp.u64[HI_IDX] = 0; - tmp.u64[LO_IDX] = c->u64[LO_IDX] & 1; + tmp.VsrD(0) = 0; + tmp.VsrD(1) = c->VsrD(1) & 1; avr_qw_add(&tmp, *a, tmp); avr_qw_add(r, tmp, *b); } else { @@ -2431,8 +2359,8 @@ void helper_vaddcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) avr_qw_not(¬_a, *a); - r->u64[HI_IDX] = 0; - r->u64[LO_IDX] = (avr_qw_cmpu(not_a, *b) < 0); + r->VsrD(0) = 0; + r->VsrD(1) = (avr_qw_cmpu(not_a, *b) < 0); #endif } @@ -2447,7 +2375,7 @@ void helper_vaddecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) r->u128 = carry_out; #else - int carry_in = c->u64[LO_IDX] & 1; + int carry_in = c->VsrD(1) & 1; int carry_out = 0; ppc_avr_t tmp; @@ -2457,8 +2385,8 @@ void helper_vaddecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) ppc_avr_t one = QW_ONE; carry_out = avr_qw_addc(&tmp, tmp, one); } - r->u64[HI_IDX] = 0; - r->u64[LO_IDX] = carry_out; + r->VsrD(0) = 0; + r->VsrD(1) = carry_out; #endif } @@ -2486,8 +2414,8 @@ void helper_vsubeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) avr_qw_not(&tmp, *b); avr_qw_add(&sum, *a, tmp); - tmp.u64[HI_IDX] = 0; - tmp.u64[LO_IDX] = c->u64[LO_IDX] & 1; + tmp.VsrD(0) = 0; + tmp.VsrD(1) = c->VsrD(1) & 1; avr_qw_add(r, sum, tmp); #endif } @@ -2503,10 +2431,10 @@ void helper_vsubcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) ppc_avr_t tmp; avr_qw_not(&tmp, *b); avr_qw_add(&tmp, *a, tmp); - carry = ((tmp.s64[HI_IDX] == -1ull) && (tmp.s64[LO_IDX] == -1ull)); + carry = ((tmp.VsrSD(0) == -1ull) && (tmp.VsrSD(1) == -1ull)); } - r->u64[HI_IDX] = 0; - r->u64[LO_IDX] = carry; + r->VsrD(0) = 0; + r->VsrD(1) = carry; #endif } @@ -2517,17 +2445,17 @@ void helper_vsubecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) (~a->u128 < ~b->u128) || ((c->u128 & 1) && (a->u128 + ~b->u128 == (__uint128_t)-1)); #else - int carry_in = c->u64[LO_IDX] & 1; + int carry_in = c->VsrD(1) & 1; int carry_out = (avr_qw_cmpu(*a, *b) > 0); if (!carry_out && carry_in) { ppc_avr_t tmp; avr_qw_not(&tmp, *b); avr_qw_add(&tmp, *a, tmp); - carry_out = ((tmp.u64[HI_IDX] == -1ull) && (tmp.u64[LO_IDX] == -1ull)); + carry_out = ((tmp.VsrD(0) == -1ull) && (tmp.VsrD(1) == -1ull)); } - r->u64[HI_IDX] = 0; - r->u64[LO_IDX] = carry_out; + r->VsrD(0) = 0; + r->VsrD(1) = carry_out; #endif } @@ -2625,7 +2553,7 @@ static bool bcd_is_valid(ppc_avr_t *bcd) static int bcd_cmp_zero(ppc_avr_t *bcd) { - if (bcd->u64[HI_IDX] == 0 && (bcd->u64[LO_IDX] >> 4) == 0) { + if (bcd->VsrD(0) == 0 && (bcd->VsrD(1) >> 4) == 0) { return CRF_EQ; } else { return (bcd_get_sgn(bcd) == 1) ? CRF_GT : CRF_LT; @@ -2634,20 +2562,12 @@ static int bcd_cmp_zero(ppc_avr_t *bcd) static uint16_t get_national_digit(ppc_avr_t *reg, int n) { -#if defined(HOST_WORDS_BIGENDIAN) - return reg->u16[7 - n]; -#else - return reg->u16[n]; -#endif + return reg->VsrH(7 - n); } static void set_national_digit(ppc_avr_t *reg, uint8_t val, int n) { -#if defined(HOST_WORDS_BIGENDIAN) - reg->u16[7 - n] = val; -#else - reg->u16[n] = val; -#endif + reg->VsrH(7 - n) = val; } static int bcd_cmp_mag(ppc_avr_t *a, ppc_avr_t *b) @@ -2745,7 +2665,7 @@ uint32_t helper_bcdadd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) } if (unlikely(invalid)) { - result.u64[HI_IDX] = result.u64[LO_IDX] = -1; + result.VsrD(0) = result.VsrD(1) = -1; cr = CRF_SO; } else if (overflow) { cr |= CRF_SO; @@ -2814,7 +2734,7 @@ uint32_t helper_bcdctn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) int invalid = (sgnb == 0); ppc_avr_t ret = { .u64 = { 0, 0 } }; - int ox_flag = (b->u64[HI_IDX] != 0) || ((b->u64[LO_IDX] >> 32) != 0); + int ox_flag = (b->VsrD(0) != 0) || ((b->VsrD(1) >> 32) != 0); for (i = 1; i < 8; i++) { set_national_digit(&ret, 0x30 + bcd_get_digit(b, i, &invalid), i); @@ -2894,7 +2814,7 @@ uint32_t helper_bcdctz(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) int invalid = (sgnb == 0); ppc_avr_t ret = { .u64 = { 0, 0 } }; - int ox_flag = ((b->u64[HI_IDX] >> 4) != 0); + int ox_flag = ((b->VsrD(0) >> 4) != 0); for (i = 0; i < 16; i++) { digit = bcd_get_digit(b, i + 1, &invalid); @@ -2935,13 +2855,13 @@ uint32_t helper_bcdcfsq(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) uint64_t hi_value; ppc_avr_t ret = { .u64 = { 0, 0 } }; - if (b->s64[HI_IDX] < 0) { - lo_value = -b->s64[LO_IDX]; - hi_value = ~b->u64[HI_IDX] + !lo_value; + if (b->VsrSD(0) < 0) { + lo_value = -b->VsrSD(1); + hi_value = ~b->VsrD(0) + !lo_value; bcd_put_digit(&ret, 0xD, 0); } else { - lo_value = b->u64[LO_IDX]; - hi_value = b->u64[HI_IDX]; + lo_value = b->VsrD(1); + hi_value = b->VsrD(0); bcd_put_digit(&ret, bcd_preferred_sgn(0, ps), 0); } @@ -2989,11 +2909,11 @@ uint32_t helper_bcdctsq(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) } if (sgnb == -1) { - r->s64[LO_IDX] = -lo_value; - r->s64[HI_IDX] = ~hi_value + !r->s64[LO_IDX]; + r->VsrSD(1) = -lo_value; + r->VsrSD(0) = ~hi_value + !r->VsrSD(1); } else { - r->s64[LO_IDX] = lo_value; - r->s64[HI_IDX] = hi_value; + r->VsrSD(1) = lo_value; + r->VsrSD(0) = hi_value; } cr = bcd_cmp_zero(b); @@ -3053,7 +2973,7 @@ uint32_t helper_bcds(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) bool ox_flag = false; int sgnb = bcd_get_sgn(b); ppc_avr_t ret = *b; - ret.u64[LO_IDX] &= ~0xf; + ret.VsrD(1) &= ~0xf; if (bcd_is_valid(b) == false) { return CRF_SO; @@ -3066,9 +2986,9 @@ uint32_t helper_bcds(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) } if (i > 0) { - ulshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], i * 4, &ox_flag); + ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag); } else { - urshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], -i * 4); + urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4); } bcd_put_digit(&ret, bcd_preferred_sgn(sgnb, ps), 0); @@ -3105,13 +3025,13 @@ uint32_t helper_bcdus(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) #endif if (i >= 32) { ox_flag = true; - ret.u64[LO_IDX] = ret.u64[HI_IDX] = 0; + ret.VsrD(1) = ret.VsrD(0) = 0; } else if (i <= -32) { - ret.u64[LO_IDX] = ret.u64[HI_IDX] = 0; + ret.VsrD(1) = ret.VsrD(0) = 0; } else if (i > 0) { - ulshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], i * 4, &ox_flag); + ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag); } else { - urshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], -i * 4); + urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4); } *r = ret; @@ -3131,7 +3051,7 @@ uint32_t helper_bcdsr(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) bool ox_flag = false; int sgnb = bcd_get_sgn(b); ppc_avr_t ret = *b; - ret.u64[LO_IDX] &= ~0xf; + ret.VsrD(1) &= ~0xf; #if defined(HOST_WORDS_BIGENDIAN) int i = a->s8[7]; @@ -3152,9 +3072,9 @@ uint32_t helper_bcdsr(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) } if (i > 0) { - ulshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], i * 4, &ox_flag); + ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag); } else { - urshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], -i * 4); + urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4); if (bcd_get_digit(&ret, 0, &invalid) >= 5) { bcd_add_mag(&ret, &ret, &bcd_one, &invalid, &unused); @@ -3188,19 +3108,19 @@ uint32_t helper_bcdtrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) if (i > 16 && i < 32) { mask = (uint64_t)-1 >> (128 - i * 4); - if (ret.u64[HI_IDX] & ~mask) { + if (ret.VsrD(0) & ~mask) { ox_flag = CRF_SO; } - ret.u64[HI_IDX] &= mask; + ret.VsrD(0) &= mask; } else if (i >= 0 && i <= 16) { mask = (uint64_t)-1 >> (64 - i * 4); - if (ret.u64[HI_IDX] || (ret.u64[LO_IDX] & ~mask)) { + if (ret.VsrD(0) || (ret.VsrD(1) & ~mask)) { ox_flag = CRF_SO; } - ret.u64[LO_IDX] &= mask; - ret.u64[HI_IDX] = 0; + ret.VsrD(1) &= mask; + ret.VsrD(0) = 0; } bcd_put_digit(&ret, bcd_preferred_sgn(bcd_get_sgn(b), ps), 0); *r = ret; @@ -3231,28 +3151,28 @@ uint32_t helper_bcdutrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) #endif if (i > 16 && i < 33) { mask = (uint64_t)-1 >> (128 - i * 4); - if (ret.u64[HI_IDX] & ~mask) { + if (ret.VsrD(0) & ~mask) { ox_flag = CRF_SO; } - ret.u64[HI_IDX] &= mask; + ret.VsrD(0) &= mask; } else if (i > 0 && i <= 16) { mask = (uint64_t)-1 >> (64 - i * 4); - if (ret.u64[HI_IDX] || (ret.u64[LO_IDX] & ~mask)) { + if (ret.VsrD(0) || (ret.VsrD(1) & ~mask)) { ox_flag = CRF_SO; } - ret.u64[LO_IDX] &= mask; - ret.u64[HI_IDX] = 0; + ret.VsrD(1) &= mask; + ret.VsrD(0) = 0; } else if (i == 0) { - if (ret.u64[HI_IDX] || ret.u64[LO_IDX]) { + if (ret.VsrD(0) || ret.VsrD(1)) { ox_flag = CRF_SO; } - ret.u64[HI_IDX] = ret.u64[LO_IDX] = 0; + ret.VsrD(0) = ret.VsrD(1) = 0; } *r = ret; - if (r->u64[HI_IDX] == 0 && r->u64[LO_IDX] == 0) { + if (r->VsrD(0) == 0 && r->VsrD(1) == 0) { return ox_flag | CRF_EQ; } @@ -3324,108 +3244,83 @@ void helper_vncipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) *r = result; } -#define ROTRu32(v, n) (((v) >> (n)) | ((v) << (32-n))) -#if defined(HOST_WORDS_BIGENDIAN) -#define EL_IDX(i) (i) -#else -#define EL_IDX(i) (3 - (i)) -#endif - void helper_vshasigmaw(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six) { int st = (st_six & 0x10) != 0; int six = st_six & 0xF; int i; - VECTOR_FOR_INORDER_I(i, u32) { + for (i = 0; i < ARRAY_SIZE(r->u32); i++) { if (st == 0) { if ((six & (0x8 >> i)) == 0) { - r->u32[EL_IDX(i)] = ROTRu32(a->u32[EL_IDX(i)], 7) ^ - ROTRu32(a->u32[EL_IDX(i)], 18) ^ - (a->u32[EL_IDX(i)] >> 3); + r->VsrW(i) = ror32(a->VsrW(i), 7) ^ + ror32(a->VsrW(i), 18) ^ + (a->VsrW(i) >> 3); } else { /* six.bit[i] == 1 */ - r->u32[EL_IDX(i)] = ROTRu32(a->u32[EL_IDX(i)], 17) ^ - ROTRu32(a->u32[EL_IDX(i)], 19) ^ - (a->u32[EL_IDX(i)] >> 10); + r->VsrW(i) = ror32(a->VsrW(i), 17) ^ + ror32(a->VsrW(i), 19) ^ + (a->VsrW(i) >> 10); } } else { /* st == 1 */ if ((six & (0x8 >> i)) == 0) { - r->u32[EL_IDX(i)] = ROTRu32(a->u32[EL_IDX(i)], 2) ^ - ROTRu32(a->u32[EL_IDX(i)], 13) ^ - ROTRu32(a->u32[EL_IDX(i)], 22); + r->VsrW(i) = ror32(a->VsrW(i), 2) ^ + ror32(a->VsrW(i), 13) ^ + ror32(a->VsrW(i), 22); } else { /* six.bit[i] == 1 */ - r->u32[EL_IDX(i)] = ROTRu32(a->u32[EL_IDX(i)], 6) ^ - ROTRu32(a->u32[EL_IDX(i)], 11) ^ - ROTRu32(a->u32[EL_IDX(i)], 25); + r->VsrW(i) = ror32(a->VsrW(i), 6) ^ + ror32(a->VsrW(i), 11) ^ + ror32(a->VsrW(i), 25); } } } } -#undef ROTRu32 -#undef EL_IDX - -#define ROTRu64(v, n) (((v) >> (n)) | ((v) << (64-n))) -#if defined(HOST_WORDS_BIGENDIAN) -#define EL_IDX(i) (i) -#else -#define EL_IDX(i) (1 - (i)) -#endif - void helper_vshasigmad(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six) { int st = (st_six & 0x10) != 0; int six = st_six & 0xF; int i; - VECTOR_FOR_INORDER_I(i, u64) { + for (i = 0; i < ARRAY_SIZE(r->u64); i++) { if (st == 0) { if ((six & (0x8 >> (2*i))) == 0) { - r->u64[EL_IDX(i)] = ROTRu64(a->u64[EL_IDX(i)], 1) ^ - ROTRu64(a->u64[EL_IDX(i)], 8) ^ - (a->u64[EL_IDX(i)] >> 7); + r->VsrD(i) = ror64(a->VsrD(i), 1) ^ + ror64(a->VsrD(i), 8) ^ + (a->VsrD(i) >> 7); } else { /* six.bit[2*i] == 1 */ - r->u64[EL_IDX(i)] = ROTRu64(a->u64[EL_IDX(i)], 19) ^ - ROTRu64(a->u64[EL_IDX(i)], 61) ^ - (a->u64[EL_IDX(i)] >> 6); + r->VsrD(i) = ror64(a->VsrD(i), 19) ^ + ror64(a->VsrD(i), 61) ^ + (a->VsrD(i) >> 6); } } else { /* st == 1 */ if ((six & (0x8 >> (2*i))) == 0) { - r->u64[EL_IDX(i)] = ROTRu64(a->u64[EL_IDX(i)], 28) ^ - ROTRu64(a->u64[EL_IDX(i)], 34) ^ - ROTRu64(a->u64[EL_IDX(i)], 39); + r->VsrD(i) = ror64(a->VsrD(i), 28) ^ + ror64(a->VsrD(i), 34) ^ + ror64(a->VsrD(i), 39); } else { /* six.bit[2*i] == 1 */ - r->u64[EL_IDX(i)] = ROTRu64(a->u64[EL_IDX(i)], 14) ^ - ROTRu64(a->u64[EL_IDX(i)], 18) ^ - ROTRu64(a->u64[EL_IDX(i)], 41); + r->VsrD(i) = ror64(a->VsrD(i), 14) ^ + ror64(a->VsrD(i), 18) ^ + ror64(a->VsrD(i), 41); } } } } -#undef ROTRu64 -#undef EL_IDX - void helper_vpermxor(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) { ppc_avr_t result; int i; - VECTOR_FOR_INORDER_I(i, u8) { - int indexA = c->u8[i] >> 4; - int indexB = c->u8[i] & 0xF; -#if defined(HOST_WORDS_BIGENDIAN) - result.u8[i] = a->u8[indexA] ^ b->u8[indexB]; -#else - result.u8[i] = a->u8[15-indexA] ^ b->u8[15-indexB]; -#endif + for (i = 0; i < ARRAY_SIZE(r->u8); i++) { + int indexA = c->VsrB(i) >> 4; + int indexB = c->VsrB(i) & 0xF; + + result.VsrB(i) = a->VsrB(indexA) ^ b->VsrB(indexB); } *r = result; } #undef VECTOR_FOR_INORDER_I -#undef HI_IDX -#undef LO_IDX /*****************************************************************************/ /* SPE extension helpers */ diff --git a/target/ppc/internal.h b/target/ppc/internal.h index c7c0f77dd6..f26a71ffcf 100644 --- a/target/ppc/internal.h +++ b/target/ppc/internal.h @@ -206,16 +206,23 @@ EXTRACT_HELPER_SPLIT_3(DCMX_XV, 5, 16, 0, 1, 2, 5, 1, 6, 6); #if defined(HOST_WORDS_BIGENDIAN) #define VsrB(i) u8[i] +#define VsrSB(i) s8[i] #define VsrH(i) u16[i] +#define VsrSH(i) s16[i] #define VsrW(i) u32[i] +#define VsrSW(i) s32[i] #define VsrD(i) u64[i] +#define VsrSD(i) s64[i] #else #define VsrB(i) u8[15 - (i)] +#define VsrSB(i) s8[15 - (i)] #define VsrH(i) u16[7 - (i)] +#define VsrSH(i) s16[7 - (i)] #define VsrW(i) u32[3 - (i)] +#define VsrSW(i) s32[3 - (i)] #define VsrD(i) u64[1 - (i)] +#define VsrSD(i) s64[1 - (i)] #endif - static inline void getVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env) { vsr->VsrD(0) = env->vsr[n].u64[0]; diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index ebbb48c42f..d01852fe31 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -36,7 +36,6 @@ #include "hw/sysbus.h" #include "hw/ppc/spapr.h" -#include "hw/ppc/spapr_vio.h" #include "hw/ppc/spapr_cpu_core.h" #include "hw/ppc/ppc.h" #include "sysemu/watchdog.h" diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c index ade06cc773..59e0b86762 100644 --- a/target/ppc/translate_init.inc.c +++ b/target/ppc/translate_init.inc.c @@ -4947,14 +4947,6 @@ static void init_proc_e500(CPUPPCState *env, int version) } if (version == fsl_e6500) { - spr_register(env, SPR_BOOKE_SPRG8, "SPRG8", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - spr_register(env, SPR_BOOKE_SPRG9, "SPRG9", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); /* Thread identification */ spr_register(env, SPR_TIR, "TIR", SPR_NOACCESS, SPR_NOACCESS, diff --git a/target/s390x/cc_helper.c b/target/s390x/cc_helper.c index 5d91e458a8..307ad61aee 100644 --- a/target/s390x/cc_helper.c +++ b/target/s390x/cc_helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c index 2a33222f7e..a758649f47 100644 --- a/target/s390x/excp_helper.c +++ b/target/s390x/excp_helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c index 1b662d2520..e921172bc4 100644 --- a/target/s390x/fpu_helper.c +++ b/target/s390x/fpu_helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/s390x/gdbstub.c b/target/s390x/gdbstub.c index b8c81dadcf..df147596ce 100644 --- a/target/s390x/gdbstub.c +++ b/target/s390x/gdbstub.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/s390x/helper.c b/target/s390x/helper.c index 254631693d..3d74836a83 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/s390x/int_helper.c b/target/s390x/int_helper.c index abf77a94e6..abbbc20d9c 100644 --- a/target/s390x/int_helper.c +++ b/target/s390x/int_helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 490c43e6e6..a506d9ef99 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c index 3f91579570..52262f62df 100644 --- a/target/s390x/misc_helper.c +++ b/target/s390x/misc_helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/s390x/translate.c b/target/s390x/translate.c index b5bd56b7ee..6249c70d02 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/tricore/cpu-qom.h b/target/tricore/cpu-qom.h index 6a69756126..93c9d77fe3 100644 --- a/target/tricore/cpu-qom.h +++ b/target/tricore/cpu-qom.h @@ -4,7 +4,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c index 2edaef1aef..e8d37e4040 100644 --- a/target/tricore/cpu.c +++ b/target/tricore/cpu.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h index c3665c6ddd..00e69dc154 100644 --- a/target/tricore/cpu.h +++ b/target/tricore/cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/tricore/fpu_helper.c b/target/tricore/fpu_helper.c index 31df462e4a..d8a6c0d25b 100644 --- a/target/tricore/fpu_helper.c +++ b/target/tricore/fpu_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/tricore/helper.c b/target/tricore/helper.c index dad7eea085..0769046993 100644 --- a/target/tricore/helper.c +++ b/target/tricore/helper.c @@ -4,7 +4,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/tricore/helper.h b/target/tricore/helper.h index e634d0c680..f60e81096b 100644 --- a/target/tricore/helper.h +++ b/target/tricore/helper.h @@ -4,7 +4,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c index b57f35387d..ed9dc0c83e 100644 --- a/target/tricore/op_helper.c +++ b/target/tricore/op_helper.c @@ -4,7 +4,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/tricore/translate.c b/target/tricore/translate.c index b5ab40d4a2..14f0ddfa1e 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/tricore/tricore-defs.h b/target/tricore/tricore-defs.h index 40abfaac14..e871aa1c6b 100644 --- a/target/tricore/tricore-defs.h +++ b/target/tricore/tricore-defs.h @@ -4,7 +4,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/tricore/tricore-opcodes.h b/target/tricore/tricore-opcodes.h index 2c3baab694..40bc121ba4 100644 --- a/target/tricore/tricore-opcodes.h +++ b/target/tricore/tricore-opcodes.h @@ -4,7 +4,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of |