#include <inttypes.h>
#include "cpu.h"
-#include "disas.h"
-#include "helper.h"
+#include "disas/disas.h"
+#include "exec/helper-proto.h"
#include "tcg-op.h"
+#include "exec/cpu_ldst.h"
+
+#include "exec/helper-gen.h"
+
+#include "trace-tcg.h"
-#define GEN_HELPER 1
-#include "helper.h"
#define DEBUG_DISAS
static target_ulong gen_opc_npc[OPC_BUF_SIZE];
static target_ulong gen_opc_jump_pc[2];
-#include "gen-icount.h"
+#include "exec/gen-icount.h"
typedef struct DisasContext {
target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */
tcg_gen_goto_tb(tb_num);
tcg_gen_movi_tl(cpu_pc, pc);
tcg_gen_movi_tl(cpu_npc, npc);
- tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
+ tcg_gen_exit_tb((uintptr_t)tb + tb_num);
} else {
/* jump to another page: currently not optimized */
tcg_gen_movi_tl(cpu_pc, pc);
case CC_OP_ADD:
case CC_OP_TADD:
case CC_OP_TADDTV:
-#if TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 32
- {
- /* For 32-bit hosts, we can re-use the host's hardware carry
- generation by using an ADD2 opcode. We discard the low
- part of the output. Ideally we'd combine this operation
- with the add that generated the carry in the first place. */
- TCGv dst_low = tcg_temp_new();
- tcg_gen_op6_i32(INDEX_op_add2_i32, dst_low, dst,
- cpu_cc_src, src1, cpu_cc_src2, src2);
- tcg_temp_free(dst_low);
+ if (TARGET_LONG_BITS == 32) {
+ /* We can re-use the host's hardware carry generation by using
+ an ADD2 opcode. We discard the low part of the output.
+ Ideally we'd combine this operation with the add that
+ generated the carry in the first place. */
+ carry = tcg_temp_new();
+ tcg_gen_add2_tl(carry, dst, cpu_cc_src, src1, cpu_cc_src2, src2);
+ tcg_temp_free(carry);
goto add_done;
}
-#endif
carry_32 = gen_add32_carry32();
break;
tcg_temp_free(carry);
#endif
-#if TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 32
add_done:
-#endif
if (update_cc) {
tcg_gen_mov_tl(cpu_cc_src, src1);
tcg_gen_mov_tl(cpu_cc_src2, src2);
case CC_OP_SUB:
case CC_OP_TSUB:
case CC_OP_TSUBTV:
-#if TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 32
- {
- /* For 32-bit hosts, we can re-use the host's hardware carry
- generation by using a SUB2 opcode. We discard the low
- part of the output. Ideally we'd combine this operation
- with the add that generated the carry in the first place. */
- TCGv dst_low = tcg_temp_new();
- tcg_gen_op6_i32(INDEX_op_sub2_i32, dst_low, dst,
- cpu_cc_src, src1, cpu_cc_src2, src2);
- tcg_temp_free(dst_low);
+ if (TARGET_LONG_BITS == 32) {
+ /* We can re-use the host's hardware carry generation by using
+ a SUB2 opcode. We discard the low part of the output.
+ Ideally we'd combine this operation with the add that
+ generated the carry in the first place. */
+ carry = tcg_temp_new();
+ tcg_gen_sub2_tl(carry, dst, cpu_cc_src, src1, cpu_cc_src2, src2);
+ tcg_temp_free(carry);
goto sub_done;
}
-#endif
carry_32 = gen_sub32_carry32();
break;
tcg_temp_free(carry);
#endif
-#if TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 32
sub_done:
-#endif
if (update_cc) {
tcg_gen_mov_tl(cpu_cc_src, src1);
tcg_gen_mov_tl(cpu_cc_src2, src2);
static inline void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
{
- TCGv_i32 r_src1, r_src2;
- TCGv_i64 r_temp, r_temp2;
-
- r_src1 = tcg_temp_new_i32();
- r_src2 = tcg_temp_new_i32();
-
- tcg_gen_trunc_tl_i32(r_src1, src1);
- tcg_gen_trunc_tl_i32(r_src2, src2);
-
- r_temp = tcg_temp_new_i64();
- r_temp2 = tcg_temp_new_i64();
-
+#if TARGET_LONG_BITS == 32
if (sign_ext) {
- tcg_gen_ext_i32_i64(r_temp, r_src2);
- tcg_gen_ext_i32_i64(r_temp2, r_src1);
+ tcg_gen_muls2_tl(dst, cpu_y, src1, src2);
} else {
- tcg_gen_extu_i32_i64(r_temp, r_src2);
- tcg_gen_extu_i32_i64(r_temp2, r_src1);
+ tcg_gen_mulu2_tl(dst, cpu_y, src1, src2);
}
+#else
+ TCGv t0 = tcg_temp_new_i64();
+ TCGv t1 = tcg_temp_new_i64();
- tcg_gen_mul_i64(r_temp2, r_temp, r_temp2);
-
- tcg_gen_shri_i64(r_temp, r_temp2, 32);
- tcg_gen_trunc_i64_tl(cpu_y, r_temp);
- tcg_temp_free_i64(r_temp);
- tcg_gen_andi_tl(cpu_y, cpu_y, 0xffffffff);
-
- tcg_gen_trunc_i64_tl(dst, r_temp2);
+ if (sign_ext) {
+ tcg_gen_ext32s_i64(t0, src1);
+ tcg_gen_ext32s_i64(t1, src2);
+ } else {
+ tcg_gen_ext32u_i64(t0, src1);
+ tcg_gen_ext32u_i64(t1, src2);
+ }
- tcg_temp_free_i64(r_temp2);
+ tcg_gen_mul_i64(dst, t0, t1);
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
- tcg_temp_free_i32(r_src1);
- tcg_temp_free_i32(r_src2);
+ tcg_gen_shri_i64(cpu_y, dst, 32);
+#endif
}
static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
tcg_temp_free_i64(t64);
}
-static inline void gen_cas_asi(DisasContext *dc, TCGv addr,
- TCGv val2, int insn, int rd)
-{
- TCGv val1 = gen_load_gpr(dc, rd);
- TCGv dst = gen_dest_gpr(dc, rd);
- TCGv_i32 r_asi = gen_get_asi(insn, addr);
-
- gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi);
- tcg_temp_free_i32(r_asi);
- gen_store_gpr(dc, rd, dst);
-}
-
static inline void gen_casx_asi(DisasContext *dc, TCGv addr,
TCGv val2, int insn, int rd)
{
#endif
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
+static inline void gen_cas_asi(DisasContext *dc, TCGv addr,
+ TCGv val2, int insn, int rd)
+{
+ TCGv val1 = gen_load_gpr(dc, rd);
+ TCGv dst = gen_dest_gpr(dc, rd);
+#ifdef TARGET_SPARC64
+ TCGv_i32 r_asi = gen_get_asi(insn, addr);
+#else
+ TCGv_i32 r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
+#endif
+
+ gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi);
+ tcg_temp_free_i32(r_asi);
+ gen_store_gpr(dc, rd, dst);
+}
+
static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn)
{
TCGv_i64 r_val;
in the SPARCv8
manual, nop on the
microSPARC II */
+ if ((rd == 0x13) && (dc->def->features &
+ CPU_FEATURE_POWERDOWN)) {
+ /* LEON3 power-down */
+ save_state(dc);
+ gen_helper_power_down(cpu_env);
+ }
break;
#else
case 0x2: /* V9 wrccr */
}
gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
break;
- case 0x3c: /* V9 casa */
- rs2 = GET_FIELD(insn, 27, 31);
- cpu_src2 = gen_load_gpr(dc, rs2);
- gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd);
- break;
case 0x3e: /* V9 casxa */
rs2 = GET_FIELD(insn, 27, 31);
cpu_src2 = gen_load_gpr(dc, rs2);
case 0x36: /* stdcq */
case 0x37: /* stdc */
goto ncp_insn;
+#endif
+#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
+ case 0x3c: /* V9 or LEON3 casa */
+#ifndef TARGET_SPARC64
+ CHECK_IU_FEATURE(dc, CASA);
+ if (IS_IMM) {
+ goto illegal_insn;
+ }
+ if (!supervisor(dc)) {
+ goto priv_insn;
+ }
+#endif
+ rs2 = GET_FIELD(insn, 27, 31);
+ cpu_src2 = gen_load_gpr(dc, rs2);
+ gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd);
+ break;
#endif
default:
goto illegal_insn;
}
}
-static inline void gen_intermediate_code_internal(TranslationBlock * tb,
- int spc, CPUSPARCState *env)
+static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
+ TranslationBlock *tb,
+ bool spc)
{
+ CPUState *cs = CPU(cpu);
+ CPUSPARCState *env = &cpu->env;
target_ulong pc_start, last_pc;
uint16_t *gen_opc_end;
DisasContext dc1, *dc = &dc1;
dc->def = env->def;
dc->fpu_enabled = tb_fpu_enabled(tb->flags);
dc->address_mask_32bit = tb_am_enabled(tb->flags);
- dc->singlestep = (env->singlestep_enabled || singlestep);
+ dc->singlestep = (cs->singlestep_enabled || singlestep);
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0)
max_insns = CF_COUNT_MASK;
- gen_icount_start();
+ gen_tb_start();
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) {
if (dc->pc != pc_start)
save_state(dc);
tcg_gen_exit_tb(0);
}
}
- gen_icount_end(tb, num_insns);
+ gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (spc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
{
- gen_intermediate_code_internal(tb, 0, env);
+ gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, false);
}
void gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
{
- gen_intermediate_code_internal(tb, 1, env);
+ gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, true);
}
void gen_intermediate_code_init(CPUSPARCState *env)
offsetof(CPUSPARCState, fpr[i]),
fregnames[i]);
}
-
- /* register helpers */
-
-#define GEN_HELPER 2
-#include "helper.h"
}
}