target-mips: add CP0.PageGrain.ELPA support
CP0.PageGrain.ELPA enables support for large physical addresses. This field is encoded as follows: 0: Large physical address support is disabled. 1: Large physical address support is enabled. If this bit is a 1, the following changes occur to coprocessor 0 registers: - The PFNX field of the EntryLo0 and EntryLo1 registers is writable and concatenated with the PFN field to form the full page frame number. - Access to optional COP0 registers with PA extension, LLAddr, TagLo is defined. P5600 can operate in 32-bit or 40-bit Physical Address Mode. Therefore if XPA is disabled (CP0.PageGrain.ELPA = 0) then assume 32-bit Address Mode. In MIPS64 assume 36 as default PABITS (when CP0.PageGrain.ELPA = 0). env->PABITS value is constant and indicates maximum PABITS available on a core, whereas env->PAMask is calculated from env->PABITS and is also affected by CP0.PageGrain.ELPA. Signed-off-by: Leon Alrae <leon.alrae@imgtec.com> Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
		
							parent
							
								
									cd0d45c401
								
							
						
					
					
						commit
						e117f52636
					
				@ -224,8 +224,14 @@ struct CPUMIPSState {
 | 
			
		||||
 | 
			
		||||
    uint32_t SEGBITS;
 | 
			
		||||
    uint32_t PABITS;
 | 
			
		||||
#if defined(TARGET_MIPS64)
 | 
			
		||||
# define PABITS_BASE 36
 | 
			
		||||
#else
 | 
			
		||||
# define PABITS_BASE 32
 | 
			
		||||
#endif
 | 
			
		||||
    target_ulong SEGMask;
 | 
			
		||||
    uint64_t PAMask;
 | 
			
		||||
#define PAMASK_BASE ((1ULL << PABITS_BASE) - 1)
 | 
			
		||||
 | 
			
		||||
    int32_t msair;
 | 
			
		||||
#define MSAIR_ProcID    8
 | 
			
		||||
@ -289,6 +295,7 @@ struct CPUMIPSState {
 | 
			
		||||
    int32_t CP0_PageGrain;
 | 
			
		||||
#define CP0PG_RIE 31
 | 
			
		||||
#define CP0PG_XIE 30
 | 
			
		||||
#define CP0PG_ELPA 29
 | 
			
		||||
#define CP0PG_IEC 27
 | 
			
		||||
    int32_t CP0_Wired;
 | 
			
		||||
    int32_t CP0_SRSConf0_rw_bitmask;
 | 
			
		||||
@ -518,7 +525,7 @@ struct CPUMIPSState {
 | 
			
		||||
#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
 | 
			
		||||
    uint32_t hflags;    /* CPU State */
 | 
			
		||||
    /* TMASK defines different execution modes */
 | 
			
		||||
#define MIPS_HFLAG_TMASK  0x35807FF
 | 
			
		||||
#define MIPS_HFLAG_TMASK  0x75807FF
 | 
			
		||||
#define MIPS_HFLAG_MODE   0x00007 /* execution modes                    */
 | 
			
		||||
    /* The KSU flags must be the lowest bits in hflags. The flag order
 | 
			
		||||
       must be the same as defined for CP0 Status. This allows to use
 | 
			
		||||
@ -566,6 +573,7 @@ struct CPUMIPSState {
 | 
			
		||||
#define MIPS_HFLAG_FBNSLOT 0x800000 /* Forbidden slot                   */
 | 
			
		||||
#define MIPS_HFLAG_MSA   0x1000000
 | 
			
		||||
#define MIPS_HFLAG_FRE   0x2000000 /* FRE enabled */
 | 
			
		||||
#define MIPS_HFLAG_ELPA  0x4000000
 | 
			
		||||
    target_ulong btarget;        /* Jump / branch target               */
 | 
			
		||||
    target_ulong bcond;          /* Branch condition (if needed)       */
 | 
			
		||||
 | 
			
		||||
@ -801,6 +809,15 @@ static inline void restore_msa_fp_status(CPUMIPSState *env)
 | 
			
		||||
    set_flush_inputs_to_zero(flush_to_zero, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void restore_pamask(CPUMIPSState *env)
 | 
			
		||||
{
 | 
			
		||||
    if (env->hflags & MIPS_HFLAG_ELPA) {
 | 
			
		||||
        env->PAMask = (1ULL << env->PABITS) - 1;
 | 
			
		||||
    } else {
 | 
			
		||||
        env->PAMask = PAMASK_BASE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
 | 
			
		||||
                                        target_ulong *cs_base, int *flags)
 | 
			
		||||
{
 | 
			
		||||
@ -848,7 +865,8 @@ static inline void compute_hflags(CPUMIPSState *env)
 | 
			
		||||
    env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
 | 
			
		||||
                     MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
 | 
			
		||||
                     MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 |
 | 
			
		||||
                     MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE);
 | 
			
		||||
                     MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE |
 | 
			
		||||
                     MIPS_HFLAG_ELPA);
 | 
			
		||||
    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
 | 
			
		||||
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
 | 
			
		||||
        !(env->hflags & MIPS_HFLAG_DM)) {
 | 
			
		||||
@ -934,6 +952,11 @@ static inline void compute_hflags(CPUMIPSState *env)
 | 
			
		||||
            env->hflags |= MIPS_HFLAG_FRE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (env->CP0_Config3 & (1 << CP0C3_LPA)) {
 | 
			
		||||
        if (env->CP0_PageGrain & (1 << CP0PG_ELPA)) {
 | 
			
		||||
            env->hflags |= MIPS_HFLAG_ELPA;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef CONFIG_USER_ONLY
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,7 @@ static int cpu_post_load(void *opaque, int version_id)
 | 
			
		||||
    restore_fp_status(env);
 | 
			
		||||
    restore_msa_fp_status(env);
 | 
			
		||||
    compute_hflags(env);
 | 
			
		||||
    restore_pamask(env);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -10,11 +10,11 @@
 | 
			
		||||
 | 
			
		||||
#if defined(TARGET_MIPS64)
 | 
			
		||||
#define TARGET_LONG_BITS 64
 | 
			
		||||
#define TARGET_PHYS_ADDR_SPACE_BITS 36
 | 
			
		||||
#define TARGET_PHYS_ADDR_SPACE_BITS 48
 | 
			
		||||
#define TARGET_VIRT_ADDR_SPACE_BITS 42
 | 
			
		||||
#else
 | 
			
		||||
#define TARGET_LONG_BITS 32
 | 
			
		||||
#define TARGET_PHYS_ADDR_SPACE_BITS 36
 | 
			
		||||
#define TARGET_PHYS_ADDR_SPACE_BITS 40
 | 
			
		||||
#define TARGET_VIRT_ADDR_SPACE_BITS 32
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1068,19 +1068,23 @@ void helper_mtc0_vpeopt(CPUMIPSState *env, target_ulong arg1)
 | 
			
		||||
    env->CP0_VPEOpt = arg1 & 0x0000ffff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MTC0_ENTRYLO_MASK(env) ((env->PAMask >> 6) & 0x3FFFFFFF)
 | 
			
		||||
 | 
			
		||||
void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1)
 | 
			
		||||
{
 | 
			
		||||
    /* Large physaddr (PABITS) not implemented */
 | 
			
		||||
    /* 1k pages not implemented */
 | 
			
		||||
    target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
 | 
			
		||||
    env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI - 30));
 | 
			
		||||
    env->CP0_EntryLo0 = (arg1 & MTC0_ENTRYLO_MASK(env))
 | 
			
		||||
                        | (rxi << (CP0EnLo_XI - 30));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(TARGET_MIPS64)
 | 
			
		||||
#define DMTC0_ENTRYLO_MASK(env) (env->PAMask >> 6)
 | 
			
		||||
 | 
			
		||||
void helper_dmtc0_entrylo0(CPUMIPSState *env, uint64_t arg1)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
 | 
			
		||||
    env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | rxi;
 | 
			
		||||
    env->CP0_EntryLo0 = (arg1 & DMTC0_ENTRYLO_MASK(env)) | rxi;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -1246,17 +1250,17 @@ void helper_mttc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
 | 
			
		||||
 | 
			
		||||
void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1)
 | 
			
		||||
{
 | 
			
		||||
    /* Large physaddr (PABITS) not implemented */
 | 
			
		||||
    /* 1k pages not implemented */
 | 
			
		||||
    target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
 | 
			
		||||
    env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI - 30));
 | 
			
		||||
    env->CP0_EntryLo1 = (arg1 & MTC0_ENTRYLO_MASK(env))
 | 
			
		||||
                        | (rxi << (CP0EnLo_XI - 30));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(TARGET_MIPS64)
 | 
			
		||||
void helper_dmtc0_entrylo1(CPUMIPSState *env, uint64_t arg1)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
 | 
			
		||||
    env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | rxi;
 | 
			
		||||
    env->CP0_EntryLo1 = (arg1 & DMTC0_ENTRYLO_MASK(env)) | rxi;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -1279,10 +1283,11 @@ void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
 | 
			
		||||
void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
 | 
			
		||||
{
 | 
			
		||||
    /* SmartMIPS not implemented */
 | 
			
		||||
    /* Large physaddr (PABITS) not implemented */
 | 
			
		||||
    /* 1k pages not implemented */
 | 
			
		||||
    env->CP0_PageGrain = (arg1 & env->CP0_PageGrain_rw_bitmask) |
 | 
			
		||||
                         (env->CP0_PageGrain & ~env->CP0_PageGrain_rw_bitmask);
 | 
			
		||||
    compute_hflags(env);
 | 
			
		||||
    restore_pamask(env);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
 | 
			
		||||
 | 
			
		||||
@ -5699,6 +5699,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
 | 
			
		||||
            check_insn(ctx, ISA_MIPS32R2);
 | 
			
		||||
            gen_helper_mtc0_pagegrain(cpu_env, arg);
 | 
			
		||||
            rn = "PageGrain";
 | 
			
		||||
            ctx->bstate = BS_STOP;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            goto cp0_unimplemented;
 | 
			
		||||
@ -19578,7 +19579,6 @@ void cpu_state_reset(CPUMIPSState *env)
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    env->PABITS = env->cpu_model->PABITS;
 | 
			
		||||
    env->PAMask = (1ULL << env->cpu_model->PABITS) - 1;
 | 
			
		||||
    env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
 | 
			
		||||
    env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
 | 
			
		||||
    env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
 | 
			
		||||
@ -19699,6 +19699,7 @@ void cpu_state_reset(CPUMIPSState *env)
 | 
			
		||||
    compute_hflags(env);
 | 
			
		||||
    restore_rounding_mode(env);
 | 
			
		||||
    restore_flush_mode(env);
 | 
			
		||||
    restore_pamask(env);
 | 
			
		||||
    cs->exception_index = EXCP_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user