From 6815146a6c5a32e24806407748f6dbc6e70f37ee Mon Sep 17 00:00:00 2001 From: twocode Date: Tue, 25 Mar 2014 23:04:28 -0700 Subject: [PATCH 1/7] The msr instruction failed to change the nzcv register value correctly. This bug resolves this bug by adding the decoding rule for handling nzcv modifications. --- target-arm/translate-a64.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index aee7218179503..800420816dae4 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -385,9 +385,15 @@ static void handle_msr(DisasContext *s, uint32_t insn) int crn = get_bits(insn, 12, 4); int op2 = get_bits(insn, 5, 3); - /* XXX what are these? */ - if (op0 == 3 && op1 == 3 && op2 == 2 && !crm && crn == 13) { - tcg_gen_st_i64(cpu_reg(dest), cpu_env, offsetof(CPUARMState, sr.tpidr_el0)); + /* Instructions for accessing special-purpose registers */ + if (op0 == 3 && crn == 4 && op2 == 0) { + TCGv_i32 t2 = tcg_temp_new_i32(); + tcg_gen_trunc_i64_i32(t2, cpu_reg(dest)); + tcg_gen_shri_i32(t2, t2, 28); + tcg_gen_st_i32(t2, cpu_env, offsetof(CPUARMState, pstate)); + tcg_temp_free_i32(t2); + } else if (op0 == 3 && op1 == 3 && op2 == 2 && !crm && crn == 13) { + tcg_gen_st32_i64(cpu_reg(dest), cpu_env, offsetof(CPUARMState, sr.tpidr_el0)); } else if (op0 == 3 && op1 == 3 && (op2 == 0 || op2 == 1) && crm == 4 && crn == 4) { /* XXX this is wrong! */ tcg_gen_st32_i64(cpu_reg(dest), cpu_env, From 1d6a3a085e9670ad9973a6064532d631126d0cb5 Mon Sep 17 00:00:00 2001 From: twocode Date: Tue, 25 Mar 2014 23:47:00 -0700 Subject: [PATCH 2/7] tst instruction is correctly decoded but incorrectly handled when working in 32-bit regsize mode. Only low 32 bits should be anded and referred for setting the n value in pstate. --- linux-user/main.c | 10 ++++++ target-arm/translate-a64.c | 65 +++++++++++++++++++++++--------------- target-arm/translate.c | 16 ++++++---- 3 files changed, 59 insertions(+), 32 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 0ddf6d1f86a71..327535f76a9a4 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -44,6 +44,8 @@ int gdbstub_port; envlist_t *envlist; const char *cpu_model; unsigned long mmap_min_addr; +unsigned long log_eip; +int always_log = 1; #if defined(CONFIG_USE_GUEST_BASE) unsigned long guest_base; int have_guest_base; @@ -3501,6 +3503,12 @@ static void handle_arg_strace(const char *arg) do_strace = 1; } +static void handle_arg_addr(const char *arg) +{ + always_log = 0; + log_eip = strtoul(arg, NULL, 16); +} + static void handle_arg_version(const char *arg) { printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION @@ -3553,6 +3561,8 @@ static const struct qemu_argument arg_table[] = { "", "run in singlestep mode"}, {"strace", "QEMU_STRACE", false, handle_arg_strace, "", "log system calls"}, + {"addr", "", true, handle_arg_addr, + "", "only print cpu status of executing such eip"}, {"version", "QEMU_VERSION", false, handle_arg_version, "", "display version information and exit"}, {NULL, NULL, false, NULL, NULL, NULL} diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 800420816dae4..786bce54d49ce 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -47,6 +47,8 @@ static TCGv_i32 pstate; static TCGv_i64 cpu_exclusive_addr; static TCGv_i64 cpu_exclusive_val; static TCGv_i64 cpu_exclusive_high; +extern long log_eip; +extern int always_log; #ifdef CONFIG_USER_ONLY static TCGv_i64 cpu_exclusive_test; static TCGv_i64 cpu_exclusive_info; @@ -98,33 +100,40 @@ void cpu_dump_state_a64(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf, { int i; - cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n", env->pc, env->sp); - for(i = 0; i < 31; i++) { - cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]); - if ((i % 4) == 3) - cpu_fprintf(f, "\n"); - else - cpu_fprintf(f, " "); - } - cpu_fprintf(f, "XZR=%016"PRIx64"\n", env->xregs[31]); - cpu_fprintf(f, "PSTATE=%c%c%c%c\n", - env->pstate & PSTATE_N ? 'n' : '.', - env->pstate & PSTATE_Z ? 'z' : '.', - env->pstate & PSTATE_C ? 'c' : '.', - env->pstate & PSTATE_V ? 'v' : '.'); - cpu_fprintf(f, "\n"); - - if (1) { //flags & CPU_DUMP_FPU) { - int numvfpregs = 32; - for (i = 0; i < numvfpregs; i++) { - uint64_t v = float64_val(env->vfp.regs[i * 2]); - uint64_t v1 = float64_val(env->vfp.regs[(i * 2) + 1]); - if (!v && !v1) continue; - cpu_fprintf(f, "d%02d.0=%016" PRIx64 " " "d%02d.0=%016" PRIx64 "\n", - i, v, i, v1); + if (always_log || (log_eip && log_eip == env->pc)) { + cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n", env->pc, env->sp); + cpu_fprintf(f, "[CPUSTATE] "); + for(i = 0; i < 31; i++) { + cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]); + if ((i % 4) == 3) { + cpu_fprintf(f, "\n"); + cpu_fprintf(f, "[CPUSTATE] "); + } + else + cpu_fprintf(f, " "); + } + cpu_fprintf(f, "XZR=%016"PRIx64"\n", env->xregs[31]); + cpu_fprintf(f, "[CPUSTATE] "); + cpu_fprintf(f, "PSTATE=%c%c%c%c\n", + env->pstate & PSTATE_N ? 'n' : '.', + env->pstate & PSTATE_Z ? 'z' : '.', + env->pstate & PSTATE_C ? 'c' : '.', + env->pstate & PSTATE_V ? 'v' : '.'); + cpu_fprintf(f, "\n"); + + if (1) { //flags & CPU_DUMP_FPU) { + int numvfpregs = 32; + for (i = 0; i < numvfpregs; i++) { + uint64_t v = float64_val(env->vfp.regs[i * 2]); + uint64_t v1 = float64_val(env->vfp.regs[(i * 2) + 1]); + if (!v && !v1) continue; + cpu_fprintf(f, "d%02d.0=%016" PRIx64 " " "d%02d.0=%016" PRIx64 "\n", + i, v, i, v1); + } + cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]); } - cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]); } + } static int get_bits(uint32_t inst, int start, int len) @@ -619,7 +628,11 @@ static void handle_orri(DisasContext *s, uint32_t insn) } if (setflags) { - gen_helper_pstate_add(pstate, pstate, tcg_dst, cpu_reg(31), tcg_dst); + if (is_32bit) { + gen_helper_pstate_add32(pstate, pstate, tcg_dst, cpu_reg(31), tcg_dst); + } else { + gen_helper_pstate_add(pstate, pstate, tcg_dst, cpu_reg(31), tcg_dst); + } } tcg_temp_free_i64(tcg_op2); diff --git a/target-arm/translate.c b/target-arm/translate.c index 593d58327adcc..59781214f2df4 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -68,6 +68,8 @@ static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF; static TCGv_i32 cpu_exclusive_addr; static TCGv_i32 cpu_exclusive_val; static TCGv_i32 cpu_exclusive_high; +extern long log_eip; +extern int always_log; #ifdef CONFIG_USER_ONLY static TCGv_i32 cpu_exclusive_test; static TCGv_i32 cpu_exclusive_info; @@ -10166,12 +10168,14 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, *tcg_ctx.gen_opc_ptr = INDEX_op_end; #ifdef DEBUG_DISAS - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { - qemu_log("----------------\n"); - qemu_log("IN: %s\n", lookup_symbol(pc_start)); - log_target_disas(env, pc_start, dc->pc - pc_start, - dc->thumb | (dc->bswap_code << 1)); - qemu_log("\n"); + if (always_log || (log_eip && log_eip == env->pc)) { + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { + qemu_log("----------------\n"); + qemu_log("IN: %s\n", lookup_symbol(pc_start)); + log_target_disas(env, pc_start, dc->pc - pc_start, + dc->thumb | (dc->bswap_code << 1)); + qemu_log("\n"); + } } #endif From a4990fcf9f9238a5e801a42ced8cf2f11a51eb24 Mon Sep 17 00:00:00 2001 From: twocode Date: Wed, 26 Mar 2014 20:35:37 -0700 Subject: [PATCH 3/7] remove the debug info. --- linux-user/main.c | 10 ------- target-arm/translate-a64.c | 59 +++++++++++++++++--------------------- target-arm/translate.c | 16 ++++------- 3 files changed, 33 insertions(+), 52 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 327535f76a9a4..0ddf6d1f86a71 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -44,8 +44,6 @@ int gdbstub_port; envlist_t *envlist; const char *cpu_model; unsigned long mmap_min_addr; -unsigned long log_eip; -int always_log = 1; #if defined(CONFIG_USE_GUEST_BASE) unsigned long guest_base; int have_guest_base; @@ -3503,12 +3501,6 @@ static void handle_arg_strace(const char *arg) do_strace = 1; } -static void handle_arg_addr(const char *arg) -{ - always_log = 0; - log_eip = strtoul(arg, NULL, 16); -} - static void handle_arg_version(const char *arg) { printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION @@ -3561,8 +3553,6 @@ static const struct qemu_argument arg_table[] = { "", "run in singlestep mode"}, {"strace", "QEMU_STRACE", false, handle_arg_strace, "", "log system calls"}, - {"addr", "", true, handle_arg_addr, - "", "only print cpu status of executing such eip"}, {"version", "QEMU_VERSION", false, handle_arg_version, "", "display version information and exit"}, {NULL, NULL, false, NULL, NULL, NULL} diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 786bce54d49ce..cc9253cb13f69 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -47,8 +47,6 @@ static TCGv_i32 pstate; static TCGv_i64 cpu_exclusive_addr; static TCGv_i64 cpu_exclusive_val; static TCGv_i64 cpu_exclusive_high; -extern long log_eip; -extern int always_log; #ifdef CONFIG_USER_ONLY static TCGv_i64 cpu_exclusive_test; static TCGv_i64 cpu_exclusive_info; @@ -100,38 +98,35 @@ void cpu_dump_state_a64(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf, { int i; - if (always_log || (log_eip && log_eip == env->pc)) { - cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n", env->pc, env->sp); - cpu_fprintf(f, "[CPUSTATE] "); - for(i = 0; i < 31; i++) { - cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]); - if ((i % 4) == 3) { - cpu_fprintf(f, "\n"); - cpu_fprintf(f, "[CPUSTATE] "); - } - else - cpu_fprintf(f, " "); + cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n", env->pc, env->sp); + cpu_fprintf(f, "[CPUSTATE] "); + for(i = 0; i < 31; i++) { + cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]); + if ((i % 4) == 3) { + cpu_fprintf(f, "\n"); + cpu_fprintf(f, "[CPUSTATE] "); } - cpu_fprintf(f, "XZR=%016"PRIx64"\n", env->xregs[31]); - cpu_fprintf(f, "[CPUSTATE] "); - cpu_fprintf(f, "PSTATE=%c%c%c%c\n", - env->pstate & PSTATE_N ? 'n' : '.', - env->pstate & PSTATE_Z ? 'z' : '.', - env->pstate & PSTATE_C ? 'c' : '.', - env->pstate & PSTATE_V ? 'v' : '.'); - cpu_fprintf(f, "\n"); - - if (1) { //flags & CPU_DUMP_FPU) { - int numvfpregs = 32; - for (i = 0; i < numvfpregs; i++) { - uint64_t v = float64_val(env->vfp.regs[i * 2]); - uint64_t v1 = float64_val(env->vfp.regs[(i * 2) + 1]); - if (!v && !v1) continue; - cpu_fprintf(f, "d%02d.0=%016" PRIx64 " " "d%02d.0=%016" PRIx64 "\n", - i, v, i, v1); - } - cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]); + else + cpu_fprintf(f, " "); + } + cpu_fprintf(f, "XZR=%016"PRIx64"\n", env->xregs[31]); + cpu_fprintf(f, "PSTATE=%c%c%c%c\n", + env->pstate & PSTATE_N ? 'n' : '.', + env->pstate & PSTATE_Z ? 'z' : '.', + env->pstate & PSTATE_C ? 'c' : '.', + env->pstate & PSTATE_V ? 'v' : '.'); + cpu_fprintf(f, "\n"); + + if (1) { //flags & CPU_DUMP_FPU) { + int numvfpregs = 32; + for (i = 0; i < numvfpregs; i++) { + uint64_t v = float64_val(env->vfp.regs[i * 2]); + uint64_t v1 = float64_val(env->vfp.regs[(i * 2) + 1]); + if (!v && !v1) continue; + cpu_fprintf(f, "d%02d.0=%016" PRIx64 " " "d%02d.0=%016" PRIx64 "\n", + i, v, i, v1); } + cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]); } } diff --git a/target-arm/translate.c b/target-arm/translate.c index 59781214f2df4..593d58327adcc 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -68,8 +68,6 @@ static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF; static TCGv_i32 cpu_exclusive_addr; static TCGv_i32 cpu_exclusive_val; static TCGv_i32 cpu_exclusive_high; -extern long log_eip; -extern int always_log; #ifdef CONFIG_USER_ONLY static TCGv_i32 cpu_exclusive_test; static TCGv_i32 cpu_exclusive_info; @@ -10168,14 +10166,12 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, *tcg_ctx.gen_opc_ptr = INDEX_op_end; #ifdef DEBUG_DISAS - if (always_log || (log_eip && log_eip == env->pc)) { - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { - qemu_log("----------------\n"); - qemu_log("IN: %s\n", lookup_symbol(pc_start)); - log_target_disas(env, pc_start, dc->pc - pc_start, - dc->thumb | (dc->bswap_code << 1)); - qemu_log("\n"); - } + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { + qemu_log("----------------\n"); + qemu_log("IN: %s\n", lookup_symbol(pc_start)); + log_target_disas(env, pc_start, dc->pc - pc_start, + dc->thumb | (dc->bswap_code << 1)); + qemu_log("\n"); } #endif From 69fb73bbb09104e4230be8e4fc642415d62e7c31 Mon Sep 17 00:00:00 2001 From: twocode Date: Wed, 26 Mar 2014 20:38:32 -0700 Subject: [PATCH 4/7] remove the debug info. --- target-arm/translate-a64.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index cc9253cb13f69..f6f88fcdf855f 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -99,13 +99,10 @@ void cpu_dump_state_a64(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf, int i; cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n", env->pc, env->sp); - cpu_fprintf(f, "[CPUSTATE] "); for(i = 0; i < 31; i++) { cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]); - if ((i % 4) == 3) { + if ((i % 4) == 3) cpu_fprintf(f, "\n"); - cpu_fprintf(f, "[CPUSTATE] "); - } else cpu_fprintf(f, " "); } @@ -128,7 +125,6 @@ void cpu_dump_state_a64(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf, } cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]); } - } static int get_bits(uint32_t inst, int start, int len) From edffce75515b138f9fa845439e608a0928bd932a Mon Sep 17 00:00:00 2001 From: twocode Date: Wed, 26 Mar 2014 20:42:58 -0700 Subject: [PATCH 5/7] remove the debug info. --- target-arm/translate-a64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index f6f88fcdf855f..536e36e161c91 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -101,7 +101,7 @@ void cpu_dump_state_a64(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n", env->pc, env->sp); for(i = 0; i < 31; i++) { cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]); - if ((i % 4) == 3) + if ((i % 4) == 3) cpu_fprintf(f, "\n"); else cpu_fprintf(f, " "); From bf10b7ca0843d646c905e3079a89e907e48afc83 Mon Sep 17 00:00:00 2001 From: twocode Date: Wed, 26 Mar 2014 22:36:00 -0700 Subject: [PATCH 6/7] exclude fpcr operation when crm == 4. --- target-arm/translate-a64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 536e36e161c91..1f5a8117e6626 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -386,7 +386,7 @@ static void handle_msr(DisasContext *s, uint32_t insn) int op2 = get_bits(insn, 5, 3); /* Instructions for accessing special-purpose registers */ - if (op0 == 3 && crn == 4 && op2 == 0) { + if (op0 == 3 && crn == 4 && op2 == 0 && crm != 4) { TCGv_i32 t2 = tcg_temp_new_i32(); tcg_gen_trunc_i64_i32(t2, cpu_reg(dest)); tcg_gen_shri_i32(t2, t2, 28); From aa1c16ddff76b0e7489939be9767b5553b4d13b3 Mon Sep 17 00:00:00 2001 From: twocode Date: Thu, 27 Mar 2014 20:52:31 -0700 Subject: [PATCH 7/7] Fix wrong decoder of ld/st instructions; Fix wrong behavior of sign extension scope of 32-bit regsize instrunctions. --- target-arm/translate-a64.c | 70 +++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index eedba38a7c6ca..0d891b6e6f979 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -1008,7 +1008,7 @@ static void ldst_do_vec(DisasContext *s, int dest, TCGv_i64 tcg_addr_real, } static void ldst_do_gpr(DisasContext *s, int dest, TCGv_i64 tcg_addr, int size, - bool is_store, bool is_signed) + bool is_store, bool is_signed, int regsize) { if (is_store) { switch (size) { @@ -1027,14 +1027,34 @@ static void ldst_do_gpr(DisasContext *s, int dest, TCGv_i64 tcg_addr, int size, } } else { if (is_signed) { - /* XXX check what impact regsize has */ + /* regsize restricts the sign extend scope of the destition register */ switch (size) { case 0: - tcg_gen_qemu_ld8s(cpu_reg(dest), tcg_addr, get_mem_index(s)); - break; + { + if (regsize == 2) { + TCGv_i32 w = tcg_temp_new_i32(); + tcg_gen_trunc_i64_i32(w, cpu_reg(dest)); + tcg_gen_qemu_ld8s(w, tcg_addr, get_mem_index(s)); + tcg_gen_extu_i32_i64(cpu_reg(dest), w); + tcg_temp_free(w); + } else { + tcg_gen_qemu_ld8s(cpu_reg(dest), tcg_addr, get_mem_index(s)); + } + break; + } case 1: - tcg_gen_qemu_ld16s(cpu_reg(dest), tcg_addr, get_mem_index(s)); - break; + { + if (regsize == 2) { + TCGv_i32 w = tcg_temp_new_i32(); + tcg_gen_trunc_i64_i32(w, cpu_reg(dest)); + tcg_gen_qemu_ld16s(w, tcg_addr, get_mem_index(s)); + tcg_gen_extu_i32_i64(cpu_reg(dest), w); + tcg_temp_free(w); + } else { + tcg_gen_qemu_ld16s(cpu_reg(dest), tcg_addr, get_mem_index(s)); + } + break; + } case 2: tcg_gen_qemu_ld32s(cpu_reg(dest), tcg_addr, get_mem_index(s)); break; @@ -1062,7 +1082,7 @@ static void ldst_do_gpr(DisasContext *s, int dest, TCGv_i64 tcg_addr, int size, } static void ldst_do(DisasContext *s, int dest, TCGv_i64 tcg_addr, int size, - bool is_store, bool is_signed, bool is_vector, uint32_t insn) + bool is_store, bool is_signed, bool is_vector, uint32_t insn, int regsize) { #ifdef HACK_WATCHPOINTS TCGv_i32 tcg_insn = tcg_const_i32(insn); @@ -1072,7 +1092,7 @@ static void ldst_do(DisasContext *s, int dest, TCGv_i64 tcg_addr, int size, if (is_vector) { ldst_do_vec(s, dest, tcg_addr, size, is_store); } else { - ldst_do_gpr(s, dest, tcg_addr, size, is_store, is_signed); + ldst_do_gpr(s, dest, tcg_addr, size, is_store, is_signed, regsize); } } @@ -1133,9 +1153,9 @@ static void handle_stp(DisasContext *s, uint32_t insn) tcg_gen_addi_i64(tcg_addr, tcg_addr, offset); } - ldst_do(s, rt, tcg_addr, size, is_store, is_signed, is_vector, insn); + ldst_do(s, rt, tcg_addr, size, is_store, is_signed, is_vector, insn, size); tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size); - ldst_do(s, rt2, tcg_addr, size, is_store, is_signed, is_vector, insn); + ldst_do(s, rt2, tcg_addr, size, is_store, is_signed, is_vector, insn, size); tcg_gen_subi_i64(tcg_addr, tcg_addr, 1 << size); if (wback) { @@ -1242,10 +1262,10 @@ static void handle_ldarx(DisasContext *s, uint32_t insn) gen_store_exclusive (s, rs, rt, rt2, tcg_addr, size, is_pair); } } else { - ldst_do_gpr(s, rt, tcg_addr, size, is_store, false); + ldst_do_gpr(s, rt, tcg_addr, size, is_store, false, size); if (is_pair) { tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size); - ldst_do_gpr(s, rt2, tcg_addr, size, is_store, false); + ldst_do_gpr(s, rt2, tcg_addr, size, is_store, false, size); } } @@ -1321,7 +1341,7 @@ static void handle_literal(DisasContext *s, uint32_t insn) goto out; } - ldst_do(s, dest, tcg_addr, size, false, is_signed, is_vector, insn); + ldst_do(s, dest, tcg_addr, size, false, is_signed, is_vector, insn, size); out: tcg_temp_free_i64(tcg_addr); @@ -1329,6 +1349,7 @@ static void handle_literal(DisasContext *s, uint32_t insn) static void handle_ldst(DisasContext *s, uint32_t insn) { + //TODO, if wback && dest = src, then unallocated or nop int dest = get_reg(insn); int source = get_bits(insn, 5, 5); int offset; @@ -1366,22 +1387,15 @@ static void handle_ldst(DisasContext *s, uint32_t insn) unallocated_encoding(s); return; } - } else if (!opc1) { + } else if (size >= 2 && !opc1) { regsize = (size == 3) ? 3 : 2; - } else { - if (size == 3) { - /* prefetch */ - if (!is_store) { - unallocated_encoding(s); - } - return; - } - if (size == 2 && !is_store) { - unallocated_encoding(s); - } + } else if (opc1){ is_store = false; is_signed = true; - regsize = is_store ? 3 : 2; + regsize = get_bits(insn, 22, 1) ? 2 : 3; + } else { + is_signed = false; + regsize = 2; } if (is_imm12) { @@ -1399,8 +1413,8 @@ static void handle_ldst(DisasContext *s, uint32_t insn) if (!postindex) { ldst_calc_index(s, tcg_addr, is_reg_offset, offset, size); } - - ldst_do(s, dest, tcg_addr, size, is_store, is_signed, is_vector, insn); + + ldst_do(s, dest, tcg_addr, size, is_store, is_signed, is_vector, insn, regsize); if (postindex) { ldst_calc_index(s, tcg_addr, is_reg_offset, offset, size);