提交 0ca540db 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20140310' into staging

target-arm queue:
 * implement WFE as yield (improves performance with emulated SMP)
 * fixes to avoid undefined behaviour shifting left into sign bit
 * libvixl format string fixes for 32 bit hosts
 * fix build error when intptr_t and tcg_target_long are different
   sizes (eg x32)
 * implement PMCCNTR register
 * fix incorrect setting of E bit in CPSR (broke booting under
   KVM on ARM)

# gpg: Signature made Mon 10 Mar 2014 15:05:25 GMT using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"

* remotes/pmaydell/tags/pull-target-arm-20140310:
  target-arm: Implement WFE as a yield operation
  hw/arm/musicpal: Avoid shifting left into sign bit
  hw/ssi/xilinx_spips.c: Avoid shifting left into sign bit
  hw/arm/omap1.c: Avoid shifting left into sign bit
  pxa2xx: Don't shift into sign bit
  libvixl: Fix format strings for several int64_t values
  target-arm: Fix intptr_t vs tcg_target_long
  target-arm: Implements the ARM PMCCNTR register
  target-arm: Fix incorrect setting of E bit in CPSR
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
...@@ -1342,7 +1342,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr, ...@@ -1342,7 +1342,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
ASSERT(format[5] == 'L'); ASSERT(format[5] == 'L');
AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide()); AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
if (instr->ShiftMoveWide() > 0) { if (instr->ShiftMoveWide() > 0) {
AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide()); AppendToOutput(", lsl #%" PRId64, 16 * instr->ShiftMoveWide());
} }
} }
return 8; return 8;
...@@ -1391,7 +1391,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr, ...@@ -1391,7 +1391,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
} }
case 'F': { // IFPSingle, IFPDouble or IFPFBits. case 'F': { // IFPSingle, IFPDouble or IFPFBits.
if (format[3] == 'F') { // IFPFbits. if (format[3] == 'F') { // IFPFbits.
AppendToOutput("#%d", 64 - instr->FPScale()); AppendToOutput("#%" PRId64, 64 - instr->FPScale());
return 8; return 8;
} else { } else {
AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(), AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(),
...@@ -1412,23 +1412,23 @@ int Disassembler::SubstituteImmediateField(Instruction* instr, ...@@ -1412,23 +1412,23 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
return 5; return 5;
} }
case 'P': { // IP - Conditional compare. case 'P': { // IP - Conditional compare.
AppendToOutput("#%d", instr->ImmCondCmp()); AppendToOutput("#%" PRId64, instr->ImmCondCmp());
return 2; return 2;
} }
case 'B': { // Bitfields. case 'B': { // Bitfields.
return SubstituteBitfieldImmediateField(instr, format); return SubstituteBitfieldImmediateField(instr, format);
} }
case 'E': { // IExtract. case 'E': { // IExtract.
AppendToOutput("#%d", instr->ImmS()); AppendToOutput("#%" PRId64, instr->ImmS());
return 8; return 8;
} }
case 'S': { // IS - Test and branch bit. case 'S': { // IS - Test and branch bit.
AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) | AppendToOutput("#%" PRId64, (instr->ImmTestBranchBit5() << 5) |
instr->ImmTestBranchBit40()); instr->ImmTestBranchBit40());
return 2; return 2;
} }
case 'D': { // IDebug - HLT and BRK instructions. case 'D': { // IDebug - HLT and BRK instructions.
AppendToOutput("#0x%x", instr->ImmException()); AppendToOutput("#0x%" PRIx64, instr->ImmException());
return 6; return 6;
} }
default: { default: {
...@@ -1598,12 +1598,12 @@ int Disassembler::SubstituteExtendField(Instruction* instr, ...@@ -1598,12 +1598,12 @@ int Disassembler::SubstituteExtendField(Instruction* instr,
(((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) || (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
(instr->ExtendMode() == UXTX))) { (instr->ExtendMode() == UXTX))) {
if (instr->ImmExtendShift() > 0) { if (instr->ImmExtendShift() > 0) {
AppendToOutput(", lsl #%d", instr->ImmExtendShift()); AppendToOutput(", lsl #%" PRId64, instr->ImmExtendShift());
} }
} else { } else {
AppendToOutput(", %s", extend_mode[instr->ExtendMode()]); AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
if (instr->ImmExtendShift() > 0) { if (instr->ImmExtendShift() > 0) {
AppendToOutput(" #%d", instr->ImmExtendShift()); AppendToOutput(" #%" PRId64, instr->ImmExtendShift());
} }
} }
return 3; return 3;
...@@ -1632,7 +1632,7 @@ int Disassembler::SubstituteLSRegOffsetField(Instruction* instr, ...@@ -1632,7 +1632,7 @@ int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
if (!((ext == UXTX) && (shift == 0))) { if (!((ext == UXTX) && (shift == 0))) {
AppendToOutput(", %s", extend_mode[ext]); AppendToOutput(", %s", extend_mode[ext]);
if (shift != 0) { if (shift != 0) {
AppendToOutput(" #%d", instr->SizeLS()); AppendToOutput(" #%" PRId64, instr->SizeLS());
} }
} }
return 9; return 9;
......
...@@ -110,10 +110,10 @@ ...@@ -110,10 +110,10 @@
#define MP_PHY_88E3015 0x01410E20 #define MP_PHY_88E3015 0x01410E20
/* TX descriptor status */ /* TX descriptor status */
#define MP_ETH_TX_OWN (1 << 31) #define MP_ETH_TX_OWN (1U << 31)
/* RX descriptor status */ /* RX descriptor status */
#define MP_ETH_RX_OWN (1 << 31) #define MP_ETH_RX_OWN (1U << 31)
/* Interrupt cause/mask bits */ /* Interrupt cause/mask bits */
#define MP_ETH_IRQ_RX_BIT 0 #define MP_ETH_IRQ_RX_BIT 0
......
...@@ -809,22 +809,26 @@ static inline void omap_pin_funcmux1_update(struct omap_mpu_state_s *s, ...@@ -809,22 +809,26 @@ static inline void omap_pin_funcmux1_update(struct omap_mpu_state_s *s,
uint32_t diff, uint32_t value) uint32_t diff, uint32_t value)
{ {
if (s->compat1509) { if (s->compat1509) {
if (diff & (1 << 31)) /* MCBSP3_CLK_HIZ_DI */ if (diff & (1U << 31)) {
omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"), /* MCBSP3_CLK_HIZ_DI */
(value >> 31) & 1); omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"), (value >> 31) & 1);
if (diff & (1 << 1)) /* CLK32K */ }
omap_clk_onoff(omap_findclk(s, "clk32k_out"), if (diff & (1 << 1)) {
(~value >> 1) & 1); /* CLK32K */
omap_clk_onoff(omap_findclk(s, "clk32k_out"), (~value >> 1) & 1);
}
} }
} }
static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s, static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
uint32_t diff, uint32_t value) uint32_t diff, uint32_t value)
{ {
if (diff & (1 << 31)) /* CONF_MOD_UART3_CLK_MODE_R */ if (diff & (1U << 31)) {
omap_clk_reparent(omap_findclk(s, "uart3_ck"), /* CONF_MOD_UART3_CLK_MODE_R */
omap_findclk(s, ((value >> 31) & 1) ? omap_clk_reparent(omap_findclk(s, "uart3_ck"),
"ck_48m" : "armper_ck")); omap_findclk(s, ((value >> 31) & 1) ?
"ck_48m" : "armper_ck"));
}
if (diff & (1 << 30)) /* CONF_MOD_UART2_CLK_MODE_R */ if (diff & (1 << 30)) /* CONF_MOD_UART2_CLK_MODE_R */
omap_clk_reparent(omap_findclk(s, "uart2_ck"), omap_clk_reparent(omap_findclk(s, "uart2_ck"),
omap_findclk(s, ((value >> 30) & 1) ? omap_findclk(s, ((value >> 30) & 1) ?
......
...@@ -259,7 +259,7 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri, ...@@ -259,7 +259,7 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
case 1: case 1:
/* Idle */ /* Idle */
if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) { /* CPDIS */ if (!(s->cm_regs[CCCR >> 2] & (1U << 31))) { /* CPDIS */
cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT); cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
break; break;
} }
...@@ -496,7 +496,7 @@ typedef struct { ...@@ -496,7 +496,7 @@ typedef struct {
#define SSCR0_SSE (1 << 7) #define SSCR0_SSE (1 << 7)
#define SSCR0_RIM (1 << 22) #define SSCR0_RIM (1 << 22)
#define SSCR0_TIM (1 << 23) #define SSCR0_TIM (1 << 23)
#define SSCR0_MOD (1 << 31) #define SSCR0_MOD (1U << 31)
#define SSCR0_DSS(x) (((((x) >> 16) & 0x10) | ((x) & 0xf)) + 1) #define SSCR0_DSS(x) (((((x) >> 16) & 0x10) | ((x) & 0xf)) + 1)
#define SSCR1_RIE (1 << 0) #define SSCR1_RIE (1 << 0)
#define SSCR1_TIE (1 << 1) #define SSCR1_TIE (1 << 1)
...@@ -1006,7 +1006,7 @@ static void pxa2xx_rtc_write(void *opaque, hwaddr addr, ...@@ -1006,7 +1006,7 @@ static void pxa2xx_rtc_write(void *opaque, hwaddr addr,
switch (addr) { switch (addr) {
case RTTR: case RTTR:
if (!(s->rttr & (1 << 31))) { if (!(s->rttr & (1U << 31))) {
pxa2xx_rtc_hzupdate(s); pxa2xx_rtc_hzupdate(s);
s->rttr = value; s->rttr = value;
pxa2xx_rtc_alarm_update(s, s->rtsr); pxa2xx_rtc_alarm_update(s, s->rtsr);
......
...@@ -110,7 +110,7 @@ static void pxa2xx_gpio_set(void *opaque, int line, int level) ...@@ -110,7 +110,7 @@ static void pxa2xx_gpio_set(void *opaque, int line, int level)
} }
bank = line >> 5; bank = line >> 5;
mask = 1 << (line & 31); mask = 1U << (line & 31);
if (level) { if (level) {
s->status[bank] |= s->rising[bank] & mask & s->status[bank] |= s->rising[bank] & mask &
......
...@@ -105,7 +105,7 @@ static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) { ...@@ -105,7 +105,7 @@ static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) {
for (i = PXA2XX_PIC_SRCS - 1; i >= 0; i --) { for (i = PXA2XX_PIC_SRCS - 1; i >= 0; i --) {
irq = s->priority[i] & 0x3f; irq = s->priority[i] & 0x3f;
if ((s->priority[i] & (1 << 31)) && irq < PXA2XX_PIC_SRCS) { if ((s->priority[i] & (1U << 31)) && irq < PXA2XX_PIC_SRCS) {
/* Source peripheral ID is valid. */ /* Source peripheral ID is valid. */
bit = 1 << (irq & 31); bit = 1 << (irq & 31);
int_set = (irq >= 32); int_set = (irq >= 32);
...@@ -119,7 +119,7 @@ static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) { ...@@ -119,7 +119,7 @@ static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) {
if (mask[int_set] & bit & ~s->is_fiq[int_set]) { if (mask[int_set] & bit & ~s->is_fiq[int_set]) {
/* IRQ asserted */ /* IRQ asserted */
ichp &= 0x0000ffff; ichp &= 0x0000ffff;
ichp |= (1 << 31) | (irq << 16); ichp |= (1U << 31) | (irq << 16);
} }
} }
} }
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
/* config register */ /* config register */
#define R_CONFIG (0x00 / 4) #define R_CONFIG (0x00 / 4)
#define IFMODE (1 << 31) #define IFMODE (1U << 31)
#define ENDIAN (1 << 26) #define ENDIAN (1 << 26)
#define MODEFAIL_GEN_EN (1 << 17) #define MODEFAIL_GEN_EN (1 << 17)
#define MAN_START_COM (1 << 16) #define MAN_START_COM (1 << 16)
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
#define R_LQSPI_CFG (0xa0 / 4) #define R_LQSPI_CFG (0xa0 / 4)
#define R_LQSPI_CFG_RESET 0x03A002EB #define R_LQSPI_CFG_RESET 0x03A002EB
#define LQSPI_CFG_LQ_MODE (1 << 31) #define LQSPI_CFG_LQ_MODE (1U << 31)
#define LQSPI_CFG_TWO_MEM (1 << 30) #define LQSPI_CFG_TWO_MEM (1 << 30)
#define LQSPI_CFG_SEP_BUS (1 << 30) #define LQSPI_CFG_SEP_BUS (1 << 30)
#define LQSPI_CFG_U_PAGE (1 << 28) #define LQSPI_CFG_U_PAGE (1 << 28)
......
...@@ -59,6 +59,7 @@ typedef uint64_t target_ulong; ...@@ -59,6 +59,7 @@ typedef uint64_t target_ulong;
#define EXCP_HLT 0x10001 /* hlt instruction reached */ #define EXCP_HLT 0x10001 /* hlt instruction reached */
#define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */ #define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */
#define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */ #define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */
#define EXCP_YIELD 0x10004 /* cpu wants to yield timeslice to another */
#define TB_JMP_CACHE_BITS 12 #define TB_JMP_CACHE_BITS 12
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
......
...@@ -222,6 +222,10 @@ typedef struct CPUARMState { ...@@ -222,6 +222,10 @@ typedef struct CPUARMState {
uint64_t dbgbcr[16]; /* breakpoint control registers */ uint64_t dbgbcr[16]; /* breakpoint control registers */
uint64_t dbgwvr[16]; /* watchpoint value registers */ uint64_t dbgwvr[16]; /* watchpoint value registers */
uint64_t dbgwcr[16]; /* watchpoint control registers */ uint64_t dbgwcr[16]; /* watchpoint control registers */
/* If the counter is enabled, this stores the last time the counter
* was reset. Otherwise it stores the counter value
*/
uint32_t c15_ccnt;
} cp15; } cp15;
struct { struct {
......
...@@ -13,6 +13,11 @@ static inline int get_phys_addr(CPUARMState *env, uint32_t address, ...@@ -13,6 +13,11 @@ static inline int get_phys_addr(CPUARMState *env, uint32_t address,
int access_type, int is_user, int access_type, int is_user,
hwaddr *phys_ptr, int *prot, hwaddr *phys_ptr, int *prot,
target_ulong *page_size); target_ulong *page_size);
/* Definitions for the PMCCNTR and PMCR registers */
#define PMCRD 0x8
#define PMCRC 0x4
#define PMCRE 0x1
#endif #endif
static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg) static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
...@@ -478,13 +483,84 @@ static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri) ...@@ -478,13 +483,84 @@ static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri)
return CP_ACCESS_OK; return CP_ACCESS_OK;
} }
#ifndef CONFIG_USER_ONLY
static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri, static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value) uint64_t value)
{ {
/* Don't computer the number of ticks in user mode */
uint32_t temp_ticks;
temp_ticks = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) *
get_ticks_per_sec() / 1000000;
if (env->cp15.c9_pmcr & PMCRE) {
/* If the counter is enabled */
if (env->cp15.c9_pmcr & PMCRD) {
/* Increment once every 64 processor clock cycles */
env->cp15.c15_ccnt = (temp_ticks/64) - env->cp15.c15_ccnt;
} else {
env->cp15.c15_ccnt = temp_ticks - env->cp15.c15_ccnt;
}
}
if (value & PMCRC) {
/* The counter has been reset */
env->cp15.c15_ccnt = 0;
}
/* only the DP, X, D and E bits are writable */ /* only the DP, X, D and E bits are writable */
env->cp15.c9_pmcr &= ~0x39; env->cp15.c9_pmcr &= ~0x39;
env->cp15.c9_pmcr |= (value & 0x39); env->cp15.c9_pmcr |= (value & 0x39);
if (env->cp15.c9_pmcr & PMCRE) {
if (env->cp15.c9_pmcr & PMCRD) {
/* Increment once every 64 processor clock cycles */
temp_ticks /= 64;
}
env->cp15.c15_ccnt = temp_ticks - env->cp15.c15_ccnt;
}
}
static uint64_t pmccntr_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
uint32_t total_ticks;
if (!(env->cp15.c9_pmcr & PMCRE)) {
/* Counter is disabled, do not change value */
return env->cp15.c15_ccnt;
}
total_ticks = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) *
get_ticks_per_sec() / 1000000;
if (env->cp15.c9_pmcr & PMCRD) {
/* Increment once every 64 processor clock cycles */
total_ticks /= 64;
}
return total_ticks - env->cp15.c15_ccnt;
}
static void pmccntr_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
uint32_t total_ticks;
if (!(env->cp15.c9_pmcr & PMCRE)) {
/* Counter is disabled, set the absolute value */
env->cp15.c15_ccnt = value;
return;
}
total_ticks = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) *
get_ticks_per_sec() / 1000000;
if (env->cp15.c9_pmcr & PMCRD) {
/* Increment once every 64 processor clock cycles */
total_ticks /= 64;
}
env->cp15.c15_ccnt = total_ticks - value;
} }
#endif
static void pmcntenset_write(CPUARMState *env, const ARMCPRegInfo *ri, static void pmcntenset_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value) uint64_t value)
...@@ -604,10 +680,12 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { ...@@ -604,10 +680,12 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
{ .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5, { .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5,
.access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0, .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0,
.accessfn = pmreg_access }, .accessfn = pmreg_access },
/* Unimplemented, RAZ/WI. */ #ifndef CONFIG_USER_ONLY
{ .name = "PMCCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0, { .name = "PMCCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0,
.access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0, .access = PL0_RW, .resetvalue = 0, .type = ARM_CP_IO,
.readfn = pmccntr_read, .writefn = pmccntr_write,
.accessfn = pmreg_access }, .accessfn = pmreg_access },
#endif
{ .name = "PMXEVTYPER", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 1, { .name = "PMXEVTYPER", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 1,
.access = PL0_RW, .access = PL0_RW,
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmxevtyper), .fieldoffset = offsetof(CPUARMState, cp15.c9_pmxevtyper),
...@@ -1873,8 +1951,10 @@ void register_cp_regs_for_features(ARMCPU *cpu) ...@@ -1873,8 +1951,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
} }
if (arm_feature(env, ARM_FEATURE_V7)) { if (arm_feature(env, ARM_FEATURE_V7)) {
/* v7 performance monitor control register: same implementor /* v7 performance monitor control register: same implementor
* field as main ID register, and we implement no event counters. * field as main ID register, and we implement only the cycle
* count register.
*/ */
#ifndef CONFIG_USER_ONLY
ARMCPRegInfo pmcr = { ARMCPRegInfo pmcr = {
.name = "PMCR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 0, .name = "PMCR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 0,
.access = PL0_RW, .resetvalue = cpu->midr & 0xff000000, .access = PL0_RW, .resetvalue = cpu->midr & 0xff000000,
...@@ -1882,12 +1962,13 @@ void register_cp_regs_for_features(ARMCPU *cpu) ...@@ -1882,12 +1962,13 @@ void register_cp_regs_for_features(ARMCPU *cpu)
.accessfn = pmreg_access, .writefn = pmcr_write, .accessfn = pmreg_access, .writefn = pmcr_write,
.raw_writefn = raw_write, .raw_writefn = raw_write,
}; };
define_one_arm_cp_reg(cpu, &pmcr);
#endif
ARMCPRegInfo clidr = { ARMCPRegInfo clidr = {
.name = "CLIDR", .state = ARM_CP_STATE_BOTH, .name = "CLIDR", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 1, .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 1,
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->clidr .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->clidr
}; };
define_one_arm_cp_reg(cpu, &pmcr);
define_one_arm_cp_reg(cpu, &clidr); define_one_arm_cp_reg(cpu, &clidr);
define_arm_cp_regs(cpu, v7_cp_reginfo); define_arm_cp_regs(cpu, v7_cp_reginfo);
} else { } else {
...@@ -2478,7 +2559,7 @@ uint32_t cpsr_read(CPUARMState *env) ...@@ -2478,7 +2559,7 @@ uint32_t cpsr_read(CPUARMState *env)
(env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
| (env->thumb << 5) | ((env->condexec_bits & 3) << 25) | (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
| ((env->condexec_bits & 0xfc) << 8) | ((env->condexec_bits & 0xfc) << 8)
| (env->GE << 16) | env->daif; | (env->GE << 16) | (env->daif & CPSR_AIF);
} }
void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
......
...@@ -50,6 +50,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE, ...@@ -50,6 +50,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32) i32, i32, i32, i32)
DEF_HELPER_2(exception, void, env, i32) DEF_HELPER_2(exception, void, env, i32)
DEF_HELPER_1(wfi, void, env) DEF_HELPER_1(wfi, void, env)
DEF_HELPER_1(wfe, void, env)
DEF_HELPER_3(cpsr_write, void, env, i32, i32) DEF_HELPER_3(cpsr_write, void, env, i32, i32)
DEF_HELPER_1(cpsr_read, i32, env) DEF_HELPER_1(cpsr_read, i32, env)
......
...@@ -225,6 +225,15 @@ void HELPER(wfi)(CPUARMState *env) ...@@ -225,6 +225,15 @@ void HELPER(wfi)(CPUARMState *env)
cpu_loop_exit(env); cpu_loop_exit(env);
} }
void HELPER(wfe)(CPUARMState *env)
{
/* Don't actually halt the CPU, just yield back to top
* level loop
*/
env->exception_index = EXCP_YIELD;
cpu_loop_exit(env);
}
void HELPER(exception)(CPUARMState *env, uint32_t excp) void HELPER(exception)(CPUARMState *env, uint32_t excp)
{ {
env->exception_index = excp; env->exception_index = excp;
......
...@@ -210,7 +210,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest) ...@@ -210,7 +210,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
if (use_goto_tb(s, n, dest)) { if (use_goto_tb(s, n, dest)) {
tcg_gen_goto_tb(n); tcg_gen_goto_tb(n);
gen_a64_set_pc_im(dest); gen_a64_set_pc_im(dest);
tcg_gen_exit_tb((tcg_target_long)tb + n); tcg_gen_exit_tb((intptr_t)tb + n);
s->is_jmp = DISAS_TB_JUMP; s->is_jmp = DISAS_TB_JUMP;
} else { } else {
gen_a64_set_pc_im(dest); gen_a64_set_pc_im(dest);
......
...@@ -3939,6 +3939,9 @@ static void gen_nop_hint(DisasContext *s, int val) ...@@ -3939,6 +3939,9 @@ static void gen_nop_hint(DisasContext *s, int val)
s->is_jmp = DISAS_WFI; s->is_jmp = DISAS_WFI;
break; break;
case 2: /* wfe */ case 2: /* wfe */
gen_set_pc_im(s, s->pc);
s->is_jmp = DISAS_WFE;
break;
case 4: /* sev */ case 4: /* sev */
case 5: /* sevl */ case 5: /* sevl */
/* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */ /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
...@@ -10857,6 +10860,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, ...@@ -10857,6 +10860,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
case DISAS_WFI: case DISAS_WFI:
gen_helper_wfi(cpu_env); gen_helper_wfi(cpu_env);
break; break;
case DISAS_WFE:
gen_helper_wfe(cpu_env);
break;
case DISAS_SWI: case DISAS_SWI:
gen_exception(EXCP_SWI); gen_exception(EXCP_SWI);
break; break;
......
...@@ -44,6 +44,8 @@ extern TCGv_ptr cpu_env; ...@@ -44,6 +44,8 @@ extern TCGv_ptr cpu_env;
* emitting unreachable code at the end of the TB in the A64 decoder * emitting unreachable code at the end of the TB in the A64 decoder
*/ */
#define DISAS_EXC 6 #define DISAS_EXC 6
/* WFE */
#define DISAS_WFE 7
#ifdef TARGET_AARCH64 #ifdef TARGET_AARCH64
void a64_translate_init(void); void a64_translate_init(void);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册