Implement (very) basic Thumb2-EE support. This doesn't actually implement
EE state, just the associated system coprocessor registers. It is sufficient to keep OS setup and context switching code happy. Signed-off-by: Paul Brook <paul@codesourcery.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6104 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
644ad8066d
commit
fe1479c3ad
@ -151,6 +151,10 @@ typedef struct CPUARMState {
|
||||
void *opaque;
|
||||
} cp[15];
|
||||
|
||||
/* Thumb-2 EE state. */
|
||||
uint32_t teecr;
|
||||
uint32_t teehbr;
|
||||
|
||||
/* Internal CPU feature flags. */
|
||||
uint32_t features;
|
||||
|
||||
@ -329,7 +333,8 @@ enum arm_features {
|
||||
ARM_FEATURE_NEON,
|
||||
ARM_FEATURE_DIV,
|
||||
ARM_FEATURE_M, /* Microcontroller profile. */
|
||||
ARM_FEATURE_OMAPCP /* OMAP specific CP15 ops handling. */
|
||||
ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. */
|
||||
ARM_FEATURE_THUMB2EE
|
||||
};
|
||||
|
||||
static inline int arm_feature(CPUARMState *env, int feature)
|
||||
|
@ -88,6 +88,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
|
||||
set_feature(env, ARM_FEATURE_VFP);
|
||||
set_feature(env, ARM_FEATURE_VFP3);
|
||||
set_feature(env, ARM_FEATURE_NEON);
|
||||
set_feature(env, ARM_FEATURE_THUMB2EE);
|
||||
env->vfp.xregs[ARM_VFP_FPSID] = 0x410330c0;
|
||||
env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222;
|
||||
env->vfp.xregs[ARM_VFP_MVFR1] = 0x00011100;
|
||||
@ -110,6 +111,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
|
||||
set_feature(env, ARM_FEATURE_VFP);
|
||||
set_feature(env, ARM_FEATURE_VFP3);
|
||||
set_feature(env, ARM_FEATURE_NEON);
|
||||
set_feature(env, ARM_FEATURE_THUMB2EE);
|
||||
set_feature(env, ARM_FEATURE_DIV);
|
||||
break;
|
||||
case ARM_CPUID_TI915T:
|
||||
@ -2595,3 +2597,12 @@ uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env)
|
||||
tmp = float32_scalbn(tmp, 31, s);
|
||||
return float32_to_int32(tmp, s);
|
||||
}
|
||||
|
||||
void HELPER(set_teecr)(CPUState *env, uint32_t val)
|
||||
{
|
||||
val &= 1;
|
||||
if (env->teecr != val) {
|
||||
env->teecr = val;
|
||||
tb_flush(env);
|
||||
}
|
||||
}
|
||||
|
@ -453,4 +453,6 @@ DEF_HELPER_3(iwmmxt_muladdsl, i64, i64, i32, i32)
|
||||
DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32)
|
||||
DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32)
|
||||
|
||||
DEF_HELPER_2(set_teecr, void, env, i32)
|
||||
|
||||
#include "def-helper.h"
|
||||
|
@ -5536,6 +5536,71 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int disas_cp14_read(CPUState * 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_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;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
|
||||
op1, crn, crm, op2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int disas_cp14_write(CPUState * 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);
|
||||
dead_tmp(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;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
|
||||
op1, crn, crm, op2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
|
||||
{
|
||||
int cpnum;
|
||||
@ -5557,9 +5622,19 @@ static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
|
||||
case 10:
|
||||
case 11:
|
||||
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:
|
||||
board:
|
||||
/* Unknown coprocessor. See if the board has hooked it. */
|
||||
return disas_cp_insn (env, s, insn);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user