Commit fe1479c3ad177df09d465338d5421a5f3b857f91
1 parent
644ad806
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
Showing
4 changed files
with
94 additions
and
1 deletions
target-arm/cpu.h
@@ -151,6 +151,10 @@ typedef struct CPUARMState { | @@ -151,6 +151,10 @@ typedef struct CPUARMState { | ||
151 | void *opaque; | 151 | void *opaque; |
152 | } cp[15]; | 152 | } cp[15]; |
153 | 153 | ||
154 | + /* Thumb-2 EE state. */ | ||
155 | + uint32_t teecr; | ||
156 | + uint32_t teehbr; | ||
157 | + | ||
154 | /* Internal CPU feature flags. */ | 158 | /* Internal CPU feature flags. */ |
155 | uint32_t features; | 159 | uint32_t features; |
156 | 160 | ||
@@ -329,7 +333,8 @@ enum arm_features { | @@ -329,7 +333,8 @@ enum arm_features { | ||
329 | ARM_FEATURE_NEON, | 333 | ARM_FEATURE_NEON, |
330 | ARM_FEATURE_DIV, | 334 | ARM_FEATURE_DIV, |
331 | ARM_FEATURE_M, /* Microcontroller profile. */ | 335 | ARM_FEATURE_M, /* Microcontroller profile. */ |
332 | - ARM_FEATURE_OMAPCP /* OMAP specific CP15 ops handling. */ | 336 | + ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. */ |
337 | + ARM_FEATURE_THUMB2EE | ||
333 | }; | 338 | }; |
334 | 339 | ||
335 | static inline int arm_feature(CPUARMState *env, int feature) | 340 | static inline int arm_feature(CPUARMState *env, int feature) |
target-arm/helper.c
@@ -88,6 +88,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) | @@ -88,6 +88,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) | ||
88 | set_feature(env, ARM_FEATURE_VFP); | 88 | set_feature(env, ARM_FEATURE_VFP); |
89 | set_feature(env, ARM_FEATURE_VFP3); | 89 | set_feature(env, ARM_FEATURE_VFP3); |
90 | set_feature(env, ARM_FEATURE_NEON); | 90 | set_feature(env, ARM_FEATURE_NEON); |
91 | + set_feature(env, ARM_FEATURE_THUMB2EE); | ||
91 | env->vfp.xregs[ARM_VFP_FPSID] = 0x410330c0; | 92 | env->vfp.xregs[ARM_VFP_FPSID] = 0x410330c0; |
92 | env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222; | 93 | env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222; |
93 | env->vfp.xregs[ARM_VFP_MVFR1] = 0x00011100; | 94 | env->vfp.xregs[ARM_VFP_MVFR1] = 0x00011100; |
@@ -110,6 +111,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) | @@ -110,6 +111,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) | ||
110 | set_feature(env, ARM_FEATURE_VFP); | 111 | set_feature(env, ARM_FEATURE_VFP); |
111 | set_feature(env, ARM_FEATURE_VFP3); | 112 | set_feature(env, ARM_FEATURE_VFP3); |
112 | set_feature(env, ARM_FEATURE_NEON); | 113 | set_feature(env, ARM_FEATURE_NEON); |
114 | + set_feature(env, ARM_FEATURE_THUMB2EE); | ||
113 | set_feature(env, ARM_FEATURE_DIV); | 115 | set_feature(env, ARM_FEATURE_DIV); |
114 | break; | 116 | break; |
115 | case ARM_CPUID_TI915T: | 117 | case ARM_CPUID_TI915T: |
@@ -2595,3 +2597,12 @@ uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env) | @@ -2595,3 +2597,12 @@ uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env) | ||
2595 | tmp = float32_scalbn(tmp, 31, s); | 2597 | tmp = float32_scalbn(tmp, 31, s); |
2596 | return float32_to_int32(tmp, s); | 2598 | return float32_to_int32(tmp, s); |
2597 | } | 2599 | } |
2600 | + | ||
2601 | +void HELPER(set_teecr)(CPUState *env, uint32_t val) | ||
2602 | +{ | ||
2603 | + val &= 1; | ||
2604 | + if (env->teecr != val) { | ||
2605 | + env->teecr = val; | ||
2606 | + tb_flush(env); | ||
2607 | + } | ||
2608 | +} |
target-arm/helpers.h
@@ -453,4 +453,6 @@ DEF_HELPER_3(iwmmxt_muladdsl, i64, i64, i32, i32) | @@ -453,4 +453,6 @@ DEF_HELPER_3(iwmmxt_muladdsl, i64, i64, i32, i32) | ||
453 | DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32) | 453 | DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32) |
454 | DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32) | 454 | DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32) |
455 | 455 | ||
456 | +DEF_HELPER_2(set_teecr, void, env, i32) | ||
457 | + | ||
456 | #include "def-helper.h" | 458 | #include "def-helper.h" |
target-arm/translate.c
@@ -5536,6 +5536,71 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -5536,6 +5536,71 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
5536 | return 0; | 5536 | return 0; |
5537 | } | 5537 | } |
5538 | 5538 | ||
5539 | +static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn) | ||
5540 | +{ | ||
5541 | + int crn = (insn >> 16) & 0xf; | ||
5542 | + int crm = insn & 0xf; | ||
5543 | + int op1 = (insn >> 21) & 7; | ||
5544 | + int op2 = (insn >> 5) & 7; | ||
5545 | + int rt = (insn >> 12) & 0xf; | ||
5546 | + TCGv tmp; | ||
5547 | + | ||
5548 | + if (arm_feature(env, ARM_FEATURE_THUMB2EE)) { | ||
5549 | + if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) { | ||
5550 | + /* TEECR */ | ||
5551 | + if (IS_USER(s)) | ||
5552 | + return 1; | ||
5553 | + tmp = load_cpu_field(teecr); | ||
5554 | + store_reg(s, rt, tmp); | ||
5555 | + return 0; | ||
5556 | + } | ||
5557 | + if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) { | ||
5558 | + /* TEEHBR */ | ||
5559 | + if (IS_USER(s) && (env->teecr & 1)) | ||
5560 | + return 1; | ||
5561 | + tmp = load_cpu_field(teehbr); | ||
5562 | + store_reg(s, rt, tmp); | ||
5563 | + return 0; | ||
5564 | + } | ||
5565 | + } | ||
5566 | + fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n", | ||
5567 | + op1, crn, crm, op2); | ||
5568 | + return 1; | ||
5569 | +} | ||
5570 | + | ||
5571 | +static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn) | ||
5572 | +{ | ||
5573 | + int crn = (insn >> 16) & 0xf; | ||
5574 | + int crm = insn & 0xf; | ||
5575 | + int op1 = (insn >> 21) & 7; | ||
5576 | + int op2 = (insn >> 5) & 7; | ||
5577 | + int rt = (insn >> 12) & 0xf; | ||
5578 | + TCGv tmp; | ||
5579 | + | ||
5580 | + if (arm_feature(env, ARM_FEATURE_THUMB2EE)) { | ||
5581 | + if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) { | ||
5582 | + /* TEECR */ | ||
5583 | + if (IS_USER(s)) | ||
5584 | + return 1; | ||
5585 | + tmp = load_reg(s, rt); | ||
5586 | + gen_helper_set_teecr(cpu_env, tmp); | ||
5587 | + dead_tmp(tmp); | ||
5588 | + return 0; | ||
5589 | + } | ||
5590 | + if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) { | ||
5591 | + /* TEEHBR */ | ||
5592 | + if (IS_USER(s) && (env->teecr & 1)) | ||
5593 | + return 1; | ||
5594 | + tmp = load_reg(s, rt); | ||
5595 | + store_cpu_field(tmp, teehbr); | ||
5596 | + return 0; | ||
5597 | + } | ||
5598 | + } | ||
5599 | + fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n", | ||
5600 | + op1, crn, crm, op2); | ||
5601 | + return 1; | ||
5602 | +} | ||
5603 | + | ||
5539 | static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn) | 5604 | static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn) |
5540 | { | 5605 | { |
5541 | int cpnum; | 5606 | int cpnum; |
@@ -5557,9 +5622,19 @@ static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -5557,9 +5622,19 @@ static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
5557 | case 10: | 5622 | case 10: |
5558 | case 11: | 5623 | case 11: |
5559 | return disas_vfp_insn (env, s, insn); | 5624 | return disas_vfp_insn (env, s, insn); |
5625 | + case 14: | ||
5626 | + /* Coprocessors 7-15 are architecturally reserved by ARM. | ||
5627 | + Unfortunately Intel decided to ignore this. */ | ||
5628 | + if (arm_feature(env, ARM_FEATURE_XSCALE)) | ||
5629 | + goto board; | ||
5630 | + if (insn & (1 << 20)) | ||
5631 | + return disas_cp14_read(env, s, insn); | ||
5632 | + else | ||
5633 | + return disas_cp14_write(env, s, insn); | ||
5560 | case 15: | 5634 | case 15: |
5561 | return disas_cp15_insn (env, s, insn); | 5635 | return disas_cp15_insn (env, s, insn); |
5562 | default: | 5636 | default: |
5637 | + board: | ||
5563 | /* Unknown coprocessor. See if the board has hooked it. */ | 5638 | /* Unknown coprocessor. See if the board has hooked it. */ |
5564 | return disas_cp_insn (env, s, insn); | 5639 | return disas_cp_insn (env, s, insn); |
5565 | } | 5640 | } |