summaryrefslogtreecommitdiffstats
path: root/qemu/target-sh4
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/target-sh4')
-rw-r--r--qemu/target-sh4/Makefile.objs1
-rw-r--r--qemu/target-sh4/cpu.c20
-rw-r--r--qemu/target-sh4/cpu.h7
-rw-r--r--qemu/target-sh4/gdbstub.c2
-rw-r--r--qemu/target-sh4/helper.c14
-rw-r--r--qemu/target-sh4/helper.h34
-rw-r--r--qemu/target-sh4/monitor.c53
-rw-r--r--qemu/target-sh4/op_helper.c3
-rw-r--r--qemu/target-sh4/translate.c278
9 files changed, 211 insertions, 201 deletions
diff --git a/qemu/target-sh4/Makefile.objs b/qemu/target-sh4/Makefile.objs
index a285358ad..2c25d96e6 100644
--- a/qemu/target-sh4/Makefile.objs
+++ b/qemu/target-sh4/Makefile.objs
@@ -1,2 +1,3 @@
obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += monitor.o
obj-y += gdbstub.o
diff --git a/qemu/target-sh4/cpu.c b/qemu/target-sh4/cpu.c
index 5c65ab4df..86ba38808 100644
--- a/qemu/target-sh4/cpu.c
+++ b/qemu/target-sh4/cpu.c
@@ -19,6 +19,8 @@
* <http://www.gnu.org/licenses/lgpl-2.1.html>
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "cpu.h"
#include "qemu-common.h"
#include "migration/vmstate.h"
@@ -70,6 +72,12 @@ static void superh_cpu_reset(CPUState *s)
set_default_nan_mode(1, &env->fp_status);
}
+static void superh_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
+{
+ info->mach = bfd_mach_sh4;
+ info->print_insn = print_insn_sh;
+}
+
typedef struct SuperHCPUListState {
fprintf_function cpu_fprintf;
FILE *file;
@@ -288,8 +296,18 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
#else
cc->get_phys_page_debug = superh_cpu_get_phys_page_debug;
#endif
- dc->vmsd = &vmstate_sh_cpu;
+ cc->disas_set_info = superh_cpu_disas_set_info;
+
cc->gdb_num_core_regs = 59;
+
+ dc->vmsd = &vmstate_sh_cpu;
+
+ /*
+ * Reason: superh_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo superh_cpu_type_info = {
diff --git a/qemu/target-sh4/cpu.h b/qemu/target-sh4/cpu.h
index 34bb3d779..3b23e967b 100644
--- a/qemu/target-sh4/cpu.h
+++ b/qemu/target-sh4/cpu.h
@@ -19,13 +19,10 @@
#ifndef _CPU_SH4_H
#define _CPU_SH4_H
-#include "config.h"
#include "qemu-common.h"
#define TARGET_LONG_BITS 32
-#define ELF_MACHINE EM_SH
-
/* CPU Subtypes */
#define SH_CPU_SH7750 (1 << 0)
#define SH_CPU_SH7750S (1 << 1)
@@ -122,6 +119,7 @@ typedef struct tlb_t {
#define ITLB_SIZE 4
#define NB_MMU_MODES 2
+#define TARGET_INSN_START_EXTRA_WORDS 1
enum sh_features {
SH_FEATURE_SH4A = 1,
@@ -227,7 +225,6 @@ void cpu_load_tlb(CPUSH4State * env);
#define cpu_init(cpu_model) CPU(cpu_sh4_init(cpu_model))
#define cpu_exec cpu_sh4_exec
-#define cpu_gen_code cpu_sh4_gen_code
#define cpu_signal_handler cpu_sh4_signal_handler
#define cpu_list sh4_cpu_list
@@ -235,7 +232,7 @@ void cpu_load_tlb(CPUSH4State * env);
#define MMU_MODE0_SUFFIX _kernel
#define MMU_MODE1_SUFFIX _user
#define MMU_USER_IDX 1
-static inline int cpu_mmu_index (CPUSH4State *env)
+static inline int cpu_mmu_index (CPUSH4State *env, bool ifetch)
{
return (env->sr & (1u << SR_MD)) == 0 ? 1 : 0;
}
diff --git a/qemu/target-sh4/gdbstub.c b/qemu/target-sh4/gdbstub.c
index a365a27aa..1b59ea8c7 100644
--- a/qemu/target-sh4/gdbstub.c
+++ b/qemu/target-sh4/gdbstub.c
@@ -17,7 +17,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
+#include "qemu/osdep.h"
#include "qemu-common.h"
#include "exec/gdbstub.h"
diff --git a/qemu/target-sh4/helper.c b/qemu/target-sh4/helper.c
index a533f08ea..6438338f2 100644
--- a/qemu/target-sh4/helper.c
+++ b/qemu/target-sh4/helper.c
@@ -16,14 +16,10 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-#include <signal.h>
+#include "qemu/osdep.h"
#include "cpu.h"
+#include "exec/log.h"
#if !defined(CONFIG_USER_ONLY)
#include "hw/sh4/sh_intc.h"
@@ -60,7 +56,7 @@ int superh_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
{
- /* For user mode, only U0 area is cachable. */
+ /* For user mode, only U0 area is cacheable. */
return !(addr & 0x80000000);
}
@@ -826,11 +822,11 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
/* check area */
if (env->sr & (1u << SR_MD)) {
- /* For previledged mode, P2 and P4 area is not cachable. */
+ /* For privileged mode, P2 and P4 area is not cacheable. */
if ((0xA0000000 <= addr && addr < 0xC0000000) || 0xE0000000 <= addr)
return 0;
} else {
- /* For user mode, only U0 area is cachable. */
+ /* For user mode, only U0 area is cacheable. */
if (0x80000000 <= addr)
return 0;
}
diff --git a/qemu/target-sh4/helper.h b/qemu/target-sh4/helper.h
index c9bc40704..dce859cae 100644
--- a/qemu/target-sh4/helper.h
+++ b/qemu/target-sh4/helper.h
@@ -18,28 +18,28 @@ DEF_HELPER_2(ld_fpscr, void, env, i32)
DEF_HELPER_FLAGS_1(fabs_FT, TCG_CALL_NO_RWG_SE, f32, f32)
DEF_HELPER_FLAGS_1(fabs_DT, TCG_CALL_NO_RWG_SE, f64, f64)
-DEF_HELPER_3(fadd_FT, f32, env, f32, f32)
-DEF_HELPER_3(fadd_DT, f64, env, f64, f64)
-DEF_HELPER_2(fcnvsd_FT_DT, f64, env, f32)
-DEF_HELPER_2(fcnvds_DT_FT, f32, env, f64)
+DEF_HELPER_FLAGS_3(fadd_FT, TCG_CALL_NO_WG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fadd_DT, TCG_CALL_NO_WG, f64, env, f64, f64)
+DEF_HELPER_FLAGS_2(fcnvsd_FT_DT, TCG_CALL_NO_WG, f64, env, f32)
+DEF_HELPER_FLAGS_2(fcnvds_DT_FT, TCG_CALL_NO_WG, f32, env, f64)
DEF_HELPER_3(fcmp_eq_FT, void, env, f32, f32)
DEF_HELPER_3(fcmp_eq_DT, void, env, f64, f64)
DEF_HELPER_3(fcmp_gt_FT, void, env, f32, f32)
DEF_HELPER_3(fcmp_gt_DT, void, env, f64, f64)
-DEF_HELPER_3(fdiv_FT, f32, env, f32, f32)
-DEF_HELPER_3(fdiv_DT, f64, env, f64, f64)
-DEF_HELPER_2(float_FT, f32, env, i32)
-DEF_HELPER_2(float_DT, f64, env, i32)
-DEF_HELPER_4(fmac_FT, f32, env, f32, f32, f32)
-DEF_HELPER_3(fmul_FT, f32, env, f32, f32)
-DEF_HELPER_3(fmul_DT, f64, env, f64, f64)
+DEF_HELPER_FLAGS_3(fdiv_FT, TCG_CALL_NO_WG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fdiv_DT, TCG_CALL_NO_WG, f64, env, f64, f64)
+DEF_HELPER_FLAGS_2(float_FT, TCG_CALL_NO_WG, f32, env, i32)
+DEF_HELPER_FLAGS_2(float_DT, TCG_CALL_NO_WG, f64, env, i32)
+DEF_HELPER_FLAGS_4(fmac_FT, TCG_CALL_NO_WG, f32, env, f32, f32, f32)
+DEF_HELPER_FLAGS_3(fmul_FT, TCG_CALL_NO_WG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fmul_DT, TCG_CALL_NO_WG, f64, env, f64, f64)
DEF_HELPER_FLAGS_1(fneg_T, TCG_CALL_NO_RWG_SE, f32, f32)
-DEF_HELPER_3(fsub_FT, f32, env, f32, f32)
-DEF_HELPER_3(fsub_DT, f64, env, f64, f64)
-DEF_HELPER_2(fsqrt_FT, f32, env, f32)
-DEF_HELPER_2(fsqrt_DT, f64, env, f64)
-DEF_HELPER_2(ftrc_FT, i32, env, f32)
-DEF_HELPER_2(ftrc_DT, i32, env, f64)
+DEF_HELPER_FLAGS_3(fsub_FT, TCG_CALL_NO_WG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fsub_DT, TCG_CALL_NO_WG, f64, env, f64, f64)
+DEF_HELPER_FLAGS_2(fsqrt_FT, TCG_CALL_NO_WG, f32, env, f32)
+DEF_HELPER_FLAGS_2(fsqrt_DT, TCG_CALL_NO_WG, f64, env, f64)
+DEF_HELPER_FLAGS_2(ftrc_FT, TCG_CALL_NO_WG, i32, env, f32)
+DEF_HELPER_FLAGS_2(ftrc_DT, TCG_CALL_NO_WG, i32, env, f64)
DEF_HELPER_3(fipr, void, env, i32, i32)
DEF_HELPER_2(ftrv, void, env, i32)
diff --git a/qemu/target-sh4/monitor.c b/qemu/target-sh4/monitor.c
new file mode 100644
index 000000000..426e5d491
--- /dev/null
+++ b/qemu/target-sh4/monitor.c
@@ -0,0 +1,53 @@
+/*
+ * QEMU monitor
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "monitor/monitor.h"
+#include "monitor/hmp-target.h"
+#include "hmp.h"
+
+static void print_tlb(Monitor *mon, int idx, tlb_t *tlb)
+{
+ monitor_printf(mon, " tlb%i:\t"
+ "asid=%hhu vpn=%x\tppn=%x\tsz=%hhu size=%u\t"
+ "v=%hhu shared=%hhu cached=%hhu prot=%hhu "
+ "dirty=%hhu writethrough=%hhu\n",
+ idx,
+ tlb->asid, tlb->vpn, tlb->ppn, tlb->sz, tlb->size,
+ tlb->v, tlb->sh, tlb->c, tlb->pr,
+ tlb->d, tlb->wt);
+}
+
+void hmp_info_tlb(Monitor *mon, const QDict *qdict)
+{
+ CPUArchState *env = mon_get_cpu_env();
+ int i;
+
+ monitor_printf (mon, "ITLB:\n");
+ for (i = 0 ; i < ITLB_SIZE ; i++)
+ print_tlb (mon, i, &env->itlb[i]);
+ monitor_printf (mon, "UTLB:\n");
+ for (i = 0 ; i < UTLB_SIZE ; i++)
+ print_tlb (mon, i, &env->utlb[i]);
+}
diff --git a/qemu/target-sh4/op_helper.c b/qemu/target-sh4/op_helper.c
index cbc11aecc..368e687d6 100644
--- a/qemu/target-sh4/op_helper.c
+++ b/qemu/target-sh4/op_helper.c
@@ -16,8 +16,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include <assert.h>
-#include <stdlib.h>
+#include "qemu/osdep.h"
#include "cpu.h"
#include "exec/helper-proto.h"
#include "exec/cpu_ldst.h"
diff --git a/qemu/target-sh4/translate.c b/qemu/target-sh4/translate.c
index 3b4a1b5ce..7c189680a 100644
--- a/qemu/target-sh4/translate.c
+++ b/qemu/target-sh4/translate.c
@@ -19,6 +19,7 @@
#define DEBUG_DISAS
+#include "qemu/osdep.h"
#include "cpu.h"
#include "disas/disas.h"
#include "tcg-op.h"
@@ -28,6 +29,7 @@
#include "exec/helper-gen.h"
#include "trace-tcg.h"
+#include "exec/log.h"
typedef struct DisasContext {
@@ -59,7 +61,7 @@ enum {
};
/* global register indexes */
-static TCGv_ptr cpu_env;
+static TCGv_env cpu_env;
static TCGv cpu_gregs[24];
static TCGv cpu_sr, cpu_sr_m, cpu_sr_q, cpu_sr_t;
static TCGv cpu_pc, cpu_ssr, cpu_spc, cpu_gbr;
@@ -70,8 +72,6 @@ static TCGv cpu_fregs[32];
/* internal register indexes */
static TCGv cpu_flags, cpu_delayed_pc;
-static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
-
#include "exec/gen-icount.h"
void sh4_translate_init(void)
@@ -102,53 +102,53 @@ void sh4_translate_init(void)
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
for (i = 0; i < 24; i++)
- cpu_gregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_gregs[i] = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, gregs[i]),
gregnames[i]);
- cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_pc = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, pc), "PC");
- cpu_sr = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_sr = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, sr), "SR");
- cpu_sr_m = tcg_global_mem_new_i32(TCG_AREG0,
- offsetof(CPUSH4State, sr_m), "SR_M");
- cpu_sr_q = tcg_global_mem_new_i32(TCG_AREG0,
- offsetof(CPUSH4State, sr_q), "SR_Q");
- cpu_sr_t = tcg_global_mem_new_i32(TCG_AREG0,
- offsetof(CPUSH4State, sr_t), "SR_T");
- cpu_ssr = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_sr_m = tcg_global_mem_new_i32(cpu_env,
+ offsetof(CPUSH4State, sr_m), "SR_M");
+ cpu_sr_q = tcg_global_mem_new_i32(cpu_env,
+ offsetof(CPUSH4State, sr_q), "SR_Q");
+ cpu_sr_t = tcg_global_mem_new_i32(cpu_env,
+ offsetof(CPUSH4State, sr_t), "SR_T");
+ cpu_ssr = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, ssr), "SSR");
- cpu_spc = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_spc = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, spc), "SPC");
- cpu_gbr = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_gbr = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, gbr), "GBR");
- cpu_vbr = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_vbr = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, vbr), "VBR");
- cpu_sgr = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_sgr = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, sgr), "SGR");
- cpu_dbr = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_dbr = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, dbr), "DBR");
- cpu_mach = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_mach = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, mach), "MACH");
- cpu_macl = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_macl = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, macl), "MACL");
- cpu_pr = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_pr = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, pr), "PR");
- cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_fpscr = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, fpscr), "FPSCR");
- cpu_fpul = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_fpul = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, fpul), "FPUL");
- cpu_flags = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_flags = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, flags), "_flags_");
- cpu_delayed_pc = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_delayed_pc = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, delayed_pc),
"_delayed_pc_");
- cpu_ldst = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_ldst = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, ldst), "_ldst_");
for (i = 0; i < 32; i++)
- cpu_fregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
+ cpu_fregs[i] = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUSH4State, fregs[i]),
fregnames[i]);
@@ -288,10 +288,10 @@ static inline void gen_load_fpr64(TCGv_i64 t, int reg)
static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_trunc_i64_i32(tmp, t);
+ tcg_gen_extrl_i64_i32(tmp, t);
tcg_gen_mov_i32(cpu_fregs[reg + 1], tmp);
tcg_gen_shri_i64(t, t, 32);
- tcg_gen_trunc_i64_i32(tmp, t);
+ tcg_gen_extrl_i64_i32(tmp, t);
tcg_gen_mov_i32(cpu_fregs[reg], tmp);
tcg_temp_free_i32(tmp);
}
@@ -612,15 +612,11 @@ static void _decode_opc(DisasContext * ctx)
return;
case 0x6008: /* swap.b Rm,Rn */
{
- TCGv high, low;
- high = tcg_temp_new();
- tcg_gen_andi_i32(high, REG(B7_4), 0xffff0000);
- low = tcg_temp_new();
+ TCGv low = tcg_temp_new();;
tcg_gen_ext16u_i32(low, REG(B7_4));
tcg_gen_bswap16_i32(low, low);
- tcg_gen_or_i32(REG(B11_8), high, low);
+ tcg_gen_deposit_i32(REG(B11_8), REG(B7_4), low, 0, 16);
tcg_temp_free(low);
- tcg_temp_free(high);
}
return;
case 0x6009: /* swap.w Rm,Rn */
@@ -692,18 +688,11 @@ static void _decode_opc(DisasContext * ctx)
{
TCGv cmp1 = tcg_temp_new();
TCGv cmp2 = tcg_temp_new();
- tcg_gen_xor_i32(cmp1, REG(B7_4), REG(B11_8));
- tcg_gen_andi_i32(cmp2, cmp1, 0xff000000);
- tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, cmp2, 0);
- tcg_gen_andi_i32(cmp2, cmp1, 0x00ff0000);
- tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
- tcg_gen_or_i32(cpu_sr_t, cpu_sr_t, cmp2);
- tcg_gen_andi_i32(cmp2, cmp1, 0x0000ff00);
- tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
- tcg_gen_or_i32(cpu_sr_t, cpu_sr_t, cmp2);
- tcg_gen_andi_i32(cmp2, cmp1, 0x000000ff);
- tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
- tcg_gen_or_i32(cpu_sr_t, cpu_sr_t, cmp2);
+ tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8));
+ tcg_gen_subi_i32(cmp1, cmp2, 0x01010101);
+ tcg_gen_andc_i32(cmp1, cmp1, cmp2);
+ tcg_gen_andi_i32(cmp1, cmp1, 0x80808080);
+ tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0);
tcg_temp_free(cmp2);
tcg_temp_free(cmp1);
}
@@ -843,67 +832,54 @@ static void _decode_opc(DisasContext * ctx)
return;
case 0x400c: /* shad Rm,Rn */
{
- TCGLabel *label1 = gen_new_label();
- TCGLabel *label2 = gen_new_label();
- TCGLabel *label3 = gen_new_label();
- TCGLabel *label4 = gen_new_label();
- TCGv shift;
- tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
- /* Rm positive, shift to the left */
- shift = tcg_temp_new();
- tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
- tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
- tcg_temp_free(shift);
- tcg_gen_br(label4);
- /* Rm negative, shift to the right */
- gen_set_label(label1);
- shift = tcg_temp_new();
- tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
- tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2);
- tcg_gen_not_i32(shift, REG(B7_4));
- tcg_gen_andi_i32(shift, shift, 0x1f);
- tcg_gen_addi_i32(shift, shift, 1);
- tcg_gen_sar_i32(REG(B11_8), REG(B11_8), shift);
- tcg_temp_free(shift);
- tcg_gen_br(label4);
- /* Rm = -32 */
- gen_set_label(label2);
- tcg_gen_brcondi_i32(TCG_COND_LT, REG(B11_8), 0, label3);
- tcg_gen_movi_i32(REG(B11_8), 0);
- tcg_gen_br(label4);
- gen_set_label(label3);
- tcg_gen_movi_i32(REG(B11_8), 0xffffffff);
- gen_set_label(label4);
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
+ TCGv t2 = tcg_temp_new();
+
+ tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
+
+ /* positive case: shift to the left */
+ tcg_gen_shl_i32(t1, REG(B11_8), t0);
+
+ /* negative case: shift to the right in two steps to
+ correctly handle the -32 case */
+ tcg_gen_xori_i32(t0, t0, 0x1f);
+ tcg_gen_sar_i32(t2, REG(B11_8), t0);
+ tcg_gen_sari_i32(t2, t2, 1);
+
+ /* select between the two cases */
+ tcg_gen_movi_i32(t0, 0);
+ tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ tcg_temp_free(t2);
}
return;
case 0x400d: /* shld Rm,Rn */
{
- TCGLabel *label1 = gen_new_label();
- TCGLabel *label2 = gen_new_label();
- TCGLabel *label3 = gen_new_label();
- TCGv shift;
- tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
- /* Rm positive, shift to the left */
- shift = tcg_temp_new();
- tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
- tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
- tcg_temp_free(shift);
- tcg_gen_br(label3);
- /* Rm negative, shift to the right */
- gen_set_label(label1);
- shift = tcg_temp_new();
- tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
- tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2);
- tcg_gen_not_i32(shift, REG(B7_4));
- tcg_gen_andi_i32(shift, shift, 0x1f);
- tcg_gen_addi_i32(shift, shift, 1);
- tcg_gen_shr_i32(REG(B11_8), REG(B11_8), shift);
- tcg_temp_free(shift);
- tcg_gen_br(label3);
- /* Rm = -32 */
- gen_set_label(label2);
- tcg_gen_movi_i32(REG(B11_8), 0);
- gen_set_label(label3);
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
+ TCGv t2 = tcg_temp_new();
+
+ tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
+
+ /* positive case: shift to the left */
+ tcg_gen_shl_i32(t1, REG(B11_8), t0);
+
+ /* negative case: shift to the right in two steps to
+ correctly handle the -32 case */
+ tcg_gen_xori_i32(t0, t0, 0x1f);
+ tcg_gen_shr_i32(t2, REG(B11_8), t0);
+ tcg_gen_shri_i32(t2, t2, 1);
+
+ /* select between the two cases */
+ tcg_gen_movi_i32(t0, 0);
+ tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ tcg_temp_free(t2);
}
return;
case 0x3008: /* sub Rm,Rn */
@@ -1814,10 +1790,6 @@ static void decode_opc(DisasContext * ctx)
{
uint32_t old_flags = ctx->flags;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(ctx->pc);
- }
-
_decode_opc(ctx);
if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
@@ -1844,16 +1816,12 @@ static void decode_opc(DisasContext * ctx)
gen_store_flags(ctx->flags);
}
-static inline void
-gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
{
+ SuperHCPU *cpu = sh_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUSH4State *env = &cpu->env;
DisasContext ctx;
target_ulong pc_start;
- CPUBreakpoint *bp;
- int i, ii;
int num_insns;
int max_insns;
@@ -1870,45 +1838,39 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
ctx.features = env->features;
ctx.has_movcal = (ctx.flags & TB_FLAG_PENDING_MOVCA);
- ii = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
+
gen_tb_start(tb);
while (ctx.bstate == BS_NONE && !tcg_op_buf_full()) {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (ctx.pc == bp->pc) {
- /* We have hit a breakpoint - make sure PC is up-to-date */
- tcg_gen_movi_i32(cpu_pc, ctx.pc);
- gen_helper_debug(cpu_env);
- ctx.bstate = BS_BRANCH;
- break;
- }
- }
- }
- if (search_pc) {
- i = tcg_op_buf_count();
- if (ii < i) {
- ii++;
- while (ii < i)
- tcg_ctx.gen_opc_instr_start[ii++] = 0;
- }
- tcg_ctx.gen_opc_pc[ii] = ctx.pc;
- gen_opc_hflags[ii] = ctx.flags;
- tcg_ctx.gen_opc_instr_start[ii] = 1;
- tcg_ctx.gen_opc_icount[ii] = num_insns;
+ tcg_gen_insn_start(ctx.pc, ctx.flags);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+ /* We have hit a breakpoint - make sure PC is up-to-date */
+ tcg_gen_movi_i32(cpu_pc, ctx.pc);
+ gen_helper_debug(cpu_env);
+ ctx.bstate = BS_BRANCH;
+ /* The address covered by the breakpoint must be included in
+ [tb->pc, tb->pc + tb->size) in order to for it to be
+ properly cleared -- thus we increment the PC here so that
+ the logic setting tb->size below does the right thing. */
+ ctx.pc += 2;
+ break;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
-#if 0
- fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc);
- fflush(stderr);
-#endif
+ }
+
ctx.opcode = cpu_lduw_code(env, ctx.pc);
decode_opc(&ctx);
- num_insns++;
ctx.pc += 2;
if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
break;
@@ -1948,15 +1910,8 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
gen_tb_end(tb, num_insns);
- if (search_pc) {
- i = tcg_op_buf_count();
- ii++;
- while (ii <= i)
- tcg_ctx.gen_opc_instr_start[ii++] = 0;
- } else {
- tb->size = ctx.pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -1967,18 +1922,9 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
#endif
}
-void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(sh_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUSH4State * env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(sh_env_get_cpu(env), tb, true);
-}
-
-void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
- env->flags = gen_opc_hflags[pc_pos];
+ env->pc = data[0];
+ env->flags = data[1];
}