diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2011-05-03 20:16:18 -0300 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2011-05-03 20:16:18 -0300 |
commit | 28262112181f27f302b5186f0df6428df6b513e7 (patch) | |
tree | c1a12fd82d869eb8c57da3e3314abb3437f3a8a1 /target-arm | |
parent | 70757dcaa40e14978bf287084d8fab9efb815a2d (diff) | |
parent | 4eb1a092e5810298b2baf4b12d9f52ea0d52322f (diff) |
* upstream-merge: (197 commits)
NBD: Avoid leaking a couple of strings when the NBD device is closed
qemu-progress.c: printf isn't signal safe
ide/atapi: fix set but unused
atapi: Explain why we need a 'media not present' state
atapi: Move comment to proper place
qemu-img resize: Fix option parsing
lm32: add Milkymist Minimac2 support
milkymist-sysctl: fix timers
milkymist-vgafb: fix console resizing
lm32: fix exception handling
kvm: use qemu_free consistently
kvm: Install specialized interrupt handler
fix crash in migration, 32-bit userspace on 64-bit host
Redirect cpu_interrupt to callback handler
Break up user and system cpu_interrupt implementations
kvm: create kvmclock when one of the flags are present
kvm: add kvmclock to its second bit
x86: Allow multiple cpu feature matches of lookup_feature
kvm: use kernel-provided para_features instead of statically coming up with new capabilities
Don't zero out buffer in sched_getaffinity
...
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'target-arm')
-rw-r--r-- | target-arm/cpu.h | 3 | ||||
-rw-r--r-- | target-arm/helper.c | 22 | ||||
-rw-r--r-- | target-arm/helper.h (renamed from target-arm/helpers.h) | 0 | ||||
-rw-r--r-- | target-arm/iwmmxt_helper.c | 2 | ||||
-rw-r--r-- | target-arm/neon_helper.c | 2 | ||||
-rw-r--r-- | target-arm/op_helper.c | 4 | ||||
-rw-r--r-- | target-arm/translate.c | 89 |
7 files changed, 105 insertions, 17 deletions
diff --git a/target-arm/cpu.h b/target-arm/cpu.h index e247a7ade..d5af64465 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -363,6 +363,7 @@ enum arm_features { ARM_FEATURE_V7MP, /* v7 Multiprocessing Extensions */ ARM_FEATURE_V4T, ARM_FEATURE_V5, + ARM_FEATURE_STRONGARM, }; static inline int arm_feature(CPUARMState *env, int feature) @@ -393,6 +394,8 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum, #define ARM_CPUID_ARM946 0x41059461 #define ARM_CPUID_TI915T 0x54029152 #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 diff --git a/target-arm/helper.c b/target-arm/helper.c index 9172fc727..62ae72ec2 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -5,7 +5,7 @@ #include "cpu.h" #include "exec-all.h" #include "gdbstub.h" -#include "helpers.h" +#include "helper.h" #include "qemu-common.h" #include "host-utils.h" #if !defined(CONFIG_USER_ONLY) @@ -214,6 +214,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) env->cp15.c0_cachetype = 0xd172172; env->cp15.c1_sys = 0x00000078; break; + case ARM_CPUID_SA1100: + case ARM_CPUID_SA1110: + set_feature(env, ARM_FEATURE_STRONGARM); + env->cp15.c1_sys = 0x00000070; + break; default: cpu_abort(env, "Bad CPU ID: %x\n", id); break; @@ -378,6 +383,8 @@ static const struct arm_cpu_t arm_cpu_names[] = { { ARM_CPUID_CORTEXA9, "cortex-a9"}, { ARM_CPUID_TI925T, "ti925t" }, { ARM_CPUID_PXA250, "pxa250" }, + { ARM_CPUID_SA1100, "sa1100" }, + { ARM_CPUID_SA1110, "sa1110" }, { ARM_CPUID_PXA255, "pxa255" }, { ARM_CPUID_PXA260, "pxa260" }, { ARM_CPUID_PXA261, "pxa261" }, @@ -1378,7 +1385,7 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val) /* This may enable/disable the MMU, so do a TLB flush. */ tlb_flush(env, 1); break; - case 1: /* Auxiliary cotrol register. */ + case 1: /* Auxiliary control register. */ if (arm_feature(env, ARM_FEATURE_XSCALE)) { env->cp15.c1_xscaleauxcr = val; break; @@ -1553,6 +1560,8 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val) case 9: if (arm_feature(env, ARM_FEATURE_OMAPCP)) break; + if (arm_feature(env, ARM_FEATURE_STRONGARM)) + break; /* Ignore ReadBuffer access */ switch (crm) { case 0: /* Cache lockdown. */ switch (op1) { @@ -2542,6 +2551,7 @@ float64 VFP_HELPER(sito, d)(uint32_t x, CPUState *env) uint32_t VFP_HELPER(toui, s)(float32 x, CPUState *env) { if (float32_is_any_nan(x)) { + float_raise(float_flag_invalid, &env->vfp.fp_status); return 0; } return float32_to_uint32(x, &env->vfp.fp_status); @@ -2550,6 +2560,7 @@ uint32_t VFP_HELPER(toui, s)(float32 x, CPUState *env) uint32_t VFP_HELPER(toui, d)(float64 x, CPUState *env) { if (float64_is_any_nan(x)) { + float_raise(float_flag_invalid, &env->vfp.fp_status); return 0; } return float64_to_uint32(x, &env->vfp.fp_status); @@ -2558,6 +2569,7 @@ uint32_t VFP_HELPER(toui, d)(float64 x, CPUState *env) uint32_t VFP_HELPER(tosi, s)(float32 x, CPUState *env) { if (float32_is_any_nan(x)) { + float_raise(float_flag_invalid, &env->vfp.fp_status); return 0; } return float32_to_int32(x, &env->vfp.fp_status); @@ -2566,6 +2578,7 @@ uint32_t VFP_HELPER(tosi, s)(float32 x, CPUState *env) uint32_t VFP_HELPER(tosi, d)(float64 x, CPUState *env) { if (float64_is_any_nan(x)) { + float_raise(float_flag_invalid, &env->vfp.fp_status); return 0; } return float64_to_int32(x, &env->vfp.fp_status); @@ -2574,6 +2587,7 @@ uint32_t VFP_HELPER(tosi, d)(float64 x, CPUState *env) uint32_t VFP_HELPER(touiz, s)(float32 x, CPUState *env) { if (float32_is_any_nan(x)) { + float_raise(float_flag_invalid, &env->vfp.fp_status); return 0; } return float32_to_uint32_round_to_zero(x, &env->vfp.fp_status); @@ -2582,6 +2596,7 @@ uint32_t VFP_HELPER(touiz, s)(float32 x, CPUState *env) uint32_t VFP_HELPER(touiz, d)(float64 x, CPUState *env) { if (float64_is_any_nan(x)) { + float_raise(float_flag_invalid, &env->vfp.fp_status); return 0; } return float64_to_uint32_round_to_zero(x, &env->vfp.fp_status); @@ -2590,6 +2605,7 @@ uint32_t VFP_HELPER(touiz, d)(float64 x, CPUState *env) uint32_t VFP_HELPER(tosiz, s)(float32 x, CPUState *env) { if (float32_is_any_nan(x)) { + float_raise(float_flag_invalid, &env->vfp.fp_status); return 0; } return float32_to_int32_round_to_zero(x, &env->vfp.fp_status); @@ -2598,6 +2614,7 @@ uint32_t VFP_HELPER(tosiz, s)(float32 x, CPUState *env) uint32_t VFP_HELPER(tosiz, d)(float64 x, CPUState *env) { if (float64_is_any_nan(x)) { + float_raise(float_flag_invalid, &env->vfp.fp_status); return 0; } return float64_to_int32_round_to_zero(x, &env->vfp.fp_status); @@ -2636,6 +2653,7 @@ uint##fsz##_t VFP_HELPER(to##name, p)(float##fsz x, uint32_t shift, \ { \ float##fsz tmp; \ if (float##fsz##_is_any_nan(x)) { \ + float_raise(float_flag_invalid, &env->vfp.fp_status); \ return 0; \ } \ tmp = float##fsz##_scalbn(x, shift, &env->vfp.fp_status); \ diff --git a/target-arm/helpers.h b/target-arm/helper.h index ae701e845..ae701e845 100644 --- a/target-arm/helpers.h +++ b/target-arm/helper.h diff --git a/target-arm/iwmmxt_helper.c b/target-arm/iwmmxt_helper.c index 3941f1fd8..ebe6eb9fa 100644 --- a/target-arm/iwmmxt_helper.c +++ b/target-arm/iwmmxt_helper.c @@ -24,7 +24,7 @@ #include "cpu.h" #include "exec.h" -#include "helpers.h" +#include "helper.h" /* iwMMXt macros extracted from GNU gdb. */ diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c index 7df925ad3..f5b173aa7 100644 --- a/target-arm/neon_helper.c +++ b/target-arm/neon_helper.c @@ -11,7 +11,7 @@ #include "cpu.h" #include "exec.h" -#include "helpers.h" +#include "helper.h" #define SIGNBIT (uint32_t)0x80000000 #define SIGNBIT64 ((uint64_t)1 << 63) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 3de261034..8334fbcf6 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -17,7 +17,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include "exec.h" -#include "helpers.h" +#include "helper.h" #define SIGNBIT (uint32_t)0x80000000 #define SIGNBIT64 ((uint64_t)1 << 63) @@ -90,7 +90,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) if (tb) { /* the PC is inside the translated code. It means that we have a virtual CPU fault */ - cpu_restore_state(tb, env, pc, NULL); + cpu_restore_state(tb, env, pc); } } raise_exception(env->exception_index); diff --git a/target-arm/translate.c b/target-arm/translate.c index 6190028d0..a1af436e3 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -30,9 +30,9 @@ #include "tcg-op.h" #include "qemu-log.h" -#include "helpers.h" +#include "helper.h" #define GEN_HELPER 1 -#include "helpers.h" +#include "helper.h" #define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T) #define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5) @@ -129,7 +129,7 @@ void arm_translate_init(void) #endif #define GEN_HELPER 2 -#include "helpers.h" +#include "helper.h" } static inline TCGv load_cpu_offset(int offset) @@ -3830,6 +3830,21 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) size = (insn >> 6) & 3; if (op > 10) return 1; + /* Catch UNDEF cases for bad values of align field */ + switch (op & 0xc) { + case 4: + if (((insn >> 5) & 1) == 1) { + return 1; + } + break; + case 8: + if (((insn >> 4) & 3) == 3) { + return 1; + } + break; + default: + break; + } nregs = neon_ls_element_type[op].nregs; interleave = neon_ls_element_type[op].interleave; spacing = neon_ls_element_type[op].spacing; @@ -3975,6 +3990,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) stride = (1 << size) * nregs; } else { /* Single element. */ + int idx = (insn >> 4) & 0xf; pass = (insn >> 7) & 1; switch (size) { case 0: @@ -3993,6 +4009,39 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) abort(); } nregs = ((insn >> 8) & 3) + 1; + /* Catch the UNDEF cases. This is unavoidably a bit messy. */ + switch (nregs) { + case 1: + if (((idx & (1 << size)) != 0) || + (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) { + return 1; + } + break; + case 3: + if ((idx & 1) != 0) { + return 1; + } + /* fall through */ + case 2: + if (size == 2 && (idx & 2) != 0) { + return 1; + } + break; + case 4: + if ((size == 2) && ((idx & 3) == 3)) { + return 1; + } + break; + default: + abort(); + } + if ((rd + stride * (nregs - 1)) > 31) { + /* Attempts to write off the end of the register file + * are UNPREDICTABLE; we choose to UNDEF because otherwise + * the neon_load_reg() would write off the end of the array. + */ + return 1; + } addr = tcg_temp_new_i32(); load_reg_var(s, addr, rn); for (reg = 0; reg < nregs; reg++) { @@ -7967,7 +8016,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) } } } else { - int i; + int i, loaded_base = 0; + TCGv loaded_var; /* Load/store multiple. */ addr = load_reg(s, rn); offset = 0; @@ -7979,6 +8029,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) tcg_gen_addi_i32(addr, addr, -offset); } + TCGV_UNUSED(loaded_var); for (i = 0; i < 16; i++) { if ((insn & (1 << i)) == 0) continue; @@ -7987,6 +8038,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) tmp = gen_ld32(addr, IS_USER(s)); if (i == 15) { gen_bx(s, tmp); + } else if (i == rn) { + loaded_var = tmp; + loaded_base = 1; } else { store_reg(s, i, tmp); } @@ -7997,6 +8051,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) } tcg_gen_addi_i32(addr, addr, 4); } + if (loaded_base) { + store_reg(s, rn, loaded_var); + } if (insn & (1 << 21)) { /* Base register writeback. */ if (insn & (1 << 24)) { @@ -9397,7 +9454,10 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) break; case 12: + { /* load/store multiple */ + TCGv loaded_var; + TCGV_UNUSED(loaded_var); rn = (insn >> 8) & 0x7; addr = load_reg(s, rn); for (i = 0; i < 8; i++) { @@ -9405,7 +9465,11 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) if (insn & (1 << 11)) { /* load */ tmp = gen_ld32(addr, IS_USER(s)); - store_reg(s, i, tmp); + if (i == rn) { + loaded_var = tmp; + } else { + store_reg(s, i, tmp); + } } else { /* store */ tmp = load_reg(s, i); @@ -9415,14 +9479,18 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) tcg_gen_addi_i32(addr, addr, 4); } } - /* Base register writeback. */ if ((insn & (1 << rn)) == 0) { + /* base reg not in list: base register writeback */ store_reg(s, rn, addr); } else { + /* base reg in list: if load, complete it now */ + if (insn & (1 << 11)) { + store_reg(s, rn, loaded_var); + } tcg_temp_free_i32(addr); } break; - + } case 13: /* conditional branch or swi */ cond = (insn >> 8) & 0xf; @@ -9551,8 +9619,8 @@ static inline void gen_intermediate_code_internal(CPUState *env, * This is handled in the same way as restoration of the * PC in these situations: we will be called again with search_pc=1 * and generate a mapping of the condexec bits for each PC in - * gen_opc_condexec_bits[]. gen_pc_load[] then uses this to restore - * the condexec bits. + * gen_opc_condexec_bits[]. restore_state_to_opc() then uses + * this to restore the condexec bits. * * Note that there are no instructions which can read the condexec * bits, and none which can write non-static values to them, so @@ -9817,8 +9885,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf, #endif } -void gen_pc_load(CPUState *env, TranslationBlock *tb, - unsigned long searched_pc, int pc_pos, void *puc) +void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos) { env->regs[15] = gen_opc_pc[pc_pos]; env->condexec_bits = gen_opc_condexec_bits[pc_pos]; |