Merge branch 'target-arm.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm
* 'target-arm.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm: (33 commits)
  target-arm: Remove ARM_CPUID_* macros
  target-arm: Remove remaining old cp15 infrastructure
  target-arm: Move block cache ops to new cp15 framework
  target-arm: Remove c0_cachetype CPUARMState field
  target-arm: Convert final ID registers
  target-arm: Convert MPIDR
  target-arm: Convert cp15 cache ID registers
  target-arm: Convert cp15 crn=0 crm={1,2} feature registers
  target-arm: Convert cp15 crn=1 registers
  target-arm: Convert cp15 crn=9 registers
  target-arm: Convert cp15 crn=6 registers
  target-arm: convert cp15 crn=7 registers
  target-arm: Convert cp15 VA-PA translation registers
  target-arm: Convert cp15 MMU TLB control
  target-arm: Convert cp15 crn=15 registers
  target-arm: Convert cp15 crn=10 registers
  target-arm: Convert cp15 crn=13 registers
  target-arm: Convert cp15 crn=2 registers
  target-arm: Convert MMU fault status cp15 registers
  target-arm: Convert cp15 c3 register
  ...
			
			
This commit is contained in:
		
						commit
						959a255dfb
					
				
							
								
								
									
										199
									
								
								hw/pxa2xx.c
									
									
									
									
									
								
							
							
						
						
									
										199
									
								
								hw/pxa2xx.c
									
									
									
									
									
								
							@ -224,43 +224,37 @@ static const VMStateDescription vmstate_pxa2xx_cm = {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint32_t pxa2xx_clkpwr_read(void *opaque, int op2, int reg, int crm)
 | 
					static int pxa2xx_clkcfg_read(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			||||||
 | 
					                              uint64_t *value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    PXA2xxState *s = (PXA2xxState *) opaque;
 | 
					    PXA2xxState *s = (PXA2xxState *)ri->opaque;
 | 
				
			||||||
 | 
					    *value = s->clkcfg;
 | 
				
			||||||
    switch (reg) {
 | 
					 | 
				
			||||||
    case 6:	/* Clock Configuration register */
 | 
					 | 
				
			||||||
        return s->clkcfg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case 7:	/* Power Mode register */
 | 
					 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    default:
 | 
					static int pxa2xx_clkcfg_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			||||||
        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
 | 
					                               uint64_t value)
 | 
				
			||||||
        break;
 | 
					{
 | 
				
			||||||
 | 
					    PXA2xxState *s = (PXA2xxState *)ri->opaque;
 | 
				
			||||||
 | 
					    s->clkcfg = value & 0xf;
 | 
				
			||||||
 | 
					    if (value & 2) {
 | 
				
			||||||
 | 
					        printf("%s: CPU frequency change attempt\n", __func__);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
 | 
					static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			||||||
                uint32_t value)
 | 
					                                uint64_t value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    PXA2xxState *s = (PXA2xxState *) opaque;
 | 
					    PXA2xxState *s = (PXA2xxState *)ri->opaque;
 | 
				
			||||||
    static const char *pwrmode[8] = {
 | 
					    static const char *pwrmode[8] = {
 | 
				
			||||||
        "Normal", "Idle", "Deep-idle", "Standby",
 | 
					        "Normal", "Idle", "Deep-idle", "Standby",
 | 
				
			||||||
        "Sleep", "reserved (!)", "reserved (!)", "Deep-sleep",
 | 
					        "Sleep", "reserved (!)", "reserved (!)", "Deep-sleep",
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (reg) {
 | 
					    if (value & 8) {
 | 
				
			||||||
    case 6:	/* Clock Configuration register */
 | 
					        printf("%s: CPU voltage change attempt\n", __func__);
 | 
				
			||||||
        s->clkcfg = value & 0xf;
 | 
					    }
 | 
				
			||||||
        if (value & 2)
 | 
					 | 
				
			||||||
            printf("%s: CPU frequency change attempt\n", __FUNCTION__);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case 7:	/* Power Mode register */
 | 
					 | 
				
			||||||
        if (value & 8)
 | 
					 | 
				
			||||||
            printf("%s: CPU voltage change attempt\n", __FUNCTION__);
 | 
					 | 
				
			||||||
    switch (value & 7) {
 | 
					    switch (value & 7) {
 | 
				
			||||||
    case 0:
 | 
					    case 0:
 | 
				
			||||||
        /* Do nothing */
 | 
					        /* Do nothing */
 | 
				
			||||||
@ -313,121 +307,78 @@ static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
    message:
 | 
					    message:
 | 
				
			||||||
            printf("%s: machine entered %s mode\n", __FUNCTION__,
 | 
					        printf("%s: machine entered %s mode\n", __func__,
 | 
				
			||||||
               pwrmode[value & 7]);
 | 
					               pwrmode[value & 7]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Performace Monitoring Registers */
 | 
					 | 
				
			||||||
#define CPPMNC		0	/* Performance Monitor Control register */
 | 
					 | 
				
			||||||
#define CPCCNT		1	/* Clock Counter register */
 | 
					 | 
				
			||||||
#define CPINTEN		4	/* Interrupt Enable register */
 | 
					 | 
				
			||||||
#define CPFLAG		5	/* Overflow Flag register */
 | 
					 | 
				
			||||||
#define CPEVTSEL	8	/* Event Selection register */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define CPPMN0		0	/* Performance Count register 0 */
 | 
					 | 
				
			||||||
#define CPPMN1		1	/* Performance Count register 1 */
 | 
					 | 
				
			||||||
#define CPPMN2		2	/* Performance Count register 2 */
 | 
					 | 
				
			||||||
#define CPPMN3		3	/* Performance Count register 3 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static uint32_t pxa2xx_perf_read(void *opaque, int op2, int reg, int crm)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    PXA2xxState *s = (PXA2xxState *) opaque;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    switch (reg) {
 | 
					 | 
				
			||||||
    case CPPMNC:
 | 
					 | 
				
			||||||
        return s->pmnc;
 | 
					 | 
				
			||||||
    case CPCCNT:
 | 
					 | 
				
			||||||
        if (s->pmnc & 1)
 | 
					 | 
				
			||||||
            return qemu_get_clock_ns(vm_clock);
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
    case CPINTEN:
 | 
					 | 
				
			||||||
    case CPFLAG:
 | 
					 | 
				
			||||||
    case CPEVTSEL:
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pxa2xx_perf_write(void *opaque, int op2, int reg, int crm,
 | 
					static int pxa2xx_cppmnc_read(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			||||||
                uint32_t value)
 | 
					                              uint64_t *value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    PXA2xxState *s = (PXA2xxState *) opaque;
 | 
					    PXA2xxState *s = (PXA2xxState *)ri->opaque;
 | 
				
			||||||
 | 
					    *value = s->pmnc;
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (reg) {
 | 
					static int pxa2xx_cppmnc_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			||||||
    case CPPMNC:
 | 
					                               uint64_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    PXA2xxState *s = (PXA2xxState *)ri->opaque;
 | 
				
			||||||
    s->pmnc = value;
 | 
					    s->pmnc = value;
 | 
				
			||||||
        break;
 | 
					    return 0;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    case CPCCNT:
 | 
					 | 
				
			||||||
    case CPINTEN:
 | 
					 | 
				
			||||||
    case CPFLAG:
 | 
					 | 
				
			||||||
    case CPEVTSEL:
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint32_t pxa2xx_cp14_read(void *opaque, int op2, int reg, int crm)
 | 
					static int pxa2xx_cpccnt_read(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			||||||
 | 
					                              uint64_t *value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    switch (crm) {
 | 
					    PXA2xxState *s = (PXA2xxState *)ri->opaque;
 | 
				
			||||||
    case 0:
 | 
					    if (s->pmnc & 1) {
 | 
				
			||||||
        return pxa2xx_clkpwr_read(opaque, op2, reg, crm);
 | 
					        *value = qemu_get_clock_ns(vm_clock);
 | 
				
			||||||
    case 1:
 | 
					    } else {
 | 
				
			||||||
        return pxa2xx_perf_read(opaque, op2, reg, crm);
 | 
					        *value = 0;
 | 
				
			||||||
    case 2:
 | 
					 | 
				
			||||||
        switch (reg) {
 | 
					 | 
				
			||||||
        case CPPMN0:
 | 
					 | 
				
			||||||
        case CPPMN1:
 | 
					 | 
				
			||||||
        case CPPMN2:
 | 
					 | 
				
			||||||
        case CPPMN3:
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        /* Fall through */
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pxa2xx_cp14_write(void *opaque, int op2, int reg, int crm,
 | 
					static const ARMCPRegInfo pxa_cp_reginfo[] = {
 | 
				
			||||||
                uint32_t value)
 | 
					    /* cp14 crn==1: perf registers */
 | 
				
			||||||
 | 
					    { .name = "CPPMNC", .cp = 14, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW,
 | 
				
			||||||
 | 
					      .readfn = pxa2xx_cppmnc_read, .writefn = pxa2xx_cppmnc_write },
 | 
				
			||||||
 | 
					    { .name = "CPCCNT", .cp = 14, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW,
 | 
				
			||||||
 | 
					      .readfn = pxa2xx_cpccnt_read, .writefn = arm_cp_write_ignore },
 | 
				
			||||||
 | 
					    { .name = "CPINTEN", .cp = 14, .crn = 1, .crm = 4, .opc1 = 0, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
 | 
				
			||||||
 | 
					    { .name = "CPFLAG", .cp = 14, .crn = 1, .crm = 5, .opc1 = 0, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
 | 
				
			||||||
 | 
					    { .name = "CPEVTSEL", .cp = 14, .crn = 1, .crm = 8, .opc1 = 0, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
 | 
				
			||||||
 | 
					    /* cp14 crn==2: performance count registers */
 | 
				
			||||||
 | 
					    { .name = "CPPMN0", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
 | 
				
			||||||
 | 
					    { .name = "CPPMN1", .cp = 14, .crn = 2, .crm = 1, .opc1 = 0, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
 | 
				
			||||||
 | 
					    { .name = "CPPMN2", .cp = 14, .crn = 2, .crm = 2, .opc1 = 0, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
 | 
				
			||||||
 | 
					    { .name = "CPPMN3", .cp = 14, .crn = 2, .crm = 3, .opc1 = 0, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
 | 
				
			||||||
 | 
					    /* cp14 crn==6: CLKCFG */
 | 
				
			||||||
 | 
					    { .name = "CLKCFG", .cp = 14, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW,
 | 
				
			||||||
 | 
					      .readfn = pxa2xx_clkcfg_read, .writefn = pxa2xx_clkcfg_write },
 | 
				
			||||||
 | 
					    /* cp14 crn==7: PWRMODE */
 | 
				
			||||||
 | 
					    { .name = "PWRMODE", .cp = 14, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW,
 | 
				
			||||||
 | 
					      .readfn = arm_cp_read_zero, .writefn = pxa2xx_pwrmode_write },
 | 
				
			||||||
 | 
					    REGINFO_SENTINEL
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void pxa2xx_setup_cp14(PXA2xxState *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    switch (crm) {
 | 
					    define_arm_cp_regs_with_opaque(s->cpu, pxa_cp_reginfo, s);
 | 
				
			||||||
    case 0:
 | 
					 | 
				
			||||||
        pxa2xx_clkpwr_write(opaque, op2, reg, crm, value);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    case 1:
 | 
					 | 
				
			||||||
        pxa2xx_perf_write(opaque, op2, reg, crm, value);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    case 2:
 | 
					 | 
				
			||||||
        switch (reg) {
 | 
					 | 
				
			||||||
        case CPPMN0:
 | 
					 | 
				
			||||||
        case CPPMN1:
 | 
					 | 
				
			||||||
        case CPPMN2:
 | 
					 | 
				
			||||||
        case CPPMN3:
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        /* Fall through */
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MDCNFG		0x00	/* SDRAM Configuration register */
 | 
					#define MDCNFG		0x00	/* SDRAM Configuration register */
 | 
				
			||||||
@ -2133,7 +2084,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
 | 
				
			|||||||
    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
 | 
					    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
 | 
				
			||||||
    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
 | 
					    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cpu_arm_set_cp_io(&s->cpu->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 | 
					    pxa2xx_setup_cp14(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->mm_base = 0x48000000;
 | 
					    s->mm_base = 0x48000000;
 | 
				
			||||||
    s->mm_regs[MDMRS >> 2] = 0x00020002;
 | 
					    s->mm_regs[MDMRS >> 2] = 0x00020002;
 | 
				
			||||||
@ -2264,7 +2215,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
 | 
				
			|||||||
    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
 | 
					    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
 | 
				
			||||||
    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
 | 
					    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cpu_arm_set_cp_io(&s->cpu->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 | 
					    pxa2xx_setup_cp14(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->mm_base = 0x48000000;
 | 
					    s->mm_base = 0x48000000;
 | 
				
			||||||
    s->mm_regs[MDMRS >> 2] = 0x00020002;
 | 
					    s->mm_regs[MDMRS >> 2] = 0x00020002;
 | 
				
			||||||
 | 
				
			|||||||
@ -209,33 +209,42 @@ static const int pxa2xx_cp_reg_map[0x10] = {
 | 
				
			|||||||
    [0xa] = ICPR2,
 | 
					    [0xa] = ICPR2,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint32_t pxa2xx_pic_cp_read(void *opaque, int op2, int reg, int crm)
 | 
					static int pxa2xx_pic_cp_read(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			||||||
 | 
					                              uint64_t *value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    target_phys_addr_t offset;
 | 
					    int offset = pxa2xx_cp_reg_map[ri->crn];
 | 
				
			||||||
 | 
					    *value = pxa2xx_pic_mem_read(ri->opaque, offset, 4);
 | 
				
			||||||
    if (pxa2xx_cp_reg_map[reg] == -1) {
 | 
					 | 
				
			||||||
        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
 | 
					 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    offset = pxa2xx_cp_reg_map[reg];
 | 
					 | 
				
			||||||
    return pxa2xx_pic_mem_read(opaque, offset, 4);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pxa2xx_pic_cp_write(void *opaque, int op2, int reg, int crm,
 | 
					static int pxa2xx_pic_cp_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			||||||
                uint32_t value)
 | 
					                               uint64_t value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    target_phys_addr_t offset;
 | 
					    int offset = pxa2xx_cp_reg_map[ri->crn];
 | 
				
			||||||
 | 
					    pxa2xx_pic_mem_write(ri->opaque, offset, value, 4);
 | 
				
			||||||
    if (pxa2xx_cp_reg_map[reg] == -1) {
 | 
					    return 0;
 | 
				
			||||||
        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    offset = pxa2xx_cp_reg_map[reg];
 | 
					 | 
				
			||||||
    pxa2xx_pic_mem_write(opaque, offset, value, 4);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define REGINFO_FOR_PIC_CP(NAME, CRN) \
 | 
				
			||||||
 | 
					    { .name = NAME, .cp = 6, .crn = CRN, .crm = 0, .opc1 = 0, .opc2 = 0, \
 | 
				
			||||||
 | 
					      .access = PL1_RW, \
 | 
				
			||||||
 | 
					      .readfn = pxa2xx_pic_cp_read, .writefn = pxa2xx_pic_cp_write }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const ARMCPRegInfo pxa_pic_cp_reginfo[] = {
 | 
				
			||||||
 | 
					    REGINFO_FOR_PIC_CP("ICIP", 0),
 | 
				
			||||||
 | 
					    REGINFO_FOR_PIC_CP("ICMR", 1),
 | 
				
			||||||
 | 
					    REGINFO_FOR_PIC_CP("ICLR", 2),
 | 
				
			||||||
 | 
					    REGINFO_FOR_PIC_CP("ICFP", 3),
 | 
				
			||||||
 | 
					    REGINFO_FOR_PIC_CP("ICPR", 4),
 | 
				
			||||||
 | 
					    REGINFO_FOR_PIC_CP("ICHP", 5),
 | 
				
			||||||
 | 
					    REGINFO_FOR_PIC_CP("ICIP2", 6),
 | 
				
			||||||
 | 
					    REGINFO_FOR_PIC_CP("ICMR2", 7),
 | 
				
			||||||
 | 
					    REGINFO_FOR_PIC_CP("ICLR2", 8),
 | 
				
			||||||
 | 
					    REGINFO_FOR_PIC_CP("ICFP2", 9),
 | 
				
			||||||
 | 
					    REGINFO_FOR_PIC_CP("ICPR2", 0xa),
 | 
				
			||||||
 | 
					    REGINFO_SENTINEL
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const MemoryRegionOps pxa2xx_pic_ops = {
 | 
					static const MemoryRegionOps pxa2xx_pic_ops = {
 | 
				
			||||||
    .read = pxa2xx_pic_mem_read,
 | 
					    .read = pxa2xx_pic_mem_read,
 | 
				
			||||||
    .write = pxa2xx_pic_mem_write,
 | 
					    .write = pxa2xx_pic_mem_write,
 | 
				
			||||||
@ -274,7 +283,7 @@ DeviceState *pxa2xx_pic_init(target_phys_addr_t base, ARMCPU *cpu)
 | 
				
			|||||||
    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
 | 
					    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Enable IC coprocessor access.  */
 | 
					    /* Enable IC coprocessor access.  */
 | 
				
			||||||
    cpu_arm_set_cp_io(env, 6, pxa2xx_pic_cp_read, pxa2xx_pic_cp_write, s);
 | 
					    define_arm_cp_regs_with_opaque(arm_env_get_cpu(env), pxa_pic_cp_reginfo, s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return dev;
 | 
					    return dev;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -35,10 +35,7 @@ const char *cpu_to_uname_machine(void *cpu_env)
 | 
				
			|||||||
     * armv7l; to get a list of CPU arch names from the linux source, use:
 | 
					     * armv7l; to get a list of CPU arch names from the linux source, use:
 | 
				
			||||||
     *     grep arch_name: -A1 linux/arch/arm/mm/proc-*.S
 | 
					     *     grep arch_name: -A1 linux/arch/arm/mm/proc-*.S
 | 
				
			||||||
     * see arch/arm/kernel/setup.c: setup_processor()
 | 
					     * see arch/arm/kernel/setup.c: setup_processor()
 | 
				
			||||||
     *
 | 
					     */
 | 
				
			||||||
     * to test by CPU id, compare cpu_env->cp15.c0_cpuid to ARM_CPUID_*
 | 
					 | 
				
			||||||
     * defines and to test by CPU feature, use arm_feature(cpu_env,
 | 
					 | 
				
			||||||
     * ARM_FEATURE_*) */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* in theory, endianness is configurable on some ARM CPUs, but this isn't
 | 
					    /* in theory, endianness is configurable on some ARM CPUs, but this isn't
 | 
				
			||||||
     * used in user mode emulation */
 | 
					     * used in user mode emulation */
 | 
				
			||||||
 | 
				
			|||||||
@ -58,6 +58,9 @@ typedef struct ARMCPU {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    CPUARMState env;
 | 
					    CPUARMState env;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Coprocessor information */
 | 
				
			||||||
 | 
					    GHashTable *cp_regs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* The instance init functions for implementation-specific subclasses
 | 
					    /* The instance init functions for implementation-specific subclasses
 | 
				
			||||||
     * set these fields to specify the implementation-dependent values of
 | 
					     * set these fields to specify the implementation-dependent values of
 | 
				
			||||||
     * various constant registers and reset values of non-constant
 | 
					     * various constant registers and reset values of non-constant
 | 
				
			||||||
@ -94,6 +97,7 @@ typedef struct ARMCPU {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    uint32_t ccsidr[16];
 | 
					    uint32_t ccsidr[16];
 | 
				
			||||||
    uint32_t reset_cbar;
 | 
					    uint32_t reset_cbar;
 | 
				
			||||||
 | 
					    uint32_t reset_auxcr;
 | 
				
			||||||
} ARMCPU;
 | 
					} ARMCPU;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
 | 
					static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
 | 
				
			||||||
@ -104,5 +108,6 @@ static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
 | 
				
			|||||||
#define ENV_GET_CPU(e) CPU(arm_env_get_cpu(e))
 | 
					#define ENV_GET_CPU(e) CPU(arm_env_get_cpu(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void arm_cpu_realize(ARMCPU *cpu);
 | 
					void arm_cpu_realize(ARMCPU *cpu);
 | 
				
			||||||
 | 
					void register_cp_regs_for_features(ARMCPU *cpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										230
									
								
								target-arm/cpu.c
									
									
									
									
									
								
							
							
						
						
									
										230
									
								
								target-arm/cpu.c
									
									
									
									
									
								
							@ -23,6 +23,38 @@
 | 
				
			|||||||
#if !defined(CONFIG_USER_ONLY)
 | 
					#if !defined(CONFIG_USER_ONLY)
 | 
				
			||||||
#include "hw/loader.h"
 | 
					#include "hw/loader.h"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#include "sysemu.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Reset a single ARMCPRegInfo register */
 | 
				
			||||||
 | 
					    ARMCPRegInfo *ri = value;
 | 
				
			||||||
 | 
					    ARMCPU *cpu = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ri->type & ARM_CP_SPECIAL) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ri->resetfn) {
 | 
				
			||||||
 | 
					        ri->resetfn(&cpu->env, ri);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* A zero offset is never possible as it would be regs[0]
 | 
				
			||||||
 | 
					     * so we use it to indicate that reset is being handled elsewhere.
 | 
				
			||||||
 | 
					     * This is basically only used for fields in non-core coprocessors
 | 
				
			||||||
 | 
					     * (like the pxa2xx ones).
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    if (!ri->fieldoffset) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ri->type & ARM_CP_64BIT) {
 | 
				
			||||||
 | 
					        CPREG_FIELD64(&cpu->env, ri) = ri->resetvalue;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        CPREG_FIELD32(&cpu->env, ri) = ri->resetvalue;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* CPUClass::reset() */
 | 
					/* CPUClass::reset() */
 | 
				
			||||||
static void arm_cpu_reset(CPUState *s)
 | 
					static void arm_cpu_reset(CPUState *s)
 | 
				
			||||||
@ -39,30 +71,10 @@ static void arm_cpu_reset(CPUState *s)
 | 
				
			|||||||
    acc->parent_reset(s);
 | 
					    acc->parent_reset(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memset(env, 0, offsetof(CPUARMState, breakpoints));
 | 
					    memset(env, 0, offsetof(CPUARMState, breakpoints));
 | 
				
			||||||
    env->cp15.c15_config_base_address = cpu->reset_cbar;
 | 
					    g_hash_table_foreach(cpu->cp_regs, cp_reg_reset, cpu);
 | 
				
			||||||
    env->cp15.c0_cpuid = cpu->midr;
 | 
					 | 
				
			||||||
    env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
 | 
					    env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
 | 
				
			||||||
    env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0;
 | 
					    env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0;
 | 
				
			||||||
    env->vfp.xregs[ARM_VFP_MVFR1] = cpu->mvfr1;
 | 
					    env->vfp.xregs[ARM_VFP_MVFR1] = cpu->mvfr1;
 | 
				
			||||||
    env->cp15.c0_cachetype = cpu->ctr;
 | 
					 | 
				
			||||||
    env->cp15.c1_sys = cpu->reset_sctlr;
 | 
					 | 
				
			||||||
    env->cp15.c0_c1[0] = cpu->id_pfr0;
 | 
					 | 
				
			||||||
    env->cp15.c0_c1[1] = cpu->id_pfr1;
 | 
					 | 
				
			||||||
    env->cp15.c0_c1[2] = cpu->id_dfr0;
 | 
					 | 
				
			||||||
    env->cp15.c0_c1[3] = cpu->id_afr0;
 | 
					 | 
				
			||||||
    env->cp15.c0_c1[4] = cpu->id_mmfr0;
 | 
					 | 
				
			||||||
    env->cp15.c0_c1[5] = cpu->id_mmfr1;
 | 
					 | 
				
			||||||
    env->cp15.c0_c1[6] = cpu->id_mmfr2;
 | 
					 | 
				
			||||||
    env->cp15.c0_c1[7] = cpu->id_mmfr3;
 | 
					 | 
				
			||||||
    env->cp15.c0_c2[0] = cpu->id_isar0;
 | 
					 | 
				
			||||||
    env->cp15.c0_c2[1] = cpu->id_isar1;
 | 
					 | 
				
			||||||
    env->cp15.c0_c2[2] = cpu->id_isar2;
 | 
					 | 
				
			||||||
    env->cp15.c0_c2[3] = cpu->id_isar3;
 | 
					 | 
				
			||||||
    env->cp15.c0_c2[4] = cpu->id_isar4;
 | 
					 | 
				
			||||||
    env->cp15.c0_c2[5] = cpu->id_isar5;
 | 
					 | 
				
			||||||
    env->cp15.c15_i_min = 0xff0;
 | 
					 | 
				
			||||||
    env->cp15.c0_clid = cpu->clidr;
 | 
					 | 
				
			||||||
    memcpy(env->cp15.c0_ccsid, cpu->ccsidr, ARRAY_SIZE(cpu->ccsidr));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
 | 
					    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
 | 
				
			||||||
        env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
 | 
					        env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
 | 
				
			||||||
@ -99,11 +111,6 @@ static void arm_cpu_reset(CPUState *s)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    env->vfp.xregs[ARM_VFP_FPEXC] = 0;
 | 
					    env->vfp.xregs[ARM_VFP_FPEXC] = 0;
 | 
				
			||||||
    env->cp15.c2_base_mask = 0xffffc000u;
 | 
					 | 
				
			||||||
    /* v7 performance monitor control register: same implementor
 | 
					 | 
				
			||||||
     * field as main ID register, and we implement no event counters.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    env->cp15.c9_pmcr = (cpu->midr & 0xff000000);
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    set_flush_to_zero(1, &env->vfp.standard_fp_status);
 | 
					    set_flush_to_zero(1, &env->vfp.standard_fp_status);
 | 
				
			||||||
    set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
 | 
					    set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
 | 
				
			||||||
@ -130,6 +137,14 @@ static void arm_cpu_initfn(Object *obj)
 | 
				
			|||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cpu_exec_init(&cpu->env);
 | 
					    cpu_exec_init(&cpu->env);
 | 
				
			||||||
 | 
					    cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal,
 | 
				
			||||||
 | 
					                                         g_free, g_free);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void arm_cpu_finalizefn(Object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
 | 
					    g_hash_table_destroy(cpu->cp_regs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void arm_cpu_realize(ARMCPU *cpu)
 | 
					void arm_cpu_realize(ARMCPU *cpu)
 | 
				
			||||||
@ -145,6 +160,7 @@ void arm_cpu_realize(ARMCPU *cpu)
 | 
				
			|||||||
    if (arm_feature(env, ARM_FEATURE_V7)) {
 | 
					    if (arm_feature(env, ARM_FEATURE_V7)) {
 | 
				
			||||||
        set_feature(env, ARM_FEATURE_VAPA);
 | 
					        set_feature(env, ARM_FEATURE_VAPA);
 | 
				
			||||||
        set_feature(env, ARM_FEATURE_THUMB2);
 | 
					        set_feature(env, ARM_FEATURE_THUMB2);
 | 
				
			||||||
 | 
					        set_feature(env, ARM_FEATURE_MPIDR);
 | 
				
			||||||
        if (!arm_feature(env, ARM_FEATURE_M)) {
 | 
					        if (!arm_feature(env, ARM_FEATURE_M)) {
 | 
				
			||||||
            set_feature(env, ARM_FEATURE_V6K);
 | 
					            set_feature(env, ARM_FEATURE_V6K);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@ -176,6 +192,8 @@ void arm_cpu_realize(ARMCPU *cpu)
 | 
				
			|||||||
    if (arm_feature(env, ARM_FEATURE_VFP3)) {
 | 
					    if (arm_feature(env, ARM_FEATURE_VFP3)) {
 | 
				
			||||||
        set_feature(env, ARM_FEATURE_VFP);
 | 
					        set_feature(env, ARM_FEATURE_VFP);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    register_cp_regs_for_features(cpu);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* CPU models */
 | 
					/* CPU models */
 | 
				
			||||||
@ -185,7 +203,9 @@ static void arm926_initfn(Object *obj)
 | 
				
			|||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_VFP);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_VFP);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_ARM926;
 | 
					    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
 | 
				
			||||||
 | 
					    set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN);
 | 
				
			||||||
 | 
					    cpu->midr = 0x41069265;
 | 
				
			||||||
    cpu->reset_fpsid = 0x41011090;
 | 
					    cpu->reset_fpsid = 0x41011090;
 | 
				
			||||||
    cpu->ctr = 0x1dd20d2;
 | 
					    cpu->ctr = 0x1dd20d2;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00090078;
 | 
					    cpu->reset_sctlr = 0x00090078;
 | 
				
			||||||
@ -196,7 +216,8 @@ static void arm946_initfn(Object *obj)
 | 
				
			|||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_MPU);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_MPU);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_ARM946;
 | 
					    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
 | 
				
			||||||
 | 
					    cpu->midr = 0x41059461;
 | 
				
			||||||
    cpu->ctr = 0x0f004006;
 | 
					    cpu->ctr = 0x0f004006;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000078;
 | 
					    cpu->reset_sctlr = 0x00000078;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -207,10 +228,23 @@ static void arm1026_initfn(Object *obj)
 | 
				
			|||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_VFP);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_VFP);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_AUXCR);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_AUXCR);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_ARM1026;
 | 
					    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
 | 
				
			||||||
 | 
					    set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN);
 | 
				
			||||||
 | 
					    cpu->midr = 0x4106a262;
 | 
				
			||||||
    cpu->reset_fpsid = 0x410110a0;
 | 
					    cpu->reset_fpsid = 0x410110a0;
 | 
				
			||||||
    cpu->ctr = 0x1dd20d2;
 | 
					    cpu->ctr = 0x1dd20d2;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00090078;
 | 
					    cpu->reset_sctlr = 0x00090078;
 | 
				
			||||||
 | 
					    cpu->reset_auxcr = 1;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */
 | 
				
			||||||
 | 
					        ARMCPRegInfo ifar = {
 | 
				
			||||||
 | 
					            .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1,
 | 
				
			||||||
 | 
					            .access = PL1_RW,
 | 
				
			||||||
 | 
					            .fieldoffset = offsetof(CPUARMState, cp15.c6_insn),
 | 
				
			||||||
 | 
					            .resetvalue = 0
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        define_one_arm_cp_reg(cpu, &ifar);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void arm1136_r2_initfn(Object *obj)
 | 
					static void arm1136_r2_initfn(Object *obj)
 | 
				
			||||||
@ -225,7 +259,10 @@ static void arm1136_r2_initfn(Object *obj)
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_V6);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V6);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_VFP);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_VFP);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_ARM1136_R2;
 | 
					    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
 | 
				
			||||||
 | 
					    set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG);
 | 
				
			||||||
 | 
					    set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS);
 | 
				
			||||||
 | 
					    cpu->midr = 0x4107b362;
 | 
				
			||||||
    cpu->reset_fpsid = 0x410120b4;
 | 
					    cpu->reset_fpsid = 0x410120b4;
 | 
				
			||||||
    cpu->mvfr0 = 0x11111111;
 | 
					    cpu->mvfr0 = 0x11111111;
 | 
				
			||||||
    cpu->mvfr1 = 0x00000000;
 | 
					    cpu->mvfr1 = 0x00000000;
 | 
				
			||||||
@ -243,6 +280,7 @@ static void arm1136_r2_initfn(Object *obj)
 | 
				
			|||||||
    cpu->id_isar2 = 0x11231111;
 | 
					    cpu->id_isar2 = 0x11231111;
 | 
				
			||||||
    cpu->id_isar3 = 0x01102131;
 | 
					    cpu->id_isar3 = 0x01102131;
 | 
				
			||||||
    cpu->id_isar4 = 0x141;
 | 
					    cpu->id_isar4 = 0x141;
 | 
				
			||||||
 | 
					    cpu->reset_auxcr = 7;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void arm1136_initfn(Object *obj)
 | 
					static void arm1136_initfn(Object *obj)
 | 
				
			||||||
@ -251,7 +289,10 @@ static void arm1136_initfn(Object *obj)
 | 
				
			|||||||
    set_feature(&cpu->env, ARM_FEATURE_V6K);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V6K);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_V6);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V6);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_VFP);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_VFP);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_ARM1136;
 | 
					    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
 | 
				
			||||||
 | 
					    set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG);
 | 
				
			||||||
 | 
					    set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS);
 | 
				
			||||||
 | 
					    cpu->midr = 0x4117b363;
 | 
				
			||||||
    cpu->reset_fpsid = 0x410120b4;
 | 
					    cpu->reset_fpsid = 0x410120b4;
 | 
				
			||||||
    cpu->mvfr0 = 0x11111111;
 | 
					    cpu->mvfr0 = 0x11111111;
 | 
				
			||||||
    cpu->mvfr1 = 0x00000000;
 | 
					    cpu->mvfr1 = 0x00000000;
 | 
				
			||||||
@ -269,6 +310,7 @@ static void arm1136_initfn(Object *obj)
 | 
				
			|||||||
    cpu->id_isar2 = 0x11231111;
 | 
					    cpu->id_isar2 = 0x11231111;
 | 
				
			||||||
    cpu->id_isar3 = 0x01102131;
 | 
					    cpu->id_isar3 = 0x01102131;
 | 
				
			||||||
    cpu->id_isar4 = 0x141;
 | 
					    cpu->id_isar4 = 0x141;
 | 
				
			||||||
 | 
					    cpu->reset_auxcr = 7;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void arm1176_initfn(Object *obj)
 | 
					static void arm1176_initfn(Object *obj)
 | 
				
			||||||
@ -277,7 +319,10 @@ static void arm1176_initfn(Object *obj)
 | 
				
			|||||||
    set_feature(&cpu->env, ARM_FEATURE_V6K);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V6K);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_VFP);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_VFP);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_VAPA);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_VAPA);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_ARM1176;
 | 
					    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
 | 
				
			||||||
 | 
					    set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG);
 | 
				
			||||||
 | 
					    set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS);
 | 
				
			||||||
 | 
					    cpu->midr = 0x410fb767;
 | 
				
			||||||
    cpu->reset_fpsid = 0x410120b5;
 | 
					    cpu->reset_fpsid = 0x410120b5;
 | 
				
			||||||
    cpu->mvfr0 = 0x11111111;
 | 
					    cpu->mvfr0 = 0x11111111;
 | 
				
			||||||
    cpu->mvfr1 = 0x00000000;
 | 
					    cpu->mvfr1 = 0x00000000;
 | 
				
			||||||
@ -295,6 +340,7 @@ static void arm1176_initfn(Object *obj)
 | 
				
			|||||||
    cpu->id_isar2 = 0x11231121;
 | 
					    cpu->id_isar2 = 0x11231121;
 | 
				
			||||||
    cpu->id_isar3 = 0x01102131;
 | 
					    cpu->id_isar3 = 0x01102131;
 | 
				
			||||||
    cpu->id_isar4 = 0x01141;
 | 
					    cpu->id_isar4 = 0x01141;
 | 
				
			||||||
 | 
					    cpu->reset_auxcr = 7;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void arm11mpcore_initfn(Object *obj)
 | 
					static void arm11mpcore_initfn(Object *obj)
 | 
				
			||||||
@ -303,11 +349,13 @@ static void arm11mpcore_initfn(Object *obj)
 | 
				
			|||||||
    set_feature(&cpu->env, ARM_FEATURE_V6K);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V6K);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_VFP);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_VFP);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_VAPA);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_VAPA);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_ARM11MPCORE;
 | 
					    set_feature(&cpu->env, ARM_FEATURE_MPIDR);
 | 
				
			||||||
 | 
					    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
 | 
				
			||||||
 | 
					    cpu->midr = 0x410fb022;
 | 
				
			||||||
    cpu->reset_fpsid = 0x410120b4;
 | 
					    cpu->reset_fpsid = 0x410120b4;
 | 
				
			||||||
    cpu->mvfr0 = 0x11111111;
 | 
					    cpu->mvfr0 = 0x11111111;
 | 
				
			||||||
    cpu->mvfr1 = 0x00000000;
 | 
					    cpu->mvfr1 = 0x00000000;
 | 
				
			||||||
    cpu->ctr = 0x1dd20d2;
 | 
					    cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */
 | 
				
			||||||
    cpu->id_pfr0 = 0x111;
 | 
					    cpu->id_pfr0 = 0x111;
 | 
				
			||||||
    cpu->id_pfr1 = 0x1;
 | 
					    cpu->id_pfr1 = 0x1;
 | 
				
			||||||
    cpu->id_dfr0 = 0;
 | 
					    cpu->id_dfr0 = 0;
 | 
				
			||||||
@ -320,6 +368,7 @@ static void arm11mpcore_initfn(Object *obj)
 | 
				
			|||||||
    cpu->id_isar2 = 0x11221011;
 | 
					    cpu->id_isar2 = 0x11221011;
 | 
				
			||||||
    cpu->id_isar3 = 0x01102131;
 | 
					    cpu->id_isar3 = 0x01102131;
 | 
				
			||||||
    cpu->id_isar4 = 0x141;
 | 
					    cpu->id_isar4 = 0x141;
 | 
				
			||||||
 | 
					    cpu->reset_auxcr = 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void cortex_m3_initfn(Object *obj)
 | 
					static void cortex_m3_initfn(Object *obj)
 | 
				
			||||||
@ -327,9 +376,17 @@ static void cortex_m3_initfn(Object *obj)
 | 
				
			|||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_V7);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V7);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_M);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_M);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_CORTEXM3;
 | 
					    cpu->midr = 0x410fc231;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
 | 
				
			||||||
 | 
					    { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
 | 
				
			||||||
 | 
					    { .name = "L2AUXCR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
 | 
				
			||||||
 | 
					    REGINFO_SENTINEL
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void cortex_a8_initfn(Object *obj)
 | 
					static void cortex_a8_initfn(Object *obj)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
@ -337,7 +394,8 @@ static void cortex_a8_initfn(Object *obj)
 | 
				
			|||||||
    set_feature(&cpu->env, ARM_FEATURE_VFP3);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_VFP3);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_NEON);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_NEON);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_CORTEXA8;
 | 
					    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
 | 
				
			||||||
 | 
					    cpu->midr = 0x410fc080;
 | 
				
			||||||
    cpu->reset_fpsid = 0x410330c0;
 | 
					    cpu->reset_fpsid = 0x410330c0;
 | 
				
			||||||
    cpu->mvfr0 = 0x11110222;
 | 
					    cpu->mvfr0 = 0x11110222;
 | 
				
			||||||
    cpu->mvfr1 = 0x00011100;
 | 
					    cpu->mvfr1 = 0x00011100;
 | 
				
			||||||
@ -360,8 +418,39 @@ static void cortex_a8_initfn(Object *obj)
 | 
				
			|||||||
    cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
 | 
					    cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
 | 
				
			||||||
    cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
 | 
					    cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
 | 
				
			||||||
    cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */
 | 
					    cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */
 | 
				
			||||||
 | 
					    cpu->reset_auxcr = 2;
 | 
				
			||||||
 | 
					    define_arm_cp_regs(cpu, cortexa8_cp_reginfo);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
 | 
				
			||||||
 | 
					    /* power_control should be set to maximum latency. Again,
 | 
				
			||||||
 | 
					     * default to 0 and set by private hook
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    { .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .resetvalue = 0,
 | 
				
			||||||
 | 
					      .fieldoffset = offsetof(CPUARMState, cp15.c15_power_control) },
 | 
				
			||||||
 | 
					    { .name = "A9_DIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 1,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .resetvalue = 0,
 | 
				
			||||||
 | 
					      .fieldoffset = offsetof(CPUARMState, cp15.c15_diagnostic) },
 | 
				
			||||||
 | 
					    { .name = "A9_PWRDIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 2,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .resetvalue = 0,
 | 
				
			||||||
 | 
					      .fieldoffset = offsetof(CPUARMState, cp15.c15_power_diagnostic) },
 | 
				
			||||||
 | 
					    { .name = "NEONBUSY", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
 | 
				
			||||||
 | 
					    /* TLB lockdown control */
 | 
				
			||||||
 | 
					    { .name = "TLB_LOCKR", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 2,
 | 
				
			||||||
 | 
					      .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
 | 
				
			||||||
 | 
					    { .name = "TLB_LOCKW", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 4,
 | 
				
			||||||
 | 
					      .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
 | 
				
			||||||
 | 
					    { .name = "TLB_VA", .cp = 15, .crn = 15, .crm = 5, .opc1 = 5, .opc2 = 2,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
 | 
				
			||||||
 | 
					    { .name = "TLB_PA", .cp = 15, .crn = 15, .crm = 6, .opc1 = 5, .opc2 = 2,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
 | 
				
			||||||
 | 
					    { .name = "TLB_ATTR", .cp = 15, .crn = 15, .crm = 7, .opc1 = 5, .opc2 = 2,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
 | 
				
			||||||
 | 
					    REGINFO_SENTINEL
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void cortex_a9_initfn(Object *obj)
 | 
					static void cortex_a9_initfn(Object *obj)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
@ -375,7 +464,7 @@ static void cortex_a9_initfn(Object *obj)
 | 
				
			|||||||
     * and valid configurations; we don't model A9UP).
 | 
					     * and valid configurations; we don't model A9UP).
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_V7MP);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V7MP);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_CORTEXA9;
 | 
					    cpu->midr = 0x410fc090;
 | 
				
			||||||
    cpu->reset_fpsid = 0x41033090;
 | 
					    cpu->reset_fpsid = 0x41033090;
 | 
				
			||||||
    cpu->mvfr0 = 0x11110222;
 | 
					    cpu->mvfr0 = 0x11110222;
 | 
				
			||||||
    cpu->mvfr1 = 0x01111111;
 | 
					    cpu->mvfr1 = 0x01111111;
 | 
				
			||||||
@ -397,8 +486,40 @@ static void cortex_a9_initfn(Object *obj)
 | 
				
			|||||||
    cpu->clidr = (1 << 27) | (1 << 24) | 3;
 | 
					    cpu->clidr = (1 << 27) | (1 << 24) | 3;
 | 
				
			||||||
    cpu->ccsidr[0] = 0xe00fe015; /* 16k L1 dcache. */
 | 
					    cpu->ccsidr[0] = 0xe00fe015; /* 16k L1 dcache. */
 | 
				
			||||||
    cpu->ccsidr[1] = 0x200fe015; /* 16k L1 icache. */
 | 
					    cpu->ccsidr[1] = 0x200fe015; /* 16k L1 icache. */
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ARMCPRegInfo cbar = {
 | 
				
			||||||
 | 
					            .name = "CBAR", .cp = 15, .crn = 15,  .crm = 0, .opc1 = 4,
 | 
				
			||||||
 | 
					            .opc2 = 0, .access = PL1_R|PL3_W, .resetvalue = cpu->reset_cbar,
 | 
				
			||||||
 | 
					            .fieldoffset = offsetof(CPUARMState, cp15.c15_config_base_address)
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        define_one_arm_cp_reg(cpu, &cbar);
 | 
				
			||||||
 | 
					        define_arm_cp_regs(cpu, cortexa9_cp_reginfo);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CONFIG_USER_ONLY
 | 
				
			||||||
 | 
					static int a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			||||||
 | 
					                           uint64_t *value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Linux wants the number of processors from here.
 | 
				
			||||||
 | 
					     * Might as well set the interrupt-controller bit too.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    *value = ((smp_cpus - 1) << 24) | (1 << 23);
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
 | 
				
			||||||
 | 
					#ifndef CONFIG_USER_ONLY
 | 
				
			||||||
 | 
					    { .name = "L2CTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .resetvalue = 0, .readfn = a15_l2ctlr_read,
 | 
				
			||||||
 | 
					      .writefn = arm_cp_write_ignore, },
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    { .name = "L2ECTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 3,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
 | 
				
			||||||
 | 
					    REGINFO_SENTINEL
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void cortex_a15_initfn(Object *obj)
 | 
					static void cortex_a15_initfn(Object *obj)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
@ -410,7 +531,8 @@ static void cortex_a15_initfn(Object *obj)
 | 
				
			|||||||
    set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_V7MP);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V7MP);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_CORTEXA15;
 | 
					    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
 | 
				
			||||||
 | 
					    cpu->midr = 0x412fc0f1;
 | 
				
			||||||
    cpu->reset_fpsid = 0x410430f0;
 | 
					    cpu->reset_fpsid = 0x410430f0;
 | 
				
			||||||
    cpu->mvfr0 = 0x10110222;
 | 
					    cpu->mvfr0 = 0x10110222;
 | 
				
			||||||
    cpu->mvfr1 = 0x11111111;
 | 
					    cpu->mvfr1 = 0x11111111;
 | 
				
			||||||
@ -433,6 +555,7 @@ static void cortex_a15_initfn(Object *obj)
 | 
				
			|||||||
    cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
 | 
					    cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
 | 
				
			||||||
    cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
 | 
					    cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
 | 
				
			||||||
    cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
 | 
					    cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
 | 
				
			||||||
 | 
					    define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ti925t_initfn(Object *obj)
 | 
					static void ti925t_initfn(Object *obj)
 | 
				
			||||||
@ -449,7 +572,8 @@ static void sa1100_initfn(Object *obj)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_STRONGARM);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_STRONGARM);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_SA1100;
 | 
					    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
 | 
				
			||||||
 | 
					    cpu->midr = 0x4401A11B;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000070;
 | 
					    cpu->reset_sctlr = 0x00000070;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -457,7 +581,8 @@ static void sa1110_initfn(Object *obj)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_STRONGARM);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_STRONGARM);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_SA1110;
 | 
					    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
 | 
				
			||||||
 | 
					    cpu->midr = 0x6901B119;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000070;
 | 
					    cpu->reset_sctlr = 0x00000070;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -466,7 +591,7 @@ static void pxa250_initfn(Object *obj)
 | 
				
			|||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_PXA250;
 | 
					    cpu->midr = 0x69052100;
 | 
				
			||||||
    cpu->ctr = 0xd172172;
 | 
					    cpu->ctr = 0xd172172;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000078;
 | 
					    cpu->reset_sctlr = 0x00000078;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -476,7 +601,7 @@ static void pxa255_initfn(Object *obj)
 | 
				
			|||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_PXA255;
 | 
					    cpu->midr = 0x69052d00;
 | 
				
			||||||
    cpu->ctr = 0xd172172;
 | 
					    cpu->ctr = 0xd172172;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000078;
 | 
					    cpu->reset_sctlr = 0x00000078;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -486,7 +611,7 @@ static void pxa260_initfn(Object *obj)
 | 
				
			|||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_PXA260;
 | 
					    cpu->midr = 0x69052903;
 | 
				
			||||||
    cpu->ctr = 0xd172172;
 | 
					    cpu->ctr = 0xd172172;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000078;
 | 
					    cpu->reset_sctlr = 0x00000078;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -496,7 +621,7 @@ static void pxa261_initfn(Object *obj)
 | 
				
			|||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_PXA261;
 | 
					    cpu->midr = 0x69052d05;
 | 
				
			||||||
    cpu->ctr = 0xd172172;
 | 
					    cpu->ctr = 0xd172172;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000078;
 | 
					    cpu->reset_sctlr = 0x00000078;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -506,7 +631,7 @@ static void pxa262_initfn(Object *obj)
 | 
				
			|||||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
					    ARMCPU *cpu = ARM_CPU(obj);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_PXA262;
 | 
					    cpu->midr = 0x69052d06;
 | 
				
			||||||
    cpu->ctr = 0xd172172;
 | 
					    cpu->ctr = 0xd172172;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000078;
 | 
					    cpu->reset_sctlr = 0x00000078;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -517,7 +642,7 @@ static void pxa270a0_initfn(Object *obj)
 | 
				
			|||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_PXA270_A0;
 | 
					    cpu->midr = 0x69054110;
 | 
				
			||||||
    cpu->ctr = 0xd172172;
 | 
					    cpu->ctr = 0xd172172;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000078;
 | 
					    cpu->reset_sctlr = 0x00000078;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -528,7 +653,7 @@ static void pxa270a1_initfn(Object *obj)
 | 
				
			|||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_PXA270_A1;
 | 
					    cpu->midr = 0x69054111;
 | 
				
			||||||
    cpu->ctr = 0xd172172;
 | 
					    cpu->ctr = 0xd172172;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000078;
 | 
					    cpu->reset_sctlr = 0x00000078;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -539,7 +664,7 @@ static void pxa270b0_initfn(Object *obj)
 | 
				
			|||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_PXA270_B0;
 | 
					    cpu->midr = 0x69054112;
 | 
				
			||||||
    cpu->ctr = 0xd172172;
 | 
					    cpu->ctr = 0xd172172;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000078;
 | 
					    cpu->reset_sctlr = 0x00000078;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -550,7 +675,7 @@ static void pxa270b1_initfn(Object *obj)
 | 
				
			|||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_PXA270_B1;
 | 
					    cpu->midr = 0x69054113;
 | 
				
			||||||
    cpu->ctr = 0xd172172;
 | 
					    cpu->ctr = 0xd172172;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000078;
 | 
					    cpu->reset_sctlr = 0x00000078;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -561,7 +686,7 @@ static void pxa270c0_initfn(Object *obj)
 | 
				
			|||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_PXA270_C0;
 | 
					    cpu->midr = 0x69054114;
 | 
				
			||||||
    cpu->ctr = 0xd172172;
 | 
					    cpu->ctr = 0xd172172;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000078;
 | 
					    cpu->reset_sctlr = 0x00000078;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -572,7 +697,7 @@ static void pxa270c5_initfn(Object *obj)
 | 
				
			|||||||
    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V5);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_PXA270_C5;
 | 
					    cpu->midr = 0x69054117;
 | 
				
			||||||
    cpu->ctr = 0xd172172;
 | 
					    cpu->ctr = 0xd172172;
 | 
				
			||||||
    cpu->reset_sctlr = 0x00000078;
 | 
					    cpu->reset_sctlr = 0x00000078;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -587,7 +712,7 @@ static void arm_any_initfn(Object *obj)
 | 
				
			|||||||
    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
 | 
				
			||||||
    set_feature(&cpu->env, ARM_FEATURE_V7MP);
 | 
					    set_feature(&cpu->env, ARM_FEATURE_V7MP);
 | 
				
			||||||
    cpu->midr = ARM_CPUID_ANY;
 | 
					    cpu->midr = 0xffffffff;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct ARMCPUInfo {
 | 
					typedef struct ARMCPUInfo {
 | 
				
			||||||
@ -657,6 +782,7 @@ static const TypeInfo arm_cpu_type_info = {
 | 
				
			|||||||
    .parent = TYPE_CPU,
 | 
					    .parent = TYPE_CPU,
 | 
				
			||||||
    .instance_size = sizeof(ARMCPU),
 | 
					    .instance_size = sizeof(ARMCPU),
 | 
				
			||||||
    .instance_init = arm_cpu_initfn,
 | 
					    .instance_init = arm_cpu_initfn,
 | 
				
			||||||
 | 
					    .instance_finalize = arm_cpu_finalizefn,
 | 
				
			||||||
    .abstract = true,
 | 
					    .abstract = true,
 | 
				
			||||||
    .class_size = sizeof(ARMCPUClass),
 | 
					    .class_size = sizeof(ARMCPUClass),
 | 
				
			||||||
    .class_init = arm_cpu_class_init,
 | 
					    .class_init = arm_cpu_class_init,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										248
									
								
								target-arm/cpu.h
									
									
									
									
									
								
							
							
						
						
									
										248
									
								
								target-arm/cpu.h
									
									
									
									
									
								
							@ -107,12 +107,7 @@ typedef struct CPUARMState {
 | 
				
			|||||||
    /* System control coprocessor (cp15) */
 | 
					    /* System control coprocessor (cp15) */
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
        uint32_t c0_cpuid;
 | 
					        uint32_t c0_cpuid;
 | 
				
			||||||
        uint32_t c0_cachetype;
 | 
					 | 
				
			||||||
        uint32_t c0_ccsid[16]; /* Cache size.  */
 | 
					 | 
				
			||||||
        uint32_t c0_clid; /* Cache level.  */
 | 
					 | 
				
			||||||
        uint32_t c0_cssel; /* Cache size selection.  */
 | 
					        uint32_t c0_cssel; /* Cache size selection.  */
 | 
				
			||||||
        uint32_t c0_c1[8]; /* Feature registers.  */
 | 
					 | 
				
			||||||
        uint32_t c0_c2[8]; /* Instruction set registers.  */
 | 
					 | 
				
			||||||
        uint32_t c1_sys; /* System control register.  */
 | 
					        uint32_t c1_sys; /* System control register.  */
 | 
				
			||||||
        uint32_t c1_coproc; /* Coprocessor access register.  */
 | 
					        uint32_t c1_coproc; /* Coprocessor access register.  */
 | 
				
			||||||
        uint32_t c1_xscaleauxcr; /* XScale auxiliary control register.  */
 | 
					        uint32_t c1_xscaleauxcr; /* XScale auxiliary control register.  */
 | 
				
			||||||
@ -228,12 +223,6 @@ typedef struct CPUARMState {
 | 
				
			|||||||
    /* Internal CPU feature flags.  */
 | 
					    /* Internal CPU feature flags.  */
 | 
				
			||||||
    uint32_t features;
 | 
					    uint32_t features;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Coprocessor IO used by peripherals */
 | 
					 | 
				
			||||||
    struct {
 | 
					 | 
				
			||||||
        ARMReadCPFunc *cp_read;
 | 
					 | 
				
			||||||
        ARMWriteCPFunc *cp_write;
 | 
					 | 
				
			||||||
        void *opaque;
 | 
					 | 
				
			||||||
    } cp[15];
 | 
					 | 
				
			||||||
    void *nvic;
 | 
					    void *nvic;
 | 
				
			||||||
    const struct arm_boot_info *boot_info;
 | 
					    const struct arm_boot_info *boot_info;
 | 
				
			||||||
} CPUARMState;
 | 
					} CPUARMState;
 | 
				
			||||||
@ -392,6 +381,11 @@ enum arm_features {
 | 
				
			|||||||
    ARM_FEATURE_VFP4, /* VFPv4 (implies that NEON is v2) */
 | 
					    ARM_FEATURE_VFP4, /* VFPv4 (implies that NEON is v2) */
 | 
				
			||||||
    ARM_FEATURE_GENERIC_TIMER,
 | 
					    ARM_FEATURE_GENERIC_TIMER,
 | 
				
			||||||
    ARM_FEATURE_MVFR, /* Media and VFP Feature Registers 0 and 1 */
 | 
					    ARM_FEATURE_MVFR, /* Media and VFP Feature Registers 0 and 1 */
 | 
				
			||||||
 | 
					    ARM_FEATURE_DUMMY_C15_REGS, /* RAZ/WI all of cp15 crn=15 */
 | 
				
			||||||
 | 
					    ARM_FEATURE_CACHE_TEST_CLEAN, /* 926/1026 style test-and-clean ops */
 | 
				
			||||||
 | 
					    ARM_FEATURE_CACHE_DIRTY_REG, /* 1136/1176 cache dirty status register */
 | 
				
			||||||
 | 
					    ARM_FEATURE_CACHE_BLOCK_OPS, /* v6 optional cache block operations */
 | 
				
			||||||
 | 
					    ARM_FEATURE_MPIDR, /* has cp15 MPIDR */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int arm_feature(CPUARMState *env, int feature)
 | 
					static inline int arm_feature(CPUARMState *env, int feature)
 | 
				
			||||||
@ -406,45 +400,215 @@ void armv7m_nvic_set_pending(void *opaque, int irq);
 | 
				
			|||||||
int armv7m_nvic_acknowledge_irq(void *opaque);
 | 
					int armv7m_nvic_acknowledge_irq(void *opaque);
 | 
				
			||||||
void armv7m_nvic_complete_irq(void *opaque, int irq);
 | 
					void armv7m_nvic_complete_irq(void *opaque, int irq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 | 
					/* Interface for defining coprocessor registers.
 | 
				
			||||||
                       ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write,
 | 
					 * Registers are defined in tables of arm_cp_reginfo structs
 | 
				
			||||||
                       void *opaque);
 | 
					 * which are passed to define_arm_cp_regs().
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* When looking up a coprocessor register we look for it
 | 
				
			||||||
 | 
					 * via an integer which encodes all of:
 | 
				
			||||||
 | 
					 *  coprocessor number
 | 
				
			||||||
 | 
					 *  Crn, Crm, opc1, opc2 fields
 | 
				
			||||||
 | 
					 *  32 or 64 bit register (ie is it accessed via MRC/MCR
 | 
				
			||||||
 | 
					 *    or via MRRC/MCRR?)
 | 
				
			||||||
 | 
					 * We allow 4 bits for opc1 because MRRC/MCRR have a 4 bit field.
 | 
				
			||||||
 | 
					 * (In this case crn and opc2 should be zero.)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define ENCODE_CP_REG(cp, is64, crn, crm, opc1, opc2)   \
 | 
				
			||||||
 | 
					    (((cp) << 16) | ((is64) << 15) | ((crn) << 11) |    \
 | 
				
			||||||
 | 
					     ((crm) << 7) | ((opc1) << 3) | (opc2))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DECODE_CPREG_CRN(enc) (((enc) >> 7) & 0xf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
 | 
				
			||||||
 | 
					 * special-behaviour cp reg and bits [15..8] indicate what behaviour
 | 
				
			||||||
 | 
					 * it has. Otherwise it is a simple cp reg, where CONST indicates that
 | 
				
			||||||
 | 
					 * TCG can assume the value to be constant (ie load at translate time)
 | 
				
			||||||
 | 
					 * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
 | 
				
			||||||
 | 
					 * indicates that the TB should not be ended after a write to this register
 | 
				
			||||||
 | 
					 * (the default is that the TB ends after cp writes). OVERRIDE permits
 | 
				
			||||||
 | 
					 * a register definition to override a previous definition for the
 | 
				
			||||||
 | 
					 * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
 | 
				
			||||||
 | 
					 * old must have the OVERRIDE bit set.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define ARM_CP_SPECIAL 1
 | 
				
			||||||
 | 
					#define ARM_CP_CONST 2
 | 
				
			||||||
 | 
					#define ARM_CP_64BIT 4
 | 
				
			||||||
 | 
					#define ARM_CP_SUPPRESS_TB_END 8
 | 
				
			||||||
 | 
					#define ARM_CP_OVERRIDE 16
 | 
				
			||||||
 | 
					#define ARM_CP_NOP (ARM_CP_SPECIAL | (1 << 8))
 | 
				
			||||||
 | 
					#define ARM_CP_WFI (ARM_CP_SPECIAL | (2 << 8))
 | 
				
			||||||
 | 
					#define ARM_LAST_SPECIAL ARM_CP_WFI
 | 
				
			||||||
 | 
					/* Used only as a terminator for ARMCPRegInfo lists */
 | 
				
			||||||
 | 
					#define ARM_CP_SENTINEL 0xffff
 | 
				
			||||||
 | 
					/* Mask of only the flag bits in a type field */
 | 
				
			||||||
 | 
					#define ARM_CP_FLAG_MASK 0x1f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Return true if cptype is a valid type field. This is used to try to
 | 
				
			||||||
 | 
					 * catch errors where the sentinel has been accidentally left off the end
 | 
				
			||||||
 | 
					 * of a list of registers.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline bool cptype_valid(int cptype)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
 | 
				
			||||||
 | 
					        || ((cptype & ARM_CP_SPECIAL) &&
 | 
				
			||||||
 | 
					            (cptype <= ARM_LAST_SPECIAL));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Access rights:
 | 
				
			||||||
 | 
					 * We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
 | 
				
			||||||
 | 
					 * defines as PL0 (user), PL1 (fiq/irq/svc/abt/und/sys, ie privileged), and
 | 
				
			||||||
 | 
					 * PL2 (hyp). The other level which has Read and Write bits is Secure PL1
 | 
				
			||||||
 | 
					 * (ie any of the privileged modes in Secure state, or Monitor mode).
 | 
				
			||||||
 | 
					 * If a register is accessible in one privilege level it's always accessible
 | 
				
			||||||
 | 
					 * in higher privilege levels too. Since "Secure PL1" also follows this rule
 | 
				
			||||||
 | 
					 * (ie anything visible in PL2 is visible in S-PL1, some things are only
 | 
				
			||||||
 | 
					 * visible in S-PL1) but "Secure PL1" is a bit of a mouthful, we bend the
 | 
				
			||||||
 | 
					 * terminology a little and call this PL3.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If access permissions for a register are more complex than can be
 | 
				
			||||||
 | 
					 * described with these bits, then use a laxer set of restrictions, and
 | 
				
			||||||
 | 
					 * do the more restrictive/complex check inside a helper function.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define PL3_R 0x80
 | 
				
			||||||
 | 
					#define PL3_W 0x40
 | 
				
			||||||
 | 
					#define PL2_R (0x20 | PL3_R)
 | 
				
			||||||
 | 
					#define PL2_W (0x10 | PL3_W)
 | 
				
			||||||
 | 
					#define PL1_R (0x08 | PL2_R)
 | 
				
			||||||
 | 
					#define PL1_W (0x04 | PL2_W)
 | 
				
			||||||
 | 
					#define PL0_R (0x02 | PL1_R)
 | 
				
			||||||
 | 
					#define PL0_W (0x01 | PL1_W)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PL3_RW (PL3_R | PL3_W)
 | 
				
			||||||
 | 
					#define PL2_RW (PL2_R | PL2_W)
 | 
				
			||||||
 | 
					#define PL1_RW (PL1_R | PL1_W)
 | 
				
			||||||
 | 
					#define PL0_RW (PL0_R | PL0_W)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int arm_current_pl(CPUARMState *env)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR) {
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /* We don't currently implement the Virtualization or TrustZone
 | 
				
			||||||
 | 
					     * extensions, so PL2 and PL3 don't exist for us.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct ARMCPRegInfo ARMCPRegInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Access functions for coprocessor registers. These should return
 | 
				
			||||||
 | 
					 * 0 on success, or one of the EXCP_* constants if access should cause
 | 
				
			||||||
 | 
					 * an exception (in which case *value is not written).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef int CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque,
 | 
				
			||||||
 | 
					                     uint64_t *value);
 | 
				
			||||||
 | 
					typedef int CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque,
 | 
				
			||||||
 | 
					                      uint64_t value);
 | 
				
			||||||
 | 
					/* Hook function for register reset */
 | 
				
			||||||
 | 
					typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CP_ANY 0xff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Definition of an ARM coprocessor register */
 | 
				
			||||||
 | 
					struct ARMCPRegInfo {
 | 
				
			||||||
 | 
					    /* Name of register (useful mainly for debugging, need not be unique) */
 | 
				
			||||||
 | 
					    const char *name;
 | 
				
			||||||
 | 
					    /* Location of register: coprocessor number and (crn,crm,opc1,opc2)
 | 
				
			||||||
 | 
					     * tuple. Any of crm, opc1 and opc2 may be CP_ANY to indicate a
 | 
				
			||||||
 | 
					     * 'wildcard' field -- any value of that field in the MRC/MCR insn
 | 
				
			||||||
 | 
					     * will be decoded to this register. The register read and write
 | 
				
			||||||
 | 
					     * callbacks will be passed an ARMCPRegInfo with the crn/crm/opc1/opc2
 | 
				
			||||||
 | 
					     * used by the program, so it is possible to register a wildcard and
 | 
				
			||||||
 | 
					     * then behave differently on read/write if necessary.
 | 
				
			||||||
 | 
					     * For 64 bit registers, only crm and opc1 are relevant; crn and opc2
 | 
				
			||||||
 | 
					     * must both be zero.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    uint8_t cp;
 | 
				
			||||||
 | 
					    uint8_t crn;
 | 
				
			||||||
 | 
					    uint8_t crm;
 | 
				
			||||||
 | 
					    uint8_t opc1;
 | 
				
			||||||
 | 
					    uint8_t opc2;
 | 
				
			||||||
 | 
					    /* Register type: ARM_CP_* bits/values */
 | 
				
			||||||
 | 
					    int type;
 | 
				
			||||||
 | 
					    /* Access rights: PL*_[RW] */
 | 
				
			||||||
 | 
					    int access;
 | 
				
			||||||
 | 
					    /* The opaque pointer passed to define_arm_cp_regs_with_opaque() when
 | 
				
			||||||
 | 
					     * this register was defined: can be used to hand data through to the
 | 
				
			||||||
 | 
					     * register read/write functions, since they are passed the ARMCPRegInfo*.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void *opaque;
 | 
				
			||||||
 | 
					    /* Value of this register, if it is ARM_CP_CONST. Otherwise, if
 | 
				
			||||||
 | 
					     * fieldoffset is non-zero, the reset value of the register.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    uint64_t resetvalue;
 | 
				
			||||||
 | 
					    /* Offset of the field in CPUARMState for this register. This is not
 | 
				
			||||||
 | 
					     * needed if either:
 | 
				
			||||||
 | 
					     *  1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs
 | 
				
			||||||
 | 
					     *  2. both readfn and writefn are specified
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
 | 
				
			||||||
 | 
					    /* Function for handling reads of this register. If NULL, then reads
 | 
				
			||||||
 | 
					     * will be done by loading from the offset into CPUARMState specified
 | 
				
			||||||
 | 
					     * by fieldoffset.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    CPReadFn *readfn;
 | 
				
			||||||
 | 
					    /* Function for handling writes of this register. If NULL, then writes
 | 
				
			||||||
 | 
					     * will be done by writing to the offset into CPUARMState specified
 | 
				
			||||||
 | 
					     * by fieldoffset.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    CPWriteFn *writefn;
 | 
				
			||||||
 | 
					    /* Function for resetting the register. If NULL, then reset will be done
 | 
				
			||||||
 | 
					     * by writing resetvalue to the field specified in fieldoffset. If
 | 
				
			||||||
 | 
					     * fieldoffset is 0 then no reset will be done.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    CPResetFn *resetfn;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Macros which are lvalues for the field in CPUARMState for the
 | 
				
			||||||
 | 
					 * ARMCPRegInfo *ri.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define CPREG_FIELD32(env, ri) \
 | 
				
			||||||
 | 
					    (*(uint32_t *)((char *)(env) + (ri)->fieldoffset))
 | 
				
			||||||
 | 
					#define CPREG_FIELD64(env, ri) \
 | 
				
			||||||
 | 
					    (*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
 | 
				
			||||||
 | 
					                                    const ARMCPRegInfo *regs, void *opaque);
 | 
				
			||||||
 | 
					void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
 | 
				
			||||||
 | 
					                                       const ARMCPRegInfo *regs, void *opaque);
 | 
				
			||||||
 | 
					static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    define_arm_cp_regs_with_opaque(cpu, regs, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const ARMCPRegInfo *get_arm_cp_reginfo(ARMCPU *cpu, uint32_t encoded_cp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* CPWriteFn that can be used to implement writes-ignored behaviour */
 | 
				
			||||||
 | 
					int arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			||||||
 | 
					                        uint64_t value);
 | 
				
			||||||
 | 
					/* CPReadFn that can be used for read-as-zero behaviour */
 | 
				
			||||||
 | 
					int arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t *value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool cp_access_ok(CPUARMState *env,
 | 
				
			||||||
 | 
					                                const ARMCPRegInfo *ri, int isread)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (ri->access >> ((arm_current_pl(env) * 2) + isread)) & 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Does the core conform to the the "MicroController" profile. e.g. Cortex-M3.
 | 
					/* Does the core conform to the the "MicroController" profile. e.g. Cortex-M3.
 | 
				
			||||||
   Note the M in older cores (eg. ARM7TDMI) stands for Multiply. These are
 | 
					   Note the M in older cores (eg. ARM7TDMI) stands for Multiply. These are
 | 
				
			||||||
   conventional cores (ie. Application or Realtime profile).  */
 | 
					   conventional cores (ie. Application or Realtime profile).  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define IS_M(env) arm_feature(env, ARM_FEATURE_M)
 | 
					#define IS_M(env) arm_feature(env, ARM_FEATURE_M)
 | 
				
			||||||
#define ARM_CPUID(env) (env->cp15.c0_cpuid)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ARM_CPUID_ARM1026     0x4106a262
 | 
					 | 
				
			||||||
#define ARM_CPUID_ARM926      0x41069265
 | 
					 | 
				
			||||||
#define ARM_CPUID_ARM946      0x41059461
 | 
					 | 
				
			||||||
#define ARM_CPUID_TI915T      0x54029152
 | 
					#define ARM_CPUID_TI915T      0x54029152
 | 
				
			||||||
#define ARM_CPUID_TI925T      0x54029252
 | 
					#define ARM_CPUID_TI925T      0x54029252
 | 
				
			||||||
#define ARM_CPUID_SA1100      0x4401A11B
 | 
					 | 
				
			||||||
#define ARM_CPUID_SA1110      0x6901B119
 | 
					 | 
				
			||||||
#define ARM_CPUID_PXA250      0x69052100
 | 
					 | 
				
			||||||
#define ARM_CPUID_PXA255      0x69052d00
 | 
					 | 
				
			||||||
#define ARM_CPUID_PXA260      0x69052903
 | 
					 | 
				
			||||||
#define ARM_CPUID_PXA261      0x69052d05
 | 
					 | 
				
			||||||
#define ARM_CPUID_PXA262      0x69052d06
 | 
					 | 
				
			||||||
#define ARM_CPUID_PXA270      0x69054110
 | 
					 | 
				
			||||||
#define ARM_CPUID_PXA270_A0   0x69054110
 | 
					 | 
				
			||||||
#define ARM_CPUID_PXA270_A1   0x69054111
 | 
					 | 
				
			||||||
#define ARM_CPUID_PXA270_B0   0x69054112
 | 
					 | 
				
			||||||
#define ARM_CPUID_PXA270_B1   0x69054113
 | 
					 | 
				
			||||||
#define ARM_CPUID_PXA270_C0   0x69054114
 | 
					 | 
				
			||||||
#define ARM_CPUID_PXA270_C5   0x69054117
 | 
					 | 
				
			||||||
#define ARM_CPUID_ARM1136     0x4117b363
 | 
					 | 
				
			||||||
#define ARM_CPUID_ARM1136_R2  0x4107b362
 | 
					 | 
				
			||||||
#define ARM_CPUID_ARM1176     0x410fb767
 | 
					 | 
				
			||||||
#define ARM_CPUID_ARM11MPCORE 0x410fb022
 | 
					 | 
				
			||||||
#define ARM_CPUID_CORTEXA8    0x410fc080
 | 
					 | 
				
			||||||
#define ARM_CPUID_CORTEXA9    0x410fc090
 | 
					 | 
				
			||||||
#define ARM_CPUID_CORTEXA15   0x412fc0f1
 | 
					 | 
				
			||||||
#define ARM_CPUID_CORTEXM3    0x410fc231
 | 
					 | 
				
			||||||
#define ARM_CPUID_ANY         0xffffffff
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(CONFIG_USER_ONLY)
 | 
					#if defined(CONFIG_USER_ONLY)
 | 
				
			||||||
#define TARGET_PAGE_BITS 12
 | 
					#define TARGET_PAGE_BITS 12
 | 
				
			||||||
@ -472,7 +636,7 @@ static inline CPUARMState *cpu_init(const char *cpu_model)
 | 
				
			|||||||
#define cpu_signal_handler cpu_arm_signal_handler
 | 
					#define cpu_signal_handler cpu_arm_signal_handler
 | 
				
			||||||
#define cpu_list arm_cpu_list
 | 
					#define cpu_list arm_cpu_list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CPU_SAVE_VERSION 6
 | 
					#define CPU_SAVE_VERSION 7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* MMU modes definitions */
 | 
					/* MMU modes definitions */
 | 
				
			||||||
#define MMU_MODE0_SUFFIX _kernel
 | 
					#define MMU_MODE0_SUFFIX _kernel
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2070
									
								
								target-arm/helper.c
									
									
									
									
									
								
							
							
						
						
									
										2070
									
								
								target-arm/helper.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -59,11 +59,10 @@ DEF_HELPER_0(cpsr_read, i32)
 | 
				
			|||||||
DEF_HELPER_3(v7m_msr, void, env, i32, i32)
 | 
					DEF_HELPER_3(v7m_msr, void, env, i32, i32)
 | 
				
			||||||
DEF_HELPER_2(v7m_mrs, i32, env, i32)
 | 
					DEF_HELPER_2(v7m_mrs, i32, env, i32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEF_HELPER_3(set_cp15, void, env, i32, i32)
 | 
					DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
 | 
				
			||||||
DEF_HELPER_2(get_cp15, i32, env, i32)
 | 
					DEF_HELPER_2(get_cp_reg, i32, env, ptr)
 | 
				
			||||||
 | 
					DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
 | 
				
			||||||
DEF_HELPER_3(set_cp, void, env, i32, i32)
 | 
					DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
 | 
				
			||||||
DEF_HELPER_2(get_cp, i32, env, i32)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEF_HELPER_2(get_r13_banked, i32, env, i32)
 | 
					DEF_HELPER_2(get_r13_banked, i32, env, i32)
 | 
				
			||||||
DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
 | 
					DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
 | 
				
			||||||
@ -459,8 +458,6 @@ DEF_HELPER_3(iwmmxt_muladdsl, i64, i64, i32, i32)
 | 
				
			|||||||
DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32)
 | 
					DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32)
 | 
				
			||||||
DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32)
 | 
					DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEF_HELPER_2(set_teecr, void, env, i32)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
DEF_HELPER_3(neon_unzip8, void, env, i32, i32)
 | 
					DEF_HELPER_3(neon_unzip8, void, env, i32, i32)
 | 
				
			||||||
DEF_HELPER_3(neon_unzip16, void, env, i32, i32)
 | 
					DEF_HELPER_3(neon_unzip16, void, env, i32, i32)
 | 
				
			||||||
DEF_HELPER_3(neon_qunzip8, void, env, i32, i32)
 | 
					DEF_HELPER_3(neon_qunzip8, void, env, i32, i32)
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,6 @@ void cpu_save(QEMUFile *f, void *opaque)
 | 
				
			|||||||
        qemu_put_be32(f, env->fiq_regs[i]);
 | 
					        qemu_put_be32(f, env->fiq_regs[i]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    qemu_put_be32(f, env->cp15.c0_cpuid);
 | 
					    qemu_put_be32(f, env->cp15.c0_cpuid);
 | 
				
			||||||
    qemu_put_be32(f, env->cp15.c0_cachetype);
 | 
					 | 
				
			||||||
    qemu_put_be32(f, env->cp15.c0_cssel);
 | 
					    qemu_put_be32(f, env->cp15.c0_cssel);
 | 
				
			||||||
    qemu_put_be32(f, env->cp15.c1_sys);
 | 
					    qemu_put_be32(f, env->cp15.c1_sys);
 | 
				
			||||||
    qemu_put_be32(f, env->cp15.c1_coproc);
 | 
					    qemu_put_be32(f, env->cp15.c1_coproc);
 | 
				
			||||||
@ -139,7 +138,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
 | 
				
			|||||||
        env->fiq_regs[i] = qemu_get_be32(f);
 | 
					        env->fiq_regs[i] = qemu_get_be32(f);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    env->cp15.c0_cpuid = qemu_get_be32(f);
 | 
					    env->cp15.c0_cpuid = qemu_get_be32(f);
 | 
				
			||||||
    env->cp15.c0_cachetype = qemu_get_be32(f);
 | 
					 | 
				
			||||||
    env->cp15.c0_cssel = qemu_get_be32(f);
 | 
					    env->cp15.c0_cssel = qemu_get_be32(f);
 | 
				
			||||||
    env->cp15.c1_sys = qemu_get_be32(f);
 | 
					    env->cp15.c1_sys = qemu_get_be32(f);
 | 
				
			||||||
    env->cp15.c1_coproc = qemu_get_be32(f);
 | 
					    env->cp15.c1_coproc = qemu_get_be32(f);
 | 
				
			||||||
 | 
				
			|||||||
@ -23,13 +23,11 @@
 | 
				
			|||||||
#define SIGNBIT (uint32_t)0x80000000
 | 
					#define SIGNBIT (uint32_t)0x80000000
 | 
				
			||||||
#define SIGNBIT64 ((uint64_t)1 << 63)
 | 
					#define SIGNBIT64 ((uint64_t)1 << 63)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if !defined(CONFIG_USER_ONLY)
 | 
					 | 
				
			||||||
static void raise_exception(int tt)
 | 
					static void raise_exception(int tt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    env->exception_index = tt;
 | 
					    env->exception_index = tt;
 | 
				
			||||||
    cpu_loop_exit(env);
 | 
					    cpu_loop_exit(env);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
 | 
					uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
 | 
				
			||||||
                          uint32_t rn, uint32_t maxindex)
 | 
					                          uint32_t rn, uint32_t maxindex)
 | 
				
			||||||
@ -287,6 +285,46 @@ void HELPER(set_user_reg)(uint32_t regno, uint32_t val)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HELPER(set_cp_reg)(CPUARMState *env, void *rip, uint32_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const ARMCPRegInfo *ri = rip;
 | 
				
			||||||
 | 
					    int excp = ri->writefn(env, ri, value);
 | 
				
			||||||
 | 
					    if (excp) {
 | 
				
			||||||
 | 
					        raise_exception(excp);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t HELPER(get_cp_reg)(CPUARMState *env, void *rip)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const ARMCPRegInfo *ri = rip;
 | 
				
			||||||
 | 
					    uint64_t value;
 | 
				
			||||||
 | 
					    int excp = ri->readfn(env, ri, &value);
 | 
				
			||||||
 | 
					    if (excp) {
 | 
				
			||||||
 | 
					        raise_exception(excp);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HELPER(set_cp_reg64)(CPUARMState *env, void *rip, uint64_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const ARMCPRegInfo *ri = rip;
 | 
				
			||||||
 | 
					    int excp = ri->writefn(env, ri, value);
 | 
				
			||||||
 | 
					    if (excp) {
 | 
				
			||||||
 | 
					        raise_exception(excp);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const ARMCPRegInfo *ri = rip;
 | 
				
			||||||
 | 
					    uint64_t value;
 | 
				
			||||||
 | 
					    int excp = ri->readfn(env, ri, &value);
 | 
				
			||||||
 | 
					    if (excp) {
 | 
				
			||||||
 | 
					        raise_exception(excp);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ??? Flag setting arithmetic is awkward because we need to do comparisons.
 | 
					/* ??? Flag setting arithmetic is awkward because we need to do comparisons.
 | 
				
			||||||
   The only way to do that in TCG is a conditional branch, which clobbers
 | 
					   The only way to do that in TCG is a conditional branch, which clobbers
 | 
				
			||||||
   all our temporaries.  For now implement these as helper functions.  */
 | 
					   all our temporaries.  For now implement these as helper functions.  */
 | 
				
			||||||
 | 
				
			|||||||
@ -2439,226 +2439,6 @@ static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
 | 
				
			|||||||
    return 1;
 | 
					    return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Disassemble system coprocessor instruction.  Return nonzero if
 | 
					 | 
				
			||||||
   instruction is not defined.  */
 | 
					 | 
				
			||||||
static int disas_cp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    TCGv tmp, tmp2;
 | 
					 | 
				
			||||||
    uint32_t rd = (insn >> 12) & 0xf;
 | 
					 | 
				
			||||||
    uint32_t cp = (insn >> 8) & 0xf;
 | 
					 | 
				
			||||||
    if (IS_USER(s)) {
 | 
					 | 
				
			||||||
        return 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (insn & ARM_CP_RW_BIT) {
 | 
					 | 
				
			||||||
        if (!env->cp[cp].cp_read)
 | 
					 | 
				
			||||||
            return 1;
 | 
					 | 
				
			||||||
        gen_set_pc_im(s->pc);
 | 
					 | 
				
			||||||
        tmp = tcg_temp_new_i32();
 | 
					 | 
				
			||||||
        tmp2 = tcg_const_i32(insn);
 | 
					 | 
				
			||||||
        gen_helper_get_cp(tmp, cpu_env, tmp2);
 | 
					 | 
				
			||||||
        tcg_temp_free(tmp2);
 | 
					 | 
				
			||||||
        store_reg(s, rd, tmp);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        if (!env->cp[cp].cp_write)
 | 
					 | 
				
			||||||
            return 1;
 | 
					 | 
				
			||||||
        gen_set_pc_im(s->pc);
 | 
					 | 
				
			||||||
        tmp = load_reg(s, rd);
 | 
					 | 
				
			||||||
        tmp2 = tcg_const_i32(insn);
 | 
					 | 
				
			||||||
        gen_helper_set_cp(cpu_env, tmp2, tmp);
 | 
					 | 
				
			||||||
        tcg_temp_free(tmp2);
 | 
					 | 
				
			||||||
        tcg_temp_free_i32(tmp);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int cp15_user_ok(CPUARMState *env, uint32_t insn)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int cpn = (insn >> 16) & 0xf;
 | 
					 | 
				
			||||||
    int cpm = insn & 0xf;
 | 
					 | 
				
			||||||
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (arm_feature(env, ARM_FEATURE_V7) && cpn == 9) {
 | 
					 | 
				
			||||||
        /* Performance monitor registers fall into three categories:
 | 
					 | 
				
			||||||
         *  (a) always UNDEF in usermode
 | 
					 | 
				
			||||||
         *  (b) UNDEF only if PMUSERENR.EN is 0
 | 
					 | 
				
			||||||
         *  (c) always read OK and UNDEF on write (PMUSERENR only)
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        if ((cpm == 12 && (op < 6)) ||
 | 
					 | 
				
			||||||
            (cpm == 13 && (op < 3))) {
 | 
					 | 
				
			||||||
            return env->cp15.c9_pmuserenr;
 | 
					 | 
				
			||||||
        } else if (cpm == 14 && op == 0 && (insn & ARM_CP_RW_BIT)) {
 | 
					 | 
				
			||||||
            /* PMUSERENR, read only */
 | 
					 | 
				
			||||||
            return 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (cpn == 13 && cpm == 0) {
 | 
					 | 
				
			||||||
        /* TLS register.  */
 | 
					 | 
				
			||||||
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
 | 
					 | 
				
			||||||
            return 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int cp15_tls_load_store(CPUARMState *env, DisasContext *s, uint32_t insn, uint32_t rd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    TCGv tmp;
 | 
					 | 
				
			||||||
    int cpn = (insn >> 16) & 0xf;
 | 
					 | 
				
			||||||
    int cpm = insn & 0xf;
 | 
					 | 
				
			||||||
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!arm_feature(env, ARM_FEATURE_V6K))
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!(cpn == 13 && cpm == 0))
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (insn & ARM_CP_RW_BIT) {
 | 
					 | 
				
			||||||
        switch (op) {
 | 
					 | 
				
			||||||
        case 2:
 | 
					 | 
				
			||||||
            tmp = load_cpu_field(cp15.c13_tls1);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case 3:
 | 
					 | 
				
			||||||
            tmp = load_cpu_field(cp15.c13_tls2);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case 4:
 | 
					 | 
				
			||||||
            tmp = load_cpu_field(cp15.c13_tls3);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        store_reg(s, rd, tmp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        tmp = load_reg(s, rd);
 | 
					 | 
				
			||||||
        switch (op) {
 | 
					 | 
				
			||||||
        case 2:
 | 
					 | 
				
			||||||
            store_cpu_field(tmp, cp15.c13_tls1);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case 3:
 | 
					 | 
				
			||||||
            store_cpu_field(tmp, cp15.c13_tls2);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case 4:
 | 
					 | 
				
			||||||
            store_cpu_field(tmp, cp15.c13_tls3);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
            tcg_temp_free_i32(tmp);
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
 | 
					 | 
				
			||||||
   instruction is not defined.  */
 | 
					 | 
				
			||||||
static int disas_cp15_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    uint32_t rd;
 | 
					 | 
				
			||||||
    TCGv tmp, tmp2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* M profile cores use memory mapped registers instead of cp15.  */
 | 
					 | 
				
			||||||
    if (arm_feature(env, ARM_FEATURE_M))
 | 
					 | 
				
			||||||
	return 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ((insn & (1 << 25)) == 0) {
 | 
					 | 
				
			||||||
        if (insn & (1 << 20)) {
 | 
					 | 
				
			||||||
            /* mrrc */
 | 
					 | 
				
			||||||
            return 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        /* mcrr.  Used for block cache operations, so implement as no-op.  */
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if ((insn & (1 << 4)) == 0) {
 | 
					 | 
				
			||||||
        /* cdp */
 | 
					 | 
				
			||||||
        return 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    /* We special case a number of cp15 instructions which were used
 | 
					 | 
				
			||||||
     * for things which are real instructions in ARMv7. This allows
 | 
					 | 
				
			||||||
     * them to work in linux-user mode which doesn't provide functional
 | 
					 | 
				
			||||||
     * get_cp15/set_cp15 helpers, and is more efficient anyway.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    switch ((insn & 0x0fff0fff)) {
 | 
					 | 
				
			||||||
    case 0x0e070f90:
 | 
					 | 
				
			||||||
        /* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores).
 | 
					 | 
				
			||||||
         * In v7, this must NOP.
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        if (IS_USER(s)) {
 | 
					 | 
				
			||||||
            return 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (!arm_feature(env, ARM_FEATURE_V7)) {
 | 
					 | 
				
			||||||
            /* Wait for interrupt.  */
 | 
					 | 
				
			||||||
            gen_set_pc_im(s->pc);
 | 
					 | 
				
			||||||
            s->is_jmp = DISAS_WFI;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
    case 0x0e070f58:
 | 
					 | 
				
			||||||
        /* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI,
 | 
					 | 
				
			||||||
         * so this is slightly over-broad.
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        if (!IS_USER(s) && !arm_feature(env, ARM_FEATURE_V6)) {
 | 
					 | 
				
			||||||
            /* Wait for interrupt.  */
 | 
					 | 
				
			||||||
            gen_set_pc_im(s->pc);
 | 
					 | 
				
			||||||
            s->is_jmp = DISAS_WFI;
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        /* Otherwise continue to handle via helper function.
 | 
					 | 
				
			||||||
         * In particular, on v7 and some v6 cores this is one of
 | 
					 | 
				
			||||||
         * the VA-PA registers.
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    case 0x0e070f3d:
 | 
					 | 
				
			||||||
        /* 0,c7,c13,1: prefetch-by-MVA in v6, NOP in v7 */
 | 
					 | 
				
			||||||
        if (arm_feature(env, ARM_FEATURE_V6)) {
 | 
					 | 
				
			||||||
            return IS_USER(s) ? 1 : 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    case 0x0e070f95: /* 0,c7,c5,4 : ISB */
 | 
					 | 
				
			||||||
    case 0x0e070f9a: /* 0,c7,c10,4: DSB */
 | 
					 | 
				
			||||||
    case 0x0e070fba: /* 0,c7,c10,5: DMB */
 | 
					 | 
				
			||||||
        /* Barriers in both v6 and v7 */
 | 
					 | 
				
			||||||
        if (arm_feature(env, ARM_FEATURE_V6)) {
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (IS_USER(s) && !cp15_user_ok(env, insn)) {
 | 
					 | 
				
			||||||
        return 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    rd = (insn >> 12) & 0xf;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (cp15_tls_load_store(env, s, insn, rd))
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tmp2 = tcg_const_i32(insn);
 | 
					 | 
				
			||||||
    if (insn & ARM_CP_RW_BIT) {
 | 
					 | 
				
			||||||
        tmp = tcg_temp_new_i32();
 | 
					 | 
				
			||||||
        gen_helper_get_cp15(tmp, cpu_env, tmp2);
 | 
					 | 
				
			||||||
        /* If the destination register is r15 then sets condition codes.  */
 | 
					 | 
				
			||||||
        if (rd != 15)
 | 
					 | 
				
			||||||
            store_reg(s, rd, tmp);
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            tcg_temp_free_i32(tmp);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        tmp = load_reg(s, rd);
 | 
					 | 
				
			||||||
        gen_helper_set_cp15(cpu_env, tmp2, tmp);
 | 
					 | 
				
			||||||
        tcg_temp_free_i32(tmp);
 | 
					 | 
				
			||||||
        /* Normally we would always end the TB here, but Linux
 | 
					 | 
				
			||||||
         * arch/arm/mach-pxa/sleep.S expects two instructions following
 | 
					 | 
				
			||||||
         * an MMU enable to execute from cache.  Imitate this behaviour.  */
 | 
					 | 
				
			||||||
        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
 | 
					 | 
				
			||||||
                (insn & 0x0fff0fff) != 0x0e010f10)
 | 
					 | 
				
			||||||
            gen_lookup_tb(s);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    tcg_temp_free_i32(tmp2);
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
 | 
					#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
 | 
				
			||||||
#define VFP_SREG(insn, bigbit, smallbit) \
 | 
					#define VFP_SREG(insn, bigbit, smallbit) \
 | 
				
			||||||
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
 | 
					  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
 | 
				
			||||||
@ -6388,104 +6168,18 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int disas_cp14_read(CPUARMState * env, DisasContext *s, uint32_t insn)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int crn = (insn >> 16) & 0xf;
 | 
					 | 
				
			||||||
    int crm = insn & 0xf;
 | 
					 | 
				
			||||||
    int op1 = (insn >> 21) & 7;
 | 
					 | 
				
			||||||
    int op2 = (insn >> 5) & 7;
 | 
					 | 
				
			||||||
    int rt = (insn >> 12) & 0xf;
 | 
					 | 
				
			||||||
    TCGv tmp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* Minimal set of debug registers, since we don't support debug */
 | 
					 | 
				
			||||||
    if (op1 == 0 && crn == 0 && op2 == 0) {
 | 
					 | 
				
			||||||
        switch (crm) {
 | 
					 | 
				
			||||||
        case 0:
 | 
					 | 
				
			||||||
            /* DBGDIDR: just RAZ. In particular this means the
 | 
					 | 
				
			||||||
             * "debug architecture version" bits will read as
 | 
					 | 
				
			||||||
             * a reserved value, which should cause Linux to
 | 
					 | 
				
			||||||
             * not try to use the debug hardware.
 | 
					 | 
				
			||||||
             */
 | 
					 | 
				
			||||||
            tmp = tcg_const_i32(0);
 | 
					 | 
				
			||||||
            store_reg(s, rt, tmp);
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        case 1:
 | 
					 | 
				
			||||||
        case 2:
 | 
					 | 
				
			||||||
            /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
 | 
					 | 
				
			||||||
             * don't implement memory mapped debug components
 | 
					 | 
				
			||||||
             */
 | 
					 | 
				
			||||||
            if (ENABLE_ARCH_7) {
 | 
					 | 
				
			||||||
                tmp = tcg_const_i32(0);
 | 
					 | 
				
			||||||
                store_reg(s, rt, tmp);
 | 
					 | 
				
			||||||
                return 0;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
 | 
					 | 
				
			||||||
        if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
 | 
					 | 
				
			||||||
            /* TEECR */
 | 
					 | 
				
			||||||
            if (IS_USER(s))
 | 
					 | 
				
			||||||
                return 1;
 | 
					 | 
				
			||||||
            tmp = load_cpu_field(teecr);
 | 
					 | 
				
			||||||
            store_reg(s, rt, tmp);
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
 | 
					 | 
				
			||||||
            /* TEEHBR */
 | 
					 | 
				
			||||||
            if (IS_USER(s) && (env->teecr & 1))
 | 
					 | 
				
			||||||
                return 1;
 | 
					 | 
				
			||||||
            tmp = load_cpu_field(teehbr);
 | 
					 | 
				
			||||||
            store_reg(s, rt, tmp);
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int disas_cp14_write(CPUARMState * env, DisasContext *s, uint32_t insn)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int crn = (insn >> 16) & 0xf;
 | 
					 | 
				
			||||||
    int crm = insn & 0xf;
 | 
					 | 
				
			||||||
    int op1 = (insn >> 21) & 7;
 | 
					 | 
				
			||||||
    int op2 = (insn >> 5) & 7;
 | 
					 | 
				
			||||||
    int rt = (insn >> 12) & 0xf;
 | 
					 | 
				
			||||||
    TCGv tmp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
 | 
					 | 
				
			||||||
        if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
 | 
					 | 
				
			||||||
            /* TEECR */
 | 
					 | 
				
			||||||
            if (IS_USER(s))
 | 
					 | 
				
			||||||
                return 1;
 | 
					 | 
				
			||||||
            tmp = load_reg(s, rt);
 | 
					 | 
				
			||||||
            gen_helper_set_teecr(cpu_env, tmp);
 | 
					 | 
				
			||||||
            tcg_temp_free_i32(tmp);
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
 | 
					 | 
				
			||||||
            /* TEEHBR */
 | 
					 | 
				
			||||||
            if (IS_USER(s) && (env->teecr & 1))
 | 
					 | 
				
			||||||
                return 1;
 | 
					 | 
				
			||||||
            tmp = load_reg(s, rt);
 | 
					 | 
				
			||||||
            store_cpu_field(tmp, teehbr);
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
 | 
					static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int cpnum;
 | 
					    int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
 | 
				
			||||||
 | 
					    const ARMCPRegInfo *ri;
 | 
				
			||||||
 | 
					    ARMCPU *cpu = arm_env_get_cpu(env);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cpnum = (insn >> 8) & 0xf;
 | 
					    cpnum = (insn >> 8) & 0xf;
 | 
				
			||||||
    if (arm_feature(env, ARM_FEATURE_XSCALE)
 | 
					    if (arm_feature(env, ARM_FEATURE_XSCALE)
 | 
				
			||||||
	    && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
 | 
						    && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* First check for coprocessor space used for actual instructions */
 | 
				
			||||||
    switch (cpnum) {
 | 
					    switch (cpnum) {
 | 
				
			||||||
      case 0:
 | 
					      case 0:
 | 
				
			||||||
      case 1:
 | 
					      case 1:
 | 
				
			||||||
@ -6498,22 +6192,154 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
 | 
				
			|||||||
    case 10:
 | 
					    case 10:
 | 
				
			||||||
    case 11:
 | 
					    case 11:
 | 
				
			||||||
	return disas_vfp_insn (env, s, insn);
 | 
						return disas_vfp_insn (env, s, insn);
 | 
				
			||||||
    case 14:
 | 
					 | 
				
			||||||
        /* Coprocessors 7-15 are architecturally reserved by ARM.
 | 
					 | 
				
			||||||
           Unfortunately Intel decided to ignore this.  */
 | 
					 | 
				
			||||||
        if (arm_feature(env, ARM_FEATURE_XSCALE))
 | 
					 | 
				
			||||||
            goto board;
 | 
					 | 
				
			||||||
        if (insn & (1 << 20))
 | 
					 | 
				
			||||||
            return disas_cp14_read(env, s, insn);
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            return disas_cp14_write(env, s, insn);
 | 
					 | 
				
			||||||
    case 15:
 | 
					 | 
				
			||||||
	return disas_cp15_insn (env, s, insn);
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
    board:
 | 
					        break;
 | 
				
			||||||
	/* Unknown coprocessor.  See if the board has hooked it.  */
 | 
					 | 
				
			||||||
	return disas_cp_insn (env, s, insn);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Otherwise treat as a generic register access */
 | 
				
			||||||
 | 
					    is64 = (insn & (1 << 25)) == 0;
 | 
				
			||||||
 | 
					    if (!is64 && ((insn & (1 << 4)) == 0)) {
 | 
				
			||||||
 | 
					        /* cdp */
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    crm = insn & 0xf;
 | 
				
			||||||
 | 
					    if (is64) {
 | 
				
			||||||
 | 
					        crn = 0;
 | 
				
			||||||
 | 
					        opc1 = (insn >> 4) & 0xf;
 | 
				
			||||||
 | 
					        opc2 = 0;
 | 
				
			||||||
 | 
					        rt2 = (insn >> 16) & 0xf;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        crn = (insn >> 16) & 0xf;
 | 
				
			||||||
 | 
					        opc1 = (insn >> 21) & 7;
 | 
				
			||||||
 | 
					        opc2 = (insn >> 5) & 7;
 | 
				
			||||||
 | 
					        rt2 = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    isread = (insn >> 20) & 1;
 | 
				
			||||||
 | 
					    rt = (insn >> 12) & 0xf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ri = get_arm_cp_reginfo(cpu,
 | 
				
			||||||
 | 
					                            ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2));
 | 
				
			||||||
 | 
					    if (ri) {
 | 
				
			||||||
 | 
					        /* Check access permissions */
 | 
				
			||||||
 | 
					        if (!cp_access_ok(env, ri, isread)) {
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Handle special cases first */
 | 
				
			||||||
 | 
					        switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
 | 
				
			||||||
 | 
					        case ARM_CP_NOP:
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        case ARM_CP_WFI:
 | 
				
			||||||
 | 
					            if (isread) {
 | 
				
			||||||
 | 
					                return 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            gen_set_pc_im(s->pc);
 | 
				
			||||||
 | 
					            s->is_jmp = DISAS_WFI;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (isread) {
 | 
				
			||||||
 | 
					            /* Read */
 | 
				
			||||||
 | 
					            if (is64) {
 | 
				
			||||||
 | 
					                TCGv_i64 tmp64;
 | 
				
			||||||
 | 
					                TCGv_i32 tmp;
 | 
				
			||||||
 | 
					                if (ri->type & ARM_CP_CONST) {
 | 
				
			||||||
 | 
					                    tmp64 = tcg_const_i64(ri->resetvalue);
 | 
				
			||||||
 | 
					                } else if (ri->readfn) {
 | 
				
			||||||
 | 
					                    TCGv_ptr tmpptr;
 | 
				
			||||||
 | 
					                    gen_set_pc_im(s->pc);
 | 
				
			||||||
 | 
					                    tmp64 = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					                    tmpptr = tcg_const_ptr(ri);
 | 
				
			||||||
 | 
					                    gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
 | 
				
			||||||
 | 
					                    tcg_temp_free_ptr(tmpptr);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    tmp64 = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					                    tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                tmp = tcg_temp_new_i32();
 | 
				
			||||||
 | 
					                tcg_gen_trunc_i64_i32(tmp, tmp64);
 | 
				
			||||||
 | 
					                store_reg(s, rt, tmp);
 | 
				
			||||||
 | 
					                tcg_gen_shri_i64(tmp64, tmp64, 32);
 | 
				
			||||||
 | 
					                tcg_gen_trunc_i64_i32(tmp, tmp64);
 | 
				
			||||||
 | 
					                store_reg(s, rt2, tmp);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                TCGv tmp;
 | 
				
			||||||
 | 
					                if (ri->type & ARM_CP_CONST) {
 | 
				
			||||||
 | 
					                    tmp = tcg_const_i32(ri->resetvalue);
 | 
				
			||||||
 | 
					                } else if (ri->readfn) {
 | 
				
			||||||
 | 
					                    TCGv_ptr tmpptr;
 | 
				
			||||||
 | 
					                    gen_set_pc_im(s->pc);
 | 
				
			||||||
 | 
					                    tmp = tcg_temp_new_i32();
 | 
				
			||||||
 | 
					                    tmpptr = tcg_const_ptr(ri);
 | 
				
			||||||
 | 
					                    gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
 | 
				
			||||||
 | 
					                    tcg_temp_free_ptr(tmpptr);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    tmp = load_cpu_offset(ri->fieldoffset);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (rt == 15) {
 | 
				
			||||||
 | 
					                    /* Destination register of r15 for 32 bit loads sets
 | 
				
			||||||
 | 
					                     * the condition codes from the high 4 bits of the value
 | 
				
			||||||
 | 
					                     */
 | 
				
			||||||
 | 
					                    gen_set_nzcv(tmp);
 | 
				
			||||||
 | 
					                    tcg_temp_free_i32(tmp);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    store_reg(s, rt, tmp);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            /* Write */
 | 
				
			||||||
 | 
					            if (ri->type & ARM_CP_CONST) {
 | 
				
			||||||
 | 
					                /* If not forbidden by access permissions, treat as WI */
 | 
				
			||||||
 | 
					                return 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (is64) {
 | 
				
			||||||
 | 
					                TCGv tmplo, tmphi;
 | 
				
			||||||
 | 
					                TCGv_i64 tmp64 = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					                tmplo = load_reg(s, rt);
 | 
				
			||||||
 | 
					                tmphi = load_reg(s, rt2);
 | 
				
			||||||
 | 
					                tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
 | 
				
			||||||
 | 
					                tcg_temp_free_i32(tmplo);
 | 
				
			||||||
 | 
					                tcg_temp_free_i32(tmphi);
 | 
				
			||||||
 | 
					                if (ri->writefn) {
 | 
				
			||||||
 | 
					                    TCGv_ptr tmpptr = tcg_const_ptr(ri);
 | 
				
			||||||
 | 
					                    gen_set_pc_im(s->pc);
 | 
				
			||||||
 | 
					                    gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
 | 
				
			||||||
 | 
					                    tcg_temp_free_ptr(tmpptr);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                tcg_temp_free_i64(tmp64);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                if (ri->writefn) {
 | 
				
			||||||
 | 
					                    TCGv tmp;
 | 
				
			||||||
 | 
					                    TCGv_ptr tmpptr;
 | 
				
			||||||
 | 
					                    gen_set_pc_im(s->pc);
 | 
				
			||||||
 | 
					                    tmp = load_reg(s, rt);
 | 
				
			||||||
 | 
					                    tmpptr = tcg_const_ptr(ri);
 | 
				
			||||||
 | 
					                    gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
 | 
				
			||||||
 | 
					                    tcg_temp_free_ptr(tmpptr);
 | 
				
			||||||
 | 
					                    tcg_temp_free_i32(tmp);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    TCGv tmp = load_reg(s, rt);
 | 
				
			||||||
 | 
					                    store_cpu_offset(tmp, ri->fieldoffset);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            /* We default to ending the TB on a coprocessor register write,
 | 
				
			||||||
 | 
					             * but allow this to be suppressed by the register definition
 | 
				
			||||||
 | 
					             * (usually only necessary to work around guest bugs).
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            if (!(ri->type & ARM_CP_SUPPRESS_TB_END)) {
 | 
				
			||||||
 | 
					                gen_lookup_tb(s);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user