ARM946 CPU support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2783 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									9455455016
								
							
						
					
					
						commit
						ce8198612e
					
				@ -251,7 +251,7 @@ static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
 | 
				
			|||||||
                    ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
 | 
					                    ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
 | 
				
			||||||
            s->env->cp15.c1_sys = 0;
 | 
					            s->env->cp15.c1_sys = 0;
 | 
				
			||||||
            s->env->cp15.c1_coproc = 0;
 | 
					            s->env->cp15.c1_coproc = 0;
 | 
				
			||||||
            s->env->cp15.c2 = 0;
 | 
					            s->env->cp15.c2_base = 0;
 | 
				
			||||||
            s->env->cp15.c3 = 0;
 | 
					            s->env->cp15.c3 = 0;
 | 
				
			||||||
            s->pm_regs[PSSR >> 2] |= 0x8;	/* Set STS */
 | 
					            s->pm_regs[PSSR >> 2] |= 0x8;	/* Set STS */
 | 
				
			||||||
            s->pm_regs[RCSR >> 2] |= 0x8;	/* Set GPR */
 | 
					            s->pm_regs[RCSR >> 2] |= 0x8;	/* Set GPR */
 | 
				
			||||||
 | 
				
			|||||||
@ -77,7 +77,7 @@ For system emulation, the following hardware targets are supported:
 | 
				
			|||||||
@item Sun4m (32-bit Sparc processor)
 | 
					@item Sun4m (32-bit Sparc processor)
 | 
				
			||||||
@item Sun4u (64-bit Sparc processor, in progress)
 | 
					@item Sun4u (64-bit Sparc processor, in progress)
 | 
				
			||||||
@item Malta board (32-bit MIPS processor)
 | 
					@item Malta board (32-bit MIPS processor)
 | 
				
			||||||
@item ARM Integrator/CP (ARM926E or 1026E processor)
 | 
					@item ARM Integrator/CP (ARM926E, 1026E or 946E processor)
 | 
				
			||||||
@item ARM Versatile baseboard (ARM926E)
 | 
					@item ARM Versatile baseboard (ARM926E)
 | 
				
			||||||
@item ARM RealView Emulation baseboard (ARM926EJ-S)
 | 
					@item ARM RealView Emulation baseboard (ARM926EJ-S)
 | 
				
			||||||
@item Spitz, Akita, Borzoi and Terrier PDAs (PXA270 processor)
 | 
					@item Spitz, Akita, Borzoi and Terrier PDAs (PXA270 processor)
 | 
				
			||||||
@ -1722,7 +1722,7 @@ devices:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@itemize @minus
 | 
					@itemize @minus
 | 
				
			||||||
@item
 | 
					@item
 | 
				
			||||||
ARM926E or ARM1026E CPU
 | 
					ARM926E, ARM1026E or ARM946E CPU
 | 
				
			||||||
@item
 | 
					@item
 | 
				
			||||||
Two PL011 UARTs
 | 
					Two PL011 UARTs
 | 
				
			||||||
@item 
 | 
					@item 
 | 
				
			||||||
 | 
				
			|||||||
@ -83,10 +83,14 @@ typedef struct CPUARMState {
 | 
				
			|||||||
        uint32_t c0_cachetype;
 | 
					        uint32_t c0_cachetype;
 | 
				
			||||||
        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 c2; /* MMU translation table base.  */
 | 
					        uint32_t c2_base; /* MMU translation table base.  */
 | 
				
			||||||
        uint32_t c3; /* MMU domain access control register.  */
 | 
					        uint32_t c2_data; /* MPU data cachable bits.  */
 | 
				
			||||||
 | 
					        uint32_t c2_insn; /* MPU instruction cachable bits.  */
 | 
				
			||||||
 | 
					        uint32_t c3; /* MMU domain access control register
 | 
				
			||||||
 | 
					                        MPU write buffer control.  */
 | 
				
			||||||
        uint32_t c5_insn; /* Fault status registers.  */
 | 
					        uint32_t c5_insn; /* Fault status registers.  */
 | 
				
			||||||
        uint32_t c5_data;
 | 
					        uint32_t c5_data;
 | 
				
			||||||
 | 
					        uint32_t c6_region[8]; /* MPU base/size registers.  */
 | 
				
			||||||
        uint32_t c6_insn; /* Fault address registers.  */
 | 
					        uint32_t c6_insn; /* Fault address registers.  */
 | 
				
			||||||
        uint32_t c6_data;
 | 
					        uint32_t c6_data;
 | 
				
			||||||
        uint32_t c9_insn; /* Cache lockdown registers.  */
 | 
					        uint32_t c9_insn; /* Cache lockdown registers.  */
 | 
				
			||||||
@ -241,7 +245,8 @@ enum arm_features {
 | 
				
			|||||||
    ARM_FEATURE_VFP,
 | 
					    ARM_FEATURE_VFP,
 | 
				
			||||||
    ARM_FEATURE_AUXCR,  /* ARM1026 Auxiliary control register.  */
 | 
					    ARM_FEATURE_AUXCR,  /* ARM1026 Auxiliary control register.  */
 | 
				
			||||||
    ARM_FEATURE_XSCALE, /* Intel XScale extensions.  */
 | 
					    ARM_FEATURE_XSCALE, /* Intel XScale extensions.  */
 | 
				
			||||||
    ARM_FEATURE_IWMMXT  /* Intel iwMMXt extension.  */
 | 
					    ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension.  */
 | 
				
			||||||
 | 
					    ARM_FEATURE_MPU     /* Only has Memory Protection Unit, not full MMU.  */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int arm_feature(CPUARMState *env, int feature)
 | 
					static inline int arm_feature(CPUARMState *env, int feature)
 | 
				
			||||||
@ -258,6 +263,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define ARM_CPUID_ARM1026   0x4106a262
 | 
					#define ARM_CPUID_ARM1026   0x4106a262
 | 
				
			||||||
#define ARM_CPUID_ARM926    0x41069265
 | 
					#define ARM_CPUID_ARM926    0x41069265
 | 
				
			||||||
 | 
					#define ARM_CPUID_ARM946    0x41059461
 | 
				
			||||||
#define ARM_CPUID_PXA250    0x69052100
 | 
					#define ARM_CPUID_PXA250    0x69052100
 | 
				
			||||||
#define ARM_CPUID_PXA255    0x69052d00
 | 
					#define ARM_CPUID_PXA255    0x69052d00
 | 
				
			||||||
#define ARM_CPUID_PXA260    0x69052903
 | 
					#define ARM_CPUID_PXA260    0x69052903
 | 
				
			||||||
 | 
				
			|||||||
@ -19,6 +19,10 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
 | 
				
			|||||||
        env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
 | 
					        env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
 | 
				
			||||||
        env->cp15.c0_cachetype = 0x1dd20d2;
 | 
					        env->cp15.c0_cachetype = 0x1dd20d2;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					    case ARM_CPUID_ARM946:
 | 
				
			||||||
 | 
					        set_feature(env, ARM_FEATURE_MPU);
 | 
				
			||||||
 | 
					        env->cp15.c0_cachetype = 0x0f004006;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case ARM_CPUID_ARM1026:
 | 
					    case ARM_CPUID_ARM1026:
 | 
				
			||||||
        set_feature(env, ARM_FEATURE_VFP);
 | 
					        set_feature(env, ARM_FEATURE_VFP);
 | 
				
			||||||
        set_feature(env, ARM_FEATURE_AUXCR);
 | 
					        set_feature(env, ARM_FEATURE_AUXCR);
 | 
				
			||||||
@ -90,6 +94,7 @@ struct arm_cpu_t {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static const struct arm_cpu_t arm_cpu_names[] = {
 | 
					static const struct arm_cpu_t arm_cpu_names[] = {
 | 
				
			||||||
    { ARM_CPUID_ARM926, "arm926"},
 | 
					    { ARM_CPUID_ARM926, "arm926"},
 | 
				
			||||||
 | 
					    { ARM_CPUID_ARM946, "arm946"},
 | 
				
			||||||
    { ARM_CPUID_ARM1026, "arm1026"},
 | 
					    { ARM_CPUID_ARM1026, "arm1026"},
 | 
				
			||||||
    { ARM_CPUID_PXA250, "pxa250" },
 | 
					    { ARM_CPUID_PXA250, "pxa250" },
 | 
				
			||||||
    { ARM_CPUID_PXA255, "pxa255" },
 | 
					    { ARM_CPUID_PXA255, "pxa255" },
 | 
				
			||||||
@ -392,13 +397,67 @@ static int get_phys_addr(CPUState *env, uint32_t address, int access_type,
 | 
				
			|||||||
        address += env->cp15.c13_fcse;
 | 
					        address += env->cp15.c13_fcse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((env->cp15.c1_sys & 1) == 0) {
 | 
					    if ((env->cp15.c1_sys & 1) == 0) {
 | 
				
			||||||
        /* MMU diusabled.  */
 | 
					        /* MMU/MPU disabled.  */
 | 
				
			||||||
        *phys_ptr = address;
 | 
					        *phys_ptr = address;
 | 
				
			||||||
        *prot = PAGE_READ | PAGE_WRITE;
 | 
					        *prot = PAGE_READ | PAGE_WRITE;
 | 
				
			||||||
 | 
					    } else if (arm_feature(env, ARM_FEATURE_MPU)) {
 | 
				
			||||||
 | 
					        int n;
 | 
				
			||||||
 | 
					        uint32_t mask;
 | 
				
			||||||
 | 
					        uint32_t base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        *phys_ptr = address;
 | 
				
			||||||
 | 
					        for (n = 7; n >= 0; n--) {
 | 
				
			||||||
 | 
					            base = env->cp15.c6_region[n];
 | 
				
			||||||
 | 
					            if ((base & 1) == 0)
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            mask = 1 << ((base >> 1) & 0x1f);
 | 
				
			||||||
 | 
					            /* Keep this shift separate from the above to avoid an
 | 
				
			||||||
 | 
					               (undefined) << 32.  */
 | 
				
			||||||
 | 
					            mask = (mask << 1) - 1;
 | 
				
			||||||
 | 
					            if (((base ^ address) & ~mask) == 0)
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (n < 0)
 | 
				
			||||||
 | 
					            return 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (access_type == 2) {
 | 
				
			||||||
 | 
					            mask = env->cp15.c5_insn;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            mask = env->cp15.c5_data;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        mask = (mask >> (n * 4)) & 0xf;
 | 
				
			||||||
 | 
					        switch (mask) {
 | 
				
			||||||
 | 
					        case 0:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case 1:
 | 
				
			||||||
 | 
					            if (is_user)
 | 
				
			||||||
 | 
					              return 1;
 | 
				
			||||||
 | 
					            *prot = PAGE_READ | PAGE_WRITE;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case 2:
 | 
				
			||||||
 | 
					            *prot = PAGE_READ;
 | 
				
			||||||
 | 
					            if (!is_user)
 | 
				
			||||||
 | 
					                *prot |= PAGE_WRITE;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case 3:
 | 
				
			||||||
 | 
					            *prot = PAGE_READ | PAGE_WRITE;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case 5:
 | 
				
			||||||
 | 
					            if (is_user)
 | 
				
			||||||
 | 
					                return 1;
 | 
				
			||||||
 | 
					            *prot = PAGE_READ;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case 6:
 | 
				
			||||||
 | 
					            *prot = PAGE_READ;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            /* Bad permission.  */
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        /* Pagetable walk.  */
 | 
					        /* Pagetable walk.  */
 | 
				
			||||||
        /* Lookup l1 descriptor.  */
 | 
					        /* Lookup l1 descriptor.  */
 | 
				
			||||||
        table = (env->cp15.c2 & 0xffffc000) | ((address >> 18) & 0x3ffc);
 | 
					        table = (env->cp15.c2_base & 0xffffc000) | ((address >> 18) & 0x3ffc);
 | 
				
			||||||
        desc = ldl_phys(table);
 | 
					        desc = ldl_phys(table);
 | 
				
			||||||
        type = (desc & 3);
 | 
					        type = (desc & 3);
 | 
				
			||||||
        domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
 | 
					        domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
 | 
				
			||||||
@ -539,18 +598,50 @@ uint32_t helper_get_cp(CPUState *env, uint32_t insn)
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Return basic MPU access permission bits.  */
 | 
				
			||||||
 | 
					static uint32_t simple_mpu_ap_bits(uint32_t val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t ret;
 | 
				
			||||||
 | 
					    uint32_t mask;
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					    ret = 0;
 | 
				
			||||||
 | 
					    mask = 3;
 | 
				
			||||||
 | 
					    for (i = 0; i < 16; i += 2) {
 | 
				
			||||||
 | 
					        ret |= (val >> i) & mask;
 | 
				
			||||||
 | 
					        mask <<= 2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Pad basic MPU access permission bits to extended format.  */
 | 
				
			||||||
 | 
					static uint32_t extended_mpu_ap_bits(uint32_t val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t ret;
 | 
				
			||||||
 | 
					    uint32_t mask;
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					    ret = 0;
 | 
				
			||||||
 | 
					    mask = 3;
 | 
				
			||||||
 | 
					    for (i = 0; i < 16; i += 2) {
 | 
				
			||||||
 | 
					        ret |= (val & mask) << i;
 | 
				
			||||||
 | 
					        mask <<= 2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
 | 
					void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t op2;
 | 
					    uint32_t op2;
 | 
				
			||||||
 | 
					    uint32_t crm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    op2 = (insn >> 5) & 7;
 | 
					    op2 = (insn >> 5) & 7;
 | 
				
			||||||
 | 
					    crm = insn & 0xf;
 | 
				
			||||||
    switch ((insn >> 16) & 0xf) {
 | 
					    switch ((insn >> 16) & 0xf) {
 | 
				
			||||||
    case 0: /* ID codes.  */
 | 
					    case 0: /* ID codes.  */
 | 
				
			||||||
        goto bad_reg;
 | 
					        goto bad_reg;
 | 
				
			||||||
    case 1: /* System configuration.  */
 | 
					    case 1: /* System configuration.  */
 | 
				
			||||||
        switch (op2) {
 | 
					        switch (op2) {
 | 
				
			||||||
        case 0:
 | 
					        case 0:
 | 
				
			||||||
            if (!arm_feature(env, ARM_FEATURE_XSCALE) || (insn & 0xf) == 0)
 | 
					            if (!arm_feature(env, ARM_FEATURE_XSCALE) || crm == 0)
 | 
				
			||||||
                env->cp15.c1_sys = val;
 | 
					                env->cp15.c1_sys = val;
 | 
				
			||||||
            /* ??? Lots of these bits are not implemented.  */
 | 
					            /* ??? Lots of these bits are not implemented.  */
 | 
				
			||||||
            /* This may enable/disable the MMU, so do a TLB flush.  */
 | 
					            /* This may enable/disable the MMU, so do a TLB flush.  */
 | 
				
			||||||
@ -571,36 +662,69 @@ void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
 | 
				
			|||||||
            goto bad_reg;
 | 
					            goto bad_reg;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 2: /* MMU Page table control.  */
 | 
					    case 2: /* MMU Page table control / MPU cache control.  */
 | 
				
			||||||
        env->cp15.c2 = val;
 | 
					        if (arm_feature(env, ARM_FEATURE_MPU)) {
 | 
				
			||||||
 | 
					            switch (op2) {
 | 
				
			||||||
 | 
					            case 0:
 | 
				
			||||||
 | 
					                env->cp15.c2_data = val;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 1:
 | 
				
			||||||
 | 
					                env->cp15.c2_insn = val;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                goto bad_reg;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            env->cp15.c2_base = val;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 3: /* MMU Domain access control.  */
 | 
					    case 3: /* MMU Domain access control / MPU write buffer control.  */
 | 
				
			||||||
        env->cp15.c3 = val;
 | 
					        env->cp15.c3 = val;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 4: /* Reserved.  */
 | 
					    case 4: /* Reserved.  */
 | 
				
			||||||
        goto bad_reg;
 | 
					        goto bad_reg;
 | 
				
			||||||
    case 5: /* MMU Fault status.  */
 | 
					    case 5: /* MMU Fault status / MPU access permission.  */
 | 
				
			||||||
        switch (op2) {
 | 
					        switch (op2) {
 | 
				
			||||||
        case 0:
 | 
					        case 0:
 | 
				
			||||||
 | 
					            if (arm_feature(env, ARM_FEATURE_MPU))
 | 
				
			||||||
 | 
					                val = extended_mpu_ap_bits(val);
 | 
				
			||||||
            env->cp15.c5_data = val;
 | 
					            env->cp15.c5_data = val;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 1:
 | 
					        case 1:
 | 
				
			||||||
 | 
					            if (arm_feature(env, ARM_FEATURE_MPU))
 | 
				
			||||||
 | 
					                val = extended_mpu_ap_bits(val);
 | 
				
			||||||
 | 
					            env->cp15.c5_insn = val;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case 2:
 | 
				
			||||||
 | 
					            if (!arm_feature(env, ARM_FEATURE_MPU))
 | 
				
			||||||
 | 
					                goto bad_reg;
 | 
				
			||||||
 | 
					            env->cp15.c5_data = val;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case 3:
 | 
				
			||||||
 | 
					            if (!arm_feature(env, ARM_FEATURE_MPU))
 | 
				
			||||||
 | 
					                goto bad_reg;
 | 
				
			||||||
            env->cp15.c5_insn = val;
 | 
					            env->cp15.c5_insn = val;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            goto bad_reg;
 | 
					            goto bad_reg;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 6: /* MMU Fault address.  */
 | 
					    case 6: /* MMU Fault address / MPU base/size.  */
 | 
				
			||||||
        switch (op2) {
 | 
					        if (arm_feature(env, ARM_FEATURE_MPU)) {
 | 
				
			||||||
        case 0:
 | 
					            if (crm >= 8)
 | 
				
			||||||
            env->cp15.c6_data = val;
 | 
					                goto bad_reg;
 | 
				
			||||||
            break;
 | 
					            env->cp15.c6_region[crm] = val;
 | 
				
			||||||
        case 1:
 | 
					        } else {
 | 
				
			||||||
            env->cp15.c6_insn = val;
 | 
					            switch (op2) {
 | 
				
			||||||
            break;
 | 
					            case 0:
 | 
				
			||||||
        default:
 | 
					                env->cp15.c6_data = val;
 | 
				
			||||||
            goto bad_reg;
 | 
					                break;
 | 
				
			||||||
 | 
					            case 1:
 | 
				
			||||||
 | 
					                env->cp15.c6_insn = val;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                goto bad_reg;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 7: /* Cache control.  */
 | 
					    case 7: /* Cache control.  */
 | 
				
			||||||
@ -629,14 +753,23 @@ void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
 | 
				
			|||||||
            goto bad_reg;
 | 
					            goto bad_reg;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 9: /* Cache lockdown.  */
 | 
					    case 9:
 | 
				
			||||||
        switch (op2) {
 | 
					        switch (crm) {
 | 
				
			||||||
        case 0:
 | 
					        case 0: /* Cache lockdown.  */
 | 
				
			||||||
            env->cp15.c9_data = val;
 | 
					            switch (op2) {
 | 
				
			||||||
            break;
 | 
					            case 0:
 | 
				
			||||||
        case 1:
 | 
					                env->cp15.c9_data = val;
 | 
				
			||||||
            env->cp15.c9_insn = val;
 | 
					                break;
 | 
				
			||||||
 | 
					            case 1:
 | 
				
			||||||
 | 
					                env->cp15.c9_insn = val;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                goto bad_reg;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					        case 1: /* TCM memory region registers.  */
 | 
				
			||||||
 | 
					            /* Not implemented.  */
 | 
				
			||||||
 | 
					            goto bad_reg;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            goto bad_reg;
 | 
					            goto bad_reg;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -644,12 +777,13 @@ void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
 | 
				
			|||||||
    case 10: /* MMU TLB lockdown.  */
 | 
					    case 10: /* MMU TLB lockdown.  */
 | 
				
			||||||
        /* ??? TLB lockdown not implemented.  */
 | 
					        /* ??? TLB lockdown not implemented.  */
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 11: /* TCM DMA control.  */
 | 
					 | 
				
			||||||
    case 12: /* Reserved.  */
 | 
					    case 12: /* Reserved.  */
 | 
				
			||||||
        goto bad_reg;
 | 
					        goto bad_reg;
 | 
				
			||||||
    case 13: /* Process ID.  */
 | 
					    case 13: /* Process ID.  */
 | 
				
			||||||
        switch (op2) {
 | 
					        switch (op2) {
 | 
				
			||||||
        case 0:
 | 
					        case 0:
 | 
				
			||||||
 | 
					            if (!arm_feature(env, ARM_FEATURE_MPU))
 | 
				
			||||||
 | 
					                goto bad_reg;
 | 
				
			||||||
            /* Unlike real hardware the qemu TLB uses virtual addresses,
 | 
					            /* Unlike real hardware the qemu TLB uses virtual addresses,
 | 
				
			||||||
               not modified virtual addresses, so this causes a TLB flush.
 | 
					               not modified virtual addresses, so this causes a TLB flush.
 | 
				
			||||||
             */
 | 
					             */
 | 
				
			||||||
@ -659,7 +793,8 @@ void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 1:
 | 
					        case 1:
 | 
				
			||||||
            /* This changes the ASID, so do a TLB flush.  */
 | 
					            /* This changes the ASID, so do a TLB flush.  */
 | 
				
			||||||
            if (env->cp15.c13_context != val)
 | 
					            if (env->cp15.c13_context != val
 | 
				
			||||||
 | 
					                && !arm_feature(env, ARM_FEATURE_MPU))
 | 
				
			||||||
              tlb_flush(env, 0);
 | 
					              tlb_flush(env, 0);
 | 
				
			||||||
            env->cp15.c13_context = val;
 | 
					            env->cp15.c13_context = val;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@ -671,7 +806,7 @@ void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
 | 
				
			|||||||
        goto bad_reg;
 | 
					        goto bad_reg;
 | 
				
			||||||
    case 15: /* Implementation specific.  */
 | 
					    case 15: /* Implementation specific.  */
 | 
				
			||||||
        if (arm_feature(env, ARM_FEATURE_XSCALE)) {
 | 
					        if (arm_feature(env, ARM_FEATURE_XSCALE)) {
 | 
				
			||||||
            if (op2 == 0 && (insn & 0xf) == 1) {
 | 
					            if (op2 == 0 && crm == 1) {
 | 
				
			||||||
                /* Changes cp0 to cp13 behavior, so needs a TB flush.  */
 | 
					                /* Changes cp0 to cp13 behavior, so needs a TB flush.  */
 | 
				
			||||||
                tb_flush(env);
 | 
					                tb_flush(env);
 | 
				
			||||||
                env->cp15.c15_cpar = (val & 0x3fff) | 2;
 | 
					                env->cp15.c15_cpar = (val & 0x3fff) | 2;
 | 
				
			||||||
@ -717,31 +852,64 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
 | 
				
			|||||||
        default:
 | 
					        default:
 | 
				
			||||||
            goto bad_reg;
 | 
					            goto bad_reg;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    case 2: /* MMU Page table control.  */
 | 
					    case 2: /* MMU Page table control / MPU cache control.  */
 | 
				
			||||||
        return env->cp15.c2;
 | 
					        if (arm_feature(env, ARM_FEATURE_MPU)) {
 | 
				
			||||||
    case 3: /* MMU Domain access control.  */
 | 
					            switch (op2) {
 | 
				
			||||||
 | 
					            case 0:
 | 
				
			||||||
 | 
					                return env->cp15.c2_data;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 1:
 | 
				
			||||||
 | 
					                return env->cp15.c2_insn;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                goto bad_reg;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return env->cp15.c2_base;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    case 3: /* MMU Domain access control / MPU write buffer control.  */
 | 
				
			||||||
        return env->cp15.c3;
 | 
					        return env->cp15.c3;
 | 
				
			||||||
    case 4: /* Reserved.  */
 | 
					    case 4: /* Reserved.  */
 | 
				
			||||||
        goto bad_reg;
 | 
					        goto bad_reg;
 | 
				
			||||||
    case 5: /* MMU Fault status.  */
 | 
					    case 5: /* MMU Fault status / MPU access permission.  */
 | 
				
			||||||
        switch (op2) {
 | 
					        switch (op2) {
 | 
				
			||||||
        case 0:
 | 
					        case 0:
 | 
				
			||||||
 | 
					            if (arm_feature(env, ARM_FEATURE_MPU))
 | 
				
			||||||
 | 
					                return simple_mpu_ap_bits(env->cp15.c5_data);
 | 
				
			||||||
            return env->cp15.c5_data;
 | 
					            return env->cp15.c5_data;
 | 
				
			||||||
        case 1:
 | 
					        case 1:
 | 
				
			||||||
 | 
					            if (arm_feature(env, ARM_FEATURE_MPU))
 | 
				
			||||||
 | 
					                return simple_mpu_ap_bits(env->cp15.c5_data);
 | 
				
			||||||
 | 
					            return env->cp15.c5_insn;
 | 
				
			||||||
 | 
					        case 2:
 | 
				
			||||||
 | 
					            if (!arm_feature(env, ARM_FEATURE_MPU))
 | 
				
			||||||
 | 
					                goto bad_reg;
 | 
				
			||||||
 | 
					            return env->cp15.c5_data;
 | 
				
			||||||
 | 
					        case 3:
 | 
				
			||||||
 | 
					            if (!arm_feature(env, ARM_FEATURE_MPU))
 | 
				
			||||||
 | 
					                goto bad_reg;
 | 
				
			||||||
            return env->cp15.c5_insn;
 | 
					            return env->cp15.c5_insn;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            goto bad_reg;
 | 
					            goto bad_reg;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    case 6: /* MMU Fault address.  */
 | 
					    case 6: /* MMU Fault address / MPU base/size.  */
 | 
				
			||||||
        switch (op2) {
 | 
					        if (arm_feature(env, ARM_FEATURE_MPU)) {
 | 
				
			||||||
        case 0:
 | 
					            int n;
 | 
				
			||||||
            return env->cp15.c6_data;
 | 
					            n = (insn & 0xf);
 | 
				
			||||||
        case 1:
 | 
					            if (n >= 8)
 | 
				
			||||||
            /* Arm9 doesn't have an IFAR, but implementing it anyway shouldn't
 | 
					                goto bad_reg;
 | 
				
			||||||
               do any harm.  */
 | 
					            return env->cp15.c6_region[n];
 | 
				
			||||||
            return env->cp15.c6_insn;
 | 
					        } else {
 | 
				
			||||||
        default:
 | 
					            switch (op2) {
 | 
				
			||||||
            goto bad_reg;
 | 
					            case 0:
 | 
				
			||||||
 | 
					                return env->cp15.c6_data;
 | 
				
			||||||
 | 
					            case 1:
 | 
				
			||||||
 | 
					                /* Arm9 doesn't have an IFAR, but implementing it anyway
 | 
				
			||||||
 | 
					                   shouldn't do any harm.  */
 | 
				
			||||||
 | 
					                return env->cp15.c6_insn;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                goto bad_reg;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    case 7: /* Cache control.  */
 | 
					    case 7: /* Cache control.  */
 | 
				
			||||||
        /* ??? This is for test, clean and invaidate operations that set the
 | 
					        /* ??? This is for test, clean and invaidate operations that set the
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user