#include <inttypes.h>
#include "cpu.h"
-#include "disas.h"
+#include "disas/disas.h"
#include "tcg-op.h"
-#include "qemu-log.h"
+#include "qemu/log.h"
+#include "exec/cpu_ldst.h"
+
+#include "exec/helper-proto.h"
+#include "exec/helper-gen.h"
+
+#include "trace-tcg.h"
-#include "helper.h"
-#define GEN_HELPER 1
-#include "helper.h"
/* internal defines */
typedef struct DisasContext {
/* Nonzero if this instruction has been conditionally skipped. */
int condjmp;
/* The label that will be jumped to when the instruction is skipped. */
- int condlabel;
+ TCGLabel *condlabel;
struct TranslationBlock *tb;
int singlestep_enabled;
#ifndef CONFIG_USER_ONLY
static TCGv cpu_F0s, cpu_F1s;
static TCGv_i64 cpu_F0d, cpu_F1d;
-#include "gen-icount.h"
+#include "exec/gen-icount.h"
static const char *regnames[] = {
"r00", "r01", "r02", "r03", "r04", "r05", "r06", "r07",
cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
offsetof(CPUUniCore32State, regs[i]), regnames[i]);
}
-
-#define GEN_HELPER 2
-#include "helper.h"
}
static int num_temps;
#define UCOP_SET_L UCOP_SET(24)
#define UCOP_SET_S UCOP_SET(24)
-#define ILLEGAL cpu_abort(env, \
+#define ILLEGAL cpu_abort(CPU(cpu), \
"Illegal UniCore32 instruction %x at line %d!", \
insn, __LINE__)
static void disas_cp0_insn(CPUUniCore32State *env, DisasContext *s,
uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
TCGv tmp, tmp2, tmp3;
if ((insn & 0xfe000000) == 0xe0000000) {
tmp2 = new_tmp();
static void disas_ocd_insn(CPUUniCore32State *env, DisasContext *s,
uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
TCGv tmp;
if ((insn & 0xff003fff) == 0xe1000400) {
dead_tmp(tmp);
}
-/* FIXME: Most targets have native widening multiplication.
- It would be good to use that instead of a full wide multiply. */
-/* 32x32->64 multiply. Marks inputs as dead. */
-static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
-{
- TCGv_i64 tmp1 = tcg_temp_new_i64();
- TCGv_i64 tmp2 = tcg_temp_new_i64();
-
- tcg_gen_extu_i32_i64(tmp1, a);
- dead_tmp(a);
- tcg_gen_extu_i32_i64(tmp2, b);
- dead_tmp(b);
- tcg_gen_mul_i64(tmp1, tmp1, tmp2);
- tcg_temp_free_i64(tmp2);
- return tmp1;
-}
-
-static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
-{
- TCGv_i64 tmp1 = tcg_temp_new_i64();
- TCGv_i64 tmp2 = tcg_temp_new_i64();
-
- tcg_gen_ext_i32_i64(tmp1, a);
- dead_tmp(a);
- tcg_gen_ext_i32_i64(tmp2, b);
- dead_tmp(b);
- tcg_gen_mul_i64(tmp1, tmp1, tmp2);
- tcg_temp_free_i64(tmp2);
- return tmp1;
-}
-
#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, CF))
/* Set CF to the top bit of var. */
dead_tmp(shift);
}
-static void gen_test_cc(int cc, int label)
+static void gen_test_cc(int cc, TCGLabel *label)
{
TCGv tmp;
TCGv tmp2;
- int inv;
+ TCGLabel *inv;
switch (cc) {
case 0: /* eq: Z */
return tmp;
}
-static inline TCGv_i64 gen_ld64(TCGv addr, int index)
-{
- TCGv_i64 tmp = tcg_temp_new_i64();
- tcg_gen_qemu_ld64(tmp, addr, index);
- return tmp;
-}
-
static inline void gen_st8(TCGv val, TCGv addr, int index)
{
tcg_gen_qemu_st8(val, addr, index);
dead_tmp(val);
}
-static inline void gen_st64(TCGv_i64 val, TCGv addr, int index)
-{
- tcg_gen_qemu_st64(val, addr, index);
- tcg_temp_free_i64(val);
-}
-
static inline void gen_set_pc_im(uint32_t val)
{
tcg_gen_movi_i32(cpu_R[31], val);
/* UniCore-F64 single load/store I_offset */
static void do_ucf64_ldst_i(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
int offset;
TCGv tmp;
TCGv addr;
/* UniCore-F64 load/store multiple words */
static void do_ucf64_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
unsigned int i;
int j, n, freg;
TCGv tmp;
/* UniCore-F64 mrc/mcr */
static void do_ucf64_trans(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
TCGv tmp;
if ((insn & 0xfe0003ff) == 0xe2000000) {
/* UniCore-F64 convert instructions */
static void do_ucf64_fcvt(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
+
if (UCOP_UCF64_FMT == 3) {
ILLEGAL;
}
/* UniCore-F64 compare instructions */
static void do_ucf64_fcmp(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
+
if (UCOP_SET(25)) {
ILLEGAL;
}
/* UniCore-F64 data processing */
static void do_ucf64_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
+
if (UCOP_UCF64_FMT == 3) {
ILLEGAL;
}
/* Disassemble an F64 instruction */
static void disas_ucf64_insn(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
+
if (!UCOP_SET(29)) {
if (UCOP_SET(26)) {
do_ucf64_ldst_m(env, s, insn);
if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
tcg_gen_goto_tb(n);
gen_set_pc_im(dest);
- tcg_gen_exit_tb((tcg_target_long)tb + n);
+ tcg_gen_exit_tb((uintptr_t)tb + n);
} else {
gen_set_pc_im(dest);
tcg_gen_exit_tb(0);
}
}
-static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
-{
- if (x) {
- tcg_gen_sari_i32(t0, t0, 16);
- } else {
- gen_sxth(t0);
- }
- if (y) {
- tcg_gen_sari_i32(t1, t1, 16);
- } else {
- gen_sxth(t1);
- }
- tcg_gen_mul_i32(t0, t0, t1);
-}
-
/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
static int gen_set_psr(DisasContext *s, uint32_t mask, int bsr, TCGv t0)
{
static void disas_coproc_insn(CPUUniCore32State *env, DisasContext *s,
uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
+
switch (UCOP_CPNUM) {
#ifndef CONFIG_USER_ONLY
case 0:
break;
default:
/* Unknown coprocessor. */
- cpu_abort(env, "Unknown coprocessor!");
+ cpu_abort(CPU(cpu), "Unknown coprocessor!");
}
}
-
-/* Store a 64-bit value to a register pair. Clobbers val. */
-static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
-{
- TCGv tmp;
- tmp = new_tmp();
- tcg_gen_trunc_i64_i32(tmp, val);
- store_reg(s, rlow, tmp);
- tmp = new_tmp();
- tcg_gen_shri_i64(val, val, 32);
- tcg_gen_trunc_i64_i32(tmp, val);
- store_reg(s, rhigh, tmp);
-}
-
-/* load and add a 64-bit value from a register pair. */
-static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
-{
- TCGv_i64 tmp;
- TCGv tmpl;
- TCGv tmph;
-
- /* Load 64-bit value rd:rn. */
- tmpl = load_reg(s, rlow);
- tmph = load_reg(s, rhigh);
- tmp = tcg_temp_new_i64();
- tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
- dead_tmp(tmpl);
- dead_tmp(tmph);
- tcg_gen_add_i64(val, val, tmp);
- tcg_temp_free_i64(tmp);
-}
-
/* data processing instructions */
static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
TCGv tmp;
TCGv tmp2;
int logic_cc;
/* multiply */
static void do_mult(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
- TCGv tmp;
- TCGv tmp2;
- TCGv_i64 tmp64;
+ TCGv tmp, tmp2, tmp3, tmp4;
if (UCOP_SET(27)) {
/* 64 bit mul */
tmp = load_reg(s, UCOP_REG_M);
tmp2 = load_reg(s, UCOP_REG_N);
if (UCOP_SET(26)) {
- tmp64 = gen_muls_i64_i32(tmp, tmp2);
+ tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
} else {
- tmp64 = gen_mulu_i64_i32(tmp, tmp2);
+ tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
}
if (UCOP_SET(25)) { /* mult accumulate */
- gen_addq(s, tmp64, UCOP_REG_LO, UCOP_REG_HI);
- }
- gen_storeq_reg(s, UCOP_REG_LO, UCOP_REG_HI, tmp64);
- tcg_temp_free_i64(tmp64);
+ tmp3 = load_reg(s, UCOP_REG_LO);
+ tmp4 = load_reg(s, UCOP_REG_HI);
+ tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, tmp3, tmp4);
+ dead_tmp(tmp3);
+ dead_tmp(tmp4);
+ }
+ store_reg(s, UCOP_REG_LO, tmp);
+ store_reg(s, UCOP_REG_HI, tmp2);
} else {
/* 32 bit mul */
tmp = load_reg(s, UCOP_REG_M);
/* miscellaneous instructions */
static void do_misc(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
unsigned int val;
TCGv tmp;
/* SWP instruction */
static void do_swap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
TCGv addr;
TCGv tmp;
TCGv tmp2;
/* load/store hw/sb */
static void do_ldst_hwsb(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
TCGv addr;
TCGv tmp;
/* load/store multiple words */
static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
unsigned int val, i, mmu_idx;
int j, n, reg, user, loaded_base;
TCGv tmp;
/* branch (and link) */
static void do_branch(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
unsigned int val;
int32_t offset;
TCGv tmp;
static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
unsigned int insn;
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
basic block 'tb'. If search_pc is TRUE, also generate PC
information for each intermediate instruction. */
-static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
- TranslationBlock *tb, int search_pc)
+static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
+ TranslationBlock *tb, bool search_pc)
{
+ CPUState *cs = CPU(cpu);
+ CPUUniCore32State *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
CPUBreakpoint *bp;
- uint16_t *gen_opc_end;
int j, lj;
target_ulong pc_start;
uint32_t next_page_start;
dc->tb = tb;
- gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
-
dc->is_jmp = DISAS_NEXT;
dc->pc = pc_start;
- dc->singlestep_enabled = env->singlestep_enabled;
+ dc->singlestep_enabled = cs->singlestep_enabled;
dc->condjmp = 0;
cpu_F0s = tcg_temp_new_i32();
cpu_F1s = tcg_temp_new_i32();
}
#endif
- gen_icount_start();
+ gen_tb_start(tb);
do {
- if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
- QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+ if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+ QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
gen_set_pc_im(dc->pc);
gen_exception(EXCP_DEBUG);
invalidate this TB. */
dc->pc += 2; /* FIXME */
goto done_generating;
- break;
}
}
}
if (search_pc) {
- j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
+ j = tcg_op_buf_count();
if (lj < j) {
lj++;
while (lj < j) {
* Also stop translation when a page boundary is reached. This
* ensures prefetch aborts occur at the right place. */
num_insns++;
- } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
- !env->singlestep_enabled &&
+ } while (!dc->is_jmp && !tcg_op_buf_full() &&
+ !cs->singlestep_enabled &&
!singlestep &&
dc->pc < next_page_start &&
num_insns < max_insns);
if (dc->condjmp) {
/* FIXME: This can theoretically happen with self-modifying
code. */
- cpu_abort(env, "IO on conditional branch instruction");
+ cpu_abort(cs, "IO on conditional branch instruction");
}
gen_io_end();
}
/* At this stage dc->condjmp will only be set when the skipped
instruction was a conditional branch or trap, and the PC has
already been written. */
- if (unlikely(env->singlestep_enabled)) {
+ if (unlikely(cs->singlestep_enabled)) {
/* Make sure the pc is updated, and raise a debug exception. */
if (dc->condjmp) {
if (dc->is_jmp == DISAS_SYSCALL) {
}
done_generating:
- gen_icount_end(tb, num_insns);
- *tcg_ctx.gen_opc_ptr = INDEX_op_end;
+ gen_tb_end(tb, num_insns);
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
}
#endif
if (search_pc) {
- j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
+ j = tcg_op_buf_count();
lj++;
while (lj <= j) {
tcg_ctx.gen_opc_instr_start[lj++] = 0;
void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
{
- gen_intermediate_code_internal(env, tb, 0);
+ gen_intermediate_code_internal(uc32_env_get_cpu(env), tb, false);
}
void gen_intermediate_code_pc(CPUUniCore32State *env, TranslationBlock *tb)
{
- gen_intermediate_code_internal(env, tb, 1);
+ gen_intermediate_code_internal(uc32_env_get_cpu(env), tb, true);
}
static const char *cpu_mode_names[16] = {
#define cpu_dump_state_ucf64(env, file, pr, flags) do { } while (0)
#endif
-void cpu_dump_state(CPUUniCore32State *env, FILE *f,
- fprintf_function cpu_fprintf, int flags)
+void uc32_cpu_dump_state(CPUState *cs, FILE *f,
+ fprintf_function cpu_fprintf, int flags)
{
+ UniCore32CPU *cpu = UNICORE32_CPU(cs);
+ CPUUniCore32State *env = &cpu->env;
int i;
uint32_t psr;