diff options
author | blueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-02-24 14:10:06 +0000 |
---|---|---|
committer | blueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-02-24 14:10:06 +0000 |
commit | 1a2fb1c0093c9ac1bceec8b5cbe550c478f2e7b3 (patch) | |
tree | 0681ab72863fcfbe4a32db5224335c36a969c259 | |
parent | f8422f52fd633bb33e83e686e29c158bde4a3623 (diff) | |
download | qemu-1a2fb1c0093c9ac1bceec8b5cbe550c478f2e7b3.tar.gz qemu-1a2fb1c0093c9ac1bceec8b5cbe550c478f2e7b3.tar.bz2 qemu-1a2fb1c0093c9ac1bceec8b5cbe550c478f2e7b3.zip |
Modify Sparc32/64 to use TCG
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3989 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | target-sparc/exec.h | 16 | ||||
-rw-r--r-- | target-sparc/helper.h | 32 | ||||
-rw-r--r-- | target-sparc/op.c | 553 | ||||
-rw-r--r-- | target-sparc/op_helper.c | 598 | ||||
-rw-r--r-- | target-sparc/op_mem.h | 73 | ||||
-rw-r--r-- | target-sparc/op_template.h | 48 | ||||
-rw-r--r-- | target-sparc/translate.c | 1109 |
7 files changed, 878 insertions, 1551 deletions
diff --git a/target-sparc/exec.h b/target-sparc/exec.h index 54c824ee87..b9fffdc9c3 100644 --- a/target-sparc/exec.h +++ b/target-sparc/exec.h @@ -52,12 +52,6 @@ register uint32_t T2 asm(AREG3); void cpu_lock(void); void cpu_unlock(void); void cpu_loop_exit(void); -void helper_flush(target_ulong addr); -void helper_ld_asi(int asi, int size, int sign); -void helper_st_asi(int asi, int size); -void helper_ldf_asi(int asi, int size, int rd); -void helper_stf_asi(int asi, int size, int rd); -void helper_rett(void); void helper_ldfsr(void); void set_cwp(int new_cwp); void do_fitos(void); @@ -101,23 +95,13 @@ void do_fcmpeq_fcc1(void); void do_fcmpeq_fcc2(void); void do_fcmpeq_fcc3(void); #endif -void do_popc(); -void do_wrpstate(); -void do_done(); -void do_retry(); #endif -void do_ldd_kernel(target_ulong addr); -void do_ldd_user(target_ulong addr); -void do_ldd_raw(target_ulong addr); void do_interrupt(int intno); void raise_exception(int tt); void check_ieee_exceptions(); void memcpy32(target_ulong *dst, const target_ulong *src); target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev); void dump_mmu(CPUState *env); -void helper_debug(); -void do_wrpsr(); -void do_rdpsr(); /* XXX: move that to a generic header */ #if !defined(CONFIG_USER_ONLY) diff --git a/target-sparc/helper.h b/target-sparc/helper.h new file mode 100644 index 0000000000..28a0d6c000 --- /dev/null +++ b/target-sparc/helper.h @@ -0,0 +1,32 @@ +#define TCG_HELPER_PROTO + +#ifndef TARGET_SPARC64 +void TCG_HELPER_PROTO helper_rett(void); +void TCG_HELPER_PROTO helper_wrpsr(target_ulong new_psr); +target_ulong TCG_HELPER_PROTO helper_rdpsr(void); +#else +void TCG_HELPER_PROTO helper_wrpstate(target_ulong new_state); +void TCG_HELPER_PROTO helper_done(void); +void TCG_HELPER_PROTO helper_retry(void); +target_ulong TCG_HELPER_PROTO helper_popc(target_ulong val); +void TCG_HELPER_PROTO helper_ldf_asi(target_ulong addr, int asi, int size, + int rd); +void TCG_HELPER_PROTO helper_stf_asi(target_ulong addr, int asi, int size, + int rd); +target_ulong TCG_HELPER_PROTO +helper_cas_asi(target_ulong addr, target_ulong val1, + target_ulong val2, uint32_t asi); +target_ulong TCG_HELPER_PROTO +helper_casx_asi(target_ulong addr, target_ulong val1, + target_ulong val2, uint32_t asi); +#endif +void TCG_HELPER_PROTO helper_trap(target_ulong nb_trap); +void TCG_HELPER_PROTO helper_trapcc(target_ulong nb_trap, + target_ulong do_trap); +void TCG_HELPER_PROTO helper_debug(void); +void TCG_HELPER_PROTO helper_flush(target_ulong addr); +uint64_t TCG_HELPER_PROTO helper_pack64(target_ulong high, target_ulong low); +uint64_t TCG_HELPER_PROTO helper_ld_asi(target_ulong addr, int asi, + int size, int sign); +void TCG_HELPER_PROTO helper_st_asi(target_ulong addr, uint64_t val, int asi, + int size); diff --git a/target-sparc/op.c b/target-sparc/op.c index 1b5b21b760..ee5b08c021 100644 --- a/target-sparc/op.c +++ b/target-sparc/op.c @@ -19,104 +19,7 @@ */ #include "exec.h" - - /*XXX*/ -#define REGNAME g0 -#define REG (env->gregs[0]) -#include "op_template.h" -#define REGNAME g1 -#define REG (env->gregs[1]) -#include "op_template.h" -#define REGNAME g2 -#define REG (env->gregs[2]) -#include "op_template.h" -#define REGNAME g3 -#define REG (env->gregs[3]) -#include "op_template.h" -#define REGNAME g4 -#define REG (env->gregs[4]) -#include "op_template.h" -#define REGNAME g5 -#define REG (env->gregs[5]) -#include "op_template.h" -#define REGNAME g6 -#define REG (env->gregs[6]) -#include "op_template.h" -#define REGNAME g7 -#define REG (env->gregs[7]) -#include "op_template.h" -#define REGNAME i0 -#define REG (REGWPTR[16]) -#include "op_template.h" -#define REGNAME i1 -#define REG (REGWPTR[17]) -#include "op_template.h" -#define REGNAME i2 -#define REG (REGWPTR[18]) -#include "op_template.h" -#define REGNAME i3 -#define REG (REGWPTR[19]) -#include "op_template.h" -#define REGNAME i4 -#define REG (REGWPTR[20]) -#include "op_template.h" -#define REGNAME i5 -#define REG (REGWPTR[21]) -#include "op_template.h" -#define REGNAME i6 -#define REG (REGWPTR[22]) -#include "op_template.h" -#define REGNAME i7 -#define REG (REGWPTR[23]) -#include "op_template.h" -#define REGNAME l0 -#define REG (REGWPTR[8]) -#include "op_template.h" -#define REGNAME l1 -#define REG (REGWPTR[9]) -#include "op_template.h" -#define REGNAME l2 -#define REG (REGWPTR[10]) -#include "op_template.h" -#define REGNAME l3 -#define REG (REGWPTR[11]) -#include "op_template.h" -#define REGNAME l4 -#define REG (REGWPTR[12]) -#include "op_template.h" -#define REGNAME l5 -#define REG (REGWPTR[13]) -#include "op_template.h" -#define REGNAME l6 -#define REG (REGWPTR[14]) -#include "op_template.h" -#define REGNAME l7 -#define REG (REGWPTR[15]) -#include "op_template.h" -#define REGNAME o0 -#define REG (REGWPTR[0]) -#include "op_template.h" -#define REGNAME o1 -#define REG (REGWPTR[1]) -#include "op_template.h" -#define REGNAME o2 -#define REG (REGWPTR[2]) -#include "op_template.h" -#define REGNAME o3 -#define REG (REGWPTR[3]) -#include "op_template.h" -#define REGNAME o4 -#define REG (REGWPTR[4]) -#include "op_template.h" -#define REGNAME o5 -#define REG (REGWPTR[5]) -#include "op_template.h" -#define REGNAME o6 -#define REG (REGWPTR[6]) -#include "op_template.h" -#define REGNAME o7 -#define REG (REGWPTR[7]) -#include "op_template.h" +#include "helper.h" #define REGNAME f0 #define REG (env->fpr[0]) @@ -267,106 +170,11 @@ #endif #ifdef TARGET_SPARC64 -#ifdef WORDS_BIGENDIAN -typedef union UREG64 { - struct { uint16_t v3, v2, v1, v0; } w; - struct { uint32_t v1, v0; } l; - uint64_t q; -} UREG64; -#else -typedef union UREG64 { - struct { uint16_t v0, v1, v2, v3; } w; - struct { uint32_t v0, v1; } l; - uint64_t q; -} UREG64; -#endif - -#define PARAMQ1 \ -({\ - UREG64 __p;\ - __p.l.v1 = PARAM1;\ - __p.l.v0 = PARAM2;\ - __p.q;\ -}) - -void OPPROTO op_movq_T0_im64(void) -{ - T0 = PARAMQ1; -} - -void OPPROTO op_movq_T1_im64(void) -{ - T1 = PARAMQ1; -} - #define XFLAG_SET(x) ((env->xcc&x)?1:0) - -#else -#define EIP (env->pc) #endif #define FLAG_SET(x) ((env->psr&x)?1:0) -void OPPROTO op_movl_T0_0(void) -{ - T0 = 0; -} - -void OPPROTO op_movl_T0_im(void) -{ - T0 = (uint32_t)PARAM1; -} - -void OPPROTO op_movl_T1_im(void) -{ - T1 = (uint32_t)PARAM1; -} - -void OPPROTO op_movl_T2_im(void) -{ - T2 = (uint32_t)PARAM1; -} - -void OPPROTO op_movl_T0_sim(void) -{ - T0 = (int32_t)PARAM1; -} - -void OPPROTO op_movl_T1_sim(void) -{ - T1 = (int32_t)PARAM1; -} - -void OPPROTO op_movl_T2_sim(void) -{ - T2 = (int32_t)PARAM1; -} - -void OPPROTO op_movl_T0_env(void) -{ - T0 = *(uint32_t *)((char *)env + PARAM1); -} - -void OPPROTO op_movl_env_T0(void) -{ - *(uint32_t *)((char *)env + PARAM1) = T0; -} - -void OPPROTO op_movtl_T0_env(void) -{ - T0 = *(target_ulong *)((char *)env + PARAM1); -} - -void OPPROTO op_movtl_env_T0(void) -{ - *(target_ulong *)((char *)env + PARAM1) = T0; -} - -void OPPROTO op_add_T1_T0(void) -{ - T0 += T1; -} - void OPPROTO op_add_T1_T0_cc(void) { target_ulong src1; @@ -565,11 +373,6 @@ void OPPROTO op_tadd_T1_T0_ccTV(void) FORCE_RET(); } -void OPPROTO op_sub_T1_T0(void) -{ - T0 -= T1; -} - void OPPROTO op_sub_T1_T0_cc(void) { target_ulong src1; @@ -765,21 +568,6 @@ void OPPROTO op_tsub_T1_T0_ccTV(void) FORCE_RET(); } -void OPPROTO op_and_T1_T0(void) -{ - T0 &= T1; -} - -void OPPROTO op_or_T1_T0(void) -{ - T0 |= T1; -} - -void OPPROTO op_xor_T1_T0(void) -{ - T0 ^= T1; -} - void OPPROTO op_andn_T1_T0(void) { T0 &= ~T1; @@ -921,12 +709,6 @@ void OPPROTO op_div_cc(void) } #ifdef TARGET_SPARC64 -void OPPROTO op_mulx_T1_T0(void) -{ - T0 *= T1; - FORCE_RET(); -} - void OPPROTO op_udivx_T1_T0(void) { if (T1 == 0) { @@ -972,48 +754,6 @@ void OPPROTO op_logic_T0_cc(void) FORCE_RET(); } -void OPPROTO op_sll(void) -{ - T0 <<= (T1 & 0x1f); -} - -#ifdef TARGET_SPARC64 -void OPPROTO op_sllx(void) -{ - T0 <<= (T1 & 0x3f); -} - -void OPPROTO op_srl(void) -{ - T0 = (T0 & 0xffffffff) >> (T1 & 0x1f); -} - -void OPPROTO op_srlx(void) -{ - T0 >>= (T1 & 0x3f); -} - -void OPPROTO op_sra(void) -{ - T0 = ((int32_t) (T0 & 0xffffffff)) >> (T1 & 0x1f); -} - -void OPPROTO op_srax(void) -{ - T0 = ((int64_t) T0) >> (T1 & 0x3f); -} -#else -void OPPROTO op_srl(void) -{ - T0 >>= (T1 & 0x1f); -} - -void OPPROTO op_sra(void) -{ - T0 = ((int32_t) T0) >> (T1 & 0x1f); -} -#endif - /* Load and store */ #define MEMSUFFIX _raw #include "op_mem.h" @@ -1042,32 +782,6 @@ void OPPROTO op_stfsr(void) } #ifndef TARGET_SPARC64 -void OPPROTO op_rdpsr(void) -{ - do_rdpsr(); -} - -void OPPROTO op_wrpsr(void) -{ - do_wrpsr(); - FORCE_RET(); -} - -void OPPROTO op_wrwim(void) -{ -#if NWINDOWS == 32 - env->wim = T0; -#else - env->wim = T0 & ((1 << NWINDOWS) - 1); -#endif -} - -void OPPROTO op_rett(void) -{ - helper_rett(); - FORCE_RET(); -} - /* XXX: use another pointer for %iN registers to avoid slow wrapping handling ? */ void OPPROTO op_save(void) @@ -1178,16 +892,6 @@ void OPPROTO op_wrtt(void) env->tt[env->tl] = T0; } -void OPPROTO op_rdpstate(void) -{ - T0 = env->pstate; -} - -void OPPROTO op_wrpstate(void) -{ - do_wrpstate(); -} - // CWP handling is reversed in V9, but we still use the V8 register // order. void OPPROTO op_rdcwp(void) @@ -1247,22 +951,6 @@ void OPPROTO op_exception(void) FORCE_RET(); } -void OPPROTO op_trap_T0(void) -{ - env->exception_index = TT_TRAP + (T0 & 0x7f); - cpu_loop_exit(); - FORCE_RET(); -} - -void OPPROTO op_trapcc_T0(void) -{ - if (T2) { - env->exception_index = TT_TRAP + (T0 & 0x7f); - cpu_loop_exit(); - } - FORCE_RET(); -} - void OPPROTO op_fpexception_im(void) { env->exception_index = TT_FP_EXCP; @@ -1272,11 +960,6 @@ void OPPROTO op_fpexception_im(void) FORCE_RET(); } -void OPPROTO op_debug(void) -{ - helper_debug(); -} - void OPPROTO op_eval_ba(void) { T2 = 1; @@ -1499,33 +1182,8 @@ void OPPROTO op_eval_brgez(void) { T2 = ((int64_t)T0 >= 0); } - -void OPPROTO op_jmp_im64(void) -{ - env->pc = PARAMQ1; -} - -void OPPROTO op_movq_npc_im64(void) -{ - env->npc = PARAMQ1; -} #endif -void OPPROTO op_jmp_im(void) -{ - env->pc = (uint32_t)PARAM1; -} - -void OPPROTO op_movl_npc_im(void) -{ - env->npc = (uint32_t)PARAM1; -} - -void OPPROTO op_movl_npc_T0(void) -{ - env->npc = T0; -} - void OPPROTO op_mov_pc_npc(void) { env->pc = env->npc; @@ -1556,11 +1214,6 @@ void OPPROTO op_jz_T2_label(void) FORCE_RET(); } -void OPPROTO op_flush_T0(void) -{ - helper_flush(T0); -} - void OPPROTO op_clear_ieee_excp_and_FTT(void) { env->fsr &= ~(FSR_FTT_MASK | FSR_CEXC_MASK);; @@ -1993,210 +1646,6 @@ void OPPROTO op_restored(void) env->otherwin--; FORCE_RET(); } - -void OPPROTO op_popc(void) -{ - do_popc(); -} - -void OPPROTO op_done(void) -{ - do_done(); -} - -void OPPROTO op_retry(void) -{ - do_retry(); -} - -void OPPROTO op_sir(void) -{ - T0 = 0; // XXX -} - -void OPPROTO op_ld_asi_reg() -{ - T0 += PARAM1; - helper_ld_asi(env->asi, PARAM2, PARAM3); -} - -void OPPROTO op_st_asi_reg() -{ - T0 += PARAM1; - helper_st_asi(env->asi, PARAM2); -} - -void OPPROTO op_ldf_asi_reg() -{ - T0 += PARAM1; - helper_ldf_asi(env->asi, PARAM2, PARAM3); -} - -void OPPROTO op_stf_asi_reg() -{ - T0 += PARAM1; - helper_stf_asi(env->asi, PARAM2, PARAM3); -} - -void OPPROTO op_ldf_asi() -{ - helper_ldf_asi(PARAM1, PARAM2, PARAM3); -} - -void OPPROTO op_stf_asi() -{ - helper_stf_asi(PARAM1, PARAM2, PARAM3); -} - -void OPPROTO op_ldstub_asi_reg() /* XXX: should be atomically */ -{ - target_ulong tmp; - - T0 += PARAM1; - helper_ld_asi(env->asi, 1, 0); - tmp = T1; - T1 = 0xff; - helper_st_asi(env->asi, 1); - T1 = tmp; -} - -void OPPROTO op_swap_asi_reg() /* XXX: should be atomically */ -{ - target_ulong tmp1, tmp2; - - T0 += PARAM1; - tmp1 = T1; - helper_ld_asi(env->asi, 4, 0); - tmp2 = T1; - T1 = tmp1; - helper_st_asi(env->asi, 4); - T1 = tmp2; -} - -void OPPROTO op_ldda_asi() -{ - helper_ld_asi(PARAM1, 8, 0); - T0 = T1 & 0xffffffffUL; - T1 >>= 32; -} - -void OPPROTO op_ldda_asi_reg() -{ - T0 += PARAM1; - helper_ld_asi(env->asi, 8, 0); - T0 = T1 & 0xffffffffUL; - T1 >>= 32; -} - -void OPPROTO op_stda_asi() -{ - T1 <<= 32; - T1 += T2 & 0xffffffffUL; - helper_st_asi(PARAM1, 8); -} - -void OPPROTO op_stda_asi_reg() -{ - T0 += PARAM1; - T1 <<= 32; - T1 += T2 & 0xffffffffUL; - helper_st_asi(env->asi, 8); -} - -void OPPROTO op_cas_asi() /* XXX: should be atomically */ -{ - target_ulong tmp; - - tmp = T1 & 0xffffffffUL; - helper_ld_asi(PARAM1, 4, 0); - if (tmp == T1) { - tmp = T1; - T1 = T2 & 0xffffffffUL; - helper_st_asi(PARAM1, 4); - T1 = tmp; - } - T1 &= 0xffffffffUL; -} - -void OPPROTO op_cas_asi_reg() /* XXX: should be atomically */ -{ - target_ulong tmp; - - T0 += PARAM1; - tmp = T1 & 0xffffffffUL; - helper_ld_asi(env->asi, 4, 0); - if (tmp == T1) { - tmp = T1; - T1 = T2 & 0xffffffffUL; - helper_st_asi(env->asi, 4); - T1 = tmp; - } - T1 &= 0xffffffffUL; -} - -void OPPROTO op_casx_asi() /* XXX: should be atomically */ -{ - target_ulong tmp; - - tmp = T1; - helper_ld_asi(PARAM1, 8, 0); - if (tmp == T1) { - tmp = T1; - T1 = T2; - helper_st_asi(PARAM1, 8); - T1 = tmp; - } -} - -void OPPROTO op_casx_asi_reg() /* XXX: should be atomically */ -{ - target_ulong tmp; - - T0 += PARAM1; - tmp = T1; - helper_ld_asi(env->asi, 8, 0); - if (tmp == T1) { - tmp = T1; - T1 = T2; - helper_st_asi(env->asi, 8); - T1 = tmp; - } -} -#endif - -#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) -void OPPROTO op_ld_asi() -{ - helper_ld_asi(PARAM1, PARAM2, PARAM3); -} - -void OPPROTO op_st_asi() -{ - helper_st_asi(PARAM1, PARAM2); -} - -void OPPROTO op_ldstub_asi() /* XXX: should be atomically */ -{ - target_ulong tmp; - - helper_ld_asi(PARAM1, 1, 0); - tmp = T1; - T1 = 0xff; - helper_st_asi(PARAM1, 1); - T1 = tmp; -} - -void OPPROTO op_swap_asi() /* XXX: should be atomically */ -{ - target_ulong tmp1, tmp2; - - tmp1 = T1; - helper_ld_asi(PARAM1, 4, 0); - tmp2 = T1; - T1 = tmp1; - helper_st_asi(PARAM1, 4); - T1 = tmp2; -} #endif #ifdef TARGET_SPARC64 diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 2f7e7abc72..f13a7b1d6e 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -1,5 +1,6 @@ #include "exec.h" #include "host-utils.h" +#include "helper.h" //#define DEBUG_PCALL //#define DEBUG_MMU @@ -35,35 +36,47 @@ void raise_exception(int tt) cpu_loop_exit(); } -void check_ieee_exceptions() +void helper_trap(target_ulong nb_trap) { - T0 = get_float_exception_flags(&env->fp_status); - if (T0) - { + env->exception_index = TT_TRAP + (nb_trap & 0x7f); + cpu_loop_exit(); +} + +void helper_trapcc(target_ulong nb_trap, target_ulong do_trap) +{ + if (do_trap) { + env->exception_index = TT_TRAP + (nb_trap & 0x7f); + cpu_loop_exit(); + } +} + +void check_ieee_exceptions(void) +{ + target_ulong status; + + status = get_float_exception_flags(&env->fp_status); + if (status) { /* Copy IEEE 754 flags into FSR */ - if (T0 & float_flag_invalid) + if (status & float_flag_invalid) env->fsr |= FSR_NVC; - if (T0 & float_flag_overflow) + if (status & float_flag_overflow) env->fsr |= FSR_OFC; - if (T0 & float_flag_underflow) + if (status & float_flag_underflow) env->fsr |= FSR_UFC; - if (T0 & float_flag_divbyzero) + if (status & float_flag_divbyzero) env->fsr |= FSR_DZC; - if (T0 & float_flag_inexact) + if (status & float_flag_inexact) env->fsr |= FSR_NXC; - if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) - { + if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) { /* Unmasked exception, generate a trap */ env->fsr |= FSR_FTT_IEEE_EXCP; raise_exception(TT_FP_EXCP); - } - else - { + } else { /* Accumulate exceptions */ env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5; } - } + } } #ifdef USE_INT_TO_FLOAT_HELPERS @@ -157,12 +170,14 @@ void do_fsqrtq(void) #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \ void glue(do_, name) (void) \ { \ + target_ulong new_fsr; \ + \ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \ case float_relation_unordered: \ - T0 = (FSR_FCC1 | FSR_FCC0) << FS; \ + new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \ if ((env->fsr & FSR_NVM) || TRAP) { \ - env->fsr |= T0; \ + env->fsr |= new_fsr; \ env->fsr |= FSR_NVC; \ env->fsr |= FSR_FTT_IEEE_EXCP; \ raise_exception(TT_FP_EXCP); \ @@ -171,16 +186,16 @@ void do_fsqrtq(void) } \ break; \ case float_relation_less: \ - T0 = FSR_FCC0 << FS; \ + new_fsr = FSR_FCC0 << FS; \ break; \ case float_relation_greater: \ - T0 = FSR_FCC1 << FS; \ + new_fsr = FSR_FCC1 << FS; \ break; \ default: \ - T0 = 0; \ + new_fsr = 0; \ break; \ } \ - env->fsr |= T0; \ + env->fsr |= new_fsr; \ } GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0); @@ -222,10 +237,7 @@ GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1); #endif #endif -#ifndef TARGET_SPARC64 -#ifndef CONFIG_USER_ONLY - -#ifdef DEBUG_MXCC +#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && defined(DEBUG_MXCC) static void dump_mxcc(CPUState *env) { printf("mxccdata: %016llx %016llx %016llx %016llx\n", @@ -237,74 +249,76 @@ static void dump_mxcc(CPUState *env) } #endif -#ifdef DEBUG_ASI -static void dump_asi(const char * txt, uint32_t addr, int asi, int size, - uint32_t r1, uint32_t r2) +#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \ + && defined(DEBUG_ASI) +static void dump_asi(const char *txt, target_ulong addr, int asi, int size, + uint64_t r1) { switch (size) { case 1: - DPRINTF_ASI("%s %08x asi 0x%02x = %02x\n", txt, addr, asi, r1 & 0xff); + DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt, + addr, asi, r1 & 0xff); break; case 2: - DPRINTF_ASI("%s %08x asi 0x%02x = %04x\n", txt, addr, asi, r1 & 0xffff); + DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt, + addr, asi, r1 & 0xffff); break; case 4: - DPRINTF_ASI("%s %08x asi 0x%02x = %08x\n", txt, addr, asi, r1); + DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt, + addr, asi, r1 & 0xffffffff); break; case 8: - DPRINTF_ASI("%s %08x asi 0x%02x = %016llx\n", txt, addr, asi, - r2 | ((uint64_t)r1 << 32)); + DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt, + addr, asi, r1); break; } } #endif -void helper_ld_asi(int asi, int size, int sign) +#ifndef TARGET_SPARC64 +#ifndef CONFIG_USER_ONLY +uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) { - uint32_t ret = 0; - uint64_t tmp; + uint64_t ret = 0; #if defined(DEBUG_MXCC) || defined(DEBUG_ASI) - uint32_t last_T0 = T0; + uint32_t last_addr = addr; #endif switch (asi) { case 2: /* SuperSparc MXCC registers */ - switch (T0) { + switch (addr) { case 0x01c00a00: /* MXCC control register */ - if (size == 8) { - ret = env->mxccregs[3] >> 32; - T0 = env->mxccregs[3]; - } else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + if (size == 8) + ret = env->mxccregs[3]; + else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00a04: /* MXCC control register */ if (size == 4) ret = env->mxccregs[3]; else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00c00: /* Module reset register */ if (size == 8) { - ret = env->mxccregs[5] >> 32; - T0 = env->mxccregs[5]; + ret = env->mxccregs[5]; // should we do something here? } else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00f00: /* MBus port address register */ - if (size == 8) { - ret = env->mxccregs[7] >> 32; - T0 = env->mxccregs[7]; - } else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + if (size == 8) + ret = env->mxccregs[7]; + else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; default: - DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size); break; } - DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x," - "T0 = %08x\n", asi, size, sign, last_T0, ret, T0); + DPRINTF_MXCC("asi = %d, size = %d, sign = %d, addr = %08x -> ret = %08x," + "addr = %08x\n", asi, size, sign, last_addr, ret, addr); #ifdef DEBUG_MXCC dump_mxcc(env); #endif @@ -313,19 +327,18 @@ void helper_ld_asi(int asi, int size, int sign) { int mmulev; - mmulev = (T0 >> 8) & 15; + mmulev = (addr >> 8) & 15; if (mmulev > 4) ret = 0; - else { - ret = mmu_probe(env, T0, mmulev); - //bswap32s(&ret); - } - DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret); + else + ret = mmu_probe(env, addr, mmulev); + DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n", + addr, mmulev, ret); } break; case 4: /* read MMU regs */ { - int reg = (T0 >> 8) & 0x1f; + int reg = (addr >> 8) & 0x1f; ret = env->mmuregs[reg]; if (reg == 3) /* Fault status cleared on read */ @@ -334,7 +347,7 @@ void helper_ld_asi(int asi, int size, int sign) ret = env->mmuregs[3]; else if (reg == 0x14) /* Fault address read */ ret = env->mmuregs[4]; - DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg, ret); + DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret); } break; case 5: // Turbosparc ITLB Diagnostic @@ -344,57 +357,51 @@ void helper_ld_asi(int asi, int size, int sign) case 9: /* Supervisor code access */ switch(size) { case 1: - ret = ldub_code(T0); + ret = ldub_code(addr); break; case 2: - ret = lduw_code(T0 & ~1); + ret = lduw_code(addr & ~1); break; default: case 4: - ret = ldl_code(T0 & ~3); + ret = ldl_code(addr & ~3); break; case 8: - tmp = ldq_code(T0 & ~7); - ret = tmp >> 32; - T0 = tmp; + ret = ldq_code(addr & ~7); break; } break; case 0xa: /* User data access */ switch(size) { case 1: - ret = ldub_user(T0); + ret = ldub_user(addr); break; case 2: - ret = lduw_user(T0 & ~1); + ret = lduw_user(addr & ~1); break; default: case 4: - ret = ldl_user(T0 & ~3); + ret = ldl_user(addr & ~3); break; case 8: - tmp = ldq_user(T0 & ~7); - ret = tmp >> 32; - T0 = tmp; + ret = ldq_user(addr & ~7); break; } break; case 0xb: /* Supervisor data access */ switch(size) { case 1: - ret = ldub_kernel(T0); + ret = ldub_kernel(addr); break; case 2: - ret = lduw_kernel(T0 & ~1); + ret = lduw_kernel(addr & ~1); break; default: case 4: - ret = ldl_kernel(T0 & ~3); + ret = ldl_kernel(addr & ~3); break; case 8: - tmp = ldq_kernel(T0 & ~7); - ret = tmp >> 32; - T0 = tmp; + ret = ldq_kernel(addr & ~7); break; } break; @@ -406,42 +413,38 @@ void helper_ld_asi(int asi, int size, int sign) case 0x20: /* MMU passthrough */ switch(size) { case 1: - ret = ldub_phys(T0); + ret = ldub_phys(addr); break; case 2: - ret = lduw_phys(T0 & ~1); + ret = lduw_phys(addr & ~1); break; default: case 4: - ret = ldl_phys(T0 & ~3); + ret = ldl_phys(addr & ~3); break; case 8: - tmp = ldq_phys(T0 & ~7); - ret = tmp >> 32; - T0 = tmp; + ret = ldq_phys(addr & ~7); break; } break; case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ switch(size) { case 1: - ret = ldub_phys((target_phys_addr_t)T0 + ret = ldub_phys((target_phys_addr_t)addr | ((target_phys_addr_t)(asi & 0xf) << 32)); break; case 2: - ret = lduw_phys((target_phys_addr_t)(T0 & ~1) + ret = lduw_phys((target_phys_addr_t)(addr & ~1) | ((target_phys_addr_t)(asi & 0xf) << 32)); break; default: case 4: - ret = ldl_phys((target_phys_addr_t)(T0 & ~3) + ret = ldl_phys((target_phys_addr_t)(addr & ~3) | ((target_phys_addr_t)(asi & 0xf) << 32)); break; case 8: - tmp = ldq_phys((target_phys_addr_t)(T0 & ~7) + ret = ldq_phys((target_phys_addr_t)(addr & ~7) | ((target_phys_addr_t)(asi & 0xf) << 32)); - ret = tmp >> 32; - T0 = tmp; break; } break; @@ -453,64 +456,65 @@ void helper_ld_asi(int asi, int size, int sign) break; case 8: /* User code access, XXX */ default: - do_unassigned_access(T0, 0, 0, asi); + do_unassigned_access(addr, 0, 0, asi); ret = 0; break; } if (sign) { switch(size) { case 1: - T1 = (int8_t) ret; + ret = (int8_t) ret; break; case 2: - T1 = (int16_t) ret; + ret = (int16_t) ret; + break; + case 4: + ret = (int32_t) ret; break; default: - T1 = ret; break; } } - else - T1 = ret; #ifdef DEBUG_ASI - dump_asi("read ", last_T0, asi, size, T1, T0); + dump_asi("read ", last_addr, asi, size, ret); #endif + return ret; } -void helper_st_asi(int asi, int size) +void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size) { switch(asi) { case 2: /* SuperSparc MXCC registers */ - switch (T0) { + switch (addr) { case 0x01c00000: /* MXCC stream data register 0 */ if (size == 8) - env->mxccdata[0] = ((uint64_t)T1 << 32) | T2; + env->mxccdata[0] = val; else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00008: /* MXCC stream data register 1 */ if (size == 8) - env->mxccdata[1] = ((uint64_t)T1 << 32) | T2; + env->mxccdata[1] = val; else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00010: /* MXCC stream data register 2 */ if (size == 8) - env->mxccdata[2] = ((uint64_t)T1 << 32) | T2; + env->mxccdata[2] = val; else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00018: /* MXCC stream data register 3 */ if (size == 8) - env->mxccdata[3] = ((uint64_t)T1 << 32) | T2; + env->mxccdata[3] = val; else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00100: /* MXCC stream source */ if (size == 8) - env->mxccregs[0] = ((uint64_t)T1 << 32) | T2; + env->mxccregs[0] = val; else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 0); env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 8); env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16); @@ -518,9 +522,9 @@ void helper_st_asi(int asi, int size) break; case 0x01c00200: /* MXCC stream destination */ if (size == 8) - env->mxccregs[1] = ((uint64_t)T1 << 32) | T2; + env->mxccregs[1] = val; else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0, env->mxccdata[0]); stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8, env->mxccdata[1]); stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]); @@ -528,34 +532,34 @@ void helper_st_asi(int asi, int size) break; case 0x01c00a00: /* MXCC control register */ if (size == 8) - env->mxccregs[3] = ((uint64_t)T1 << 32) | T2; + env->mxccregs[3] = val; else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00a04: /* MXCC control register */ if (size == 4) - env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | T1; + env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | val; else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00e00: /* MXCC error register */ // writing a 1 bit clears the error if (size == 8) - env->mxccregs[6] &= ~(((uint64_t)T1 << 32) | T2); + env->mxccregs[6] &= ~val; else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00f00: /* MBus port address register */ if (size == 8) - env->mxccregs[7] = ((uint64_t)T1 << 32) | T2; + env->mxccregs[7] = val; else - DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; default: - DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size); + DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size); break; } - DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi, size, T0, T1); + DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %08x\n", asi, size, addr, val); #ifdef DEBUG_MXCC dump_mxcc(env); #endif @@ -564,11 +568,11 @@ void helper_st_asi(int asi, int size) { int mmulev; - mmulev = (T0 >> 8) & 15; + mmulev = (addr >> 8) & 15; DPRINTF_MMU("mmu flush level %d\n", mmulev); switch (mmulev) { case 0: // flush page - tlb_flush_page(env, T0 & 0xfffff000); + tlb_flush_page(env, addr & 0xfffff000); break; case 1: // flush segment (256k) case 2: // flush region (16M) @@ -586,14 +590,14 @@ void helper_st_asi(int asi, int size) break; case 4: /* write MMU regs */ { - int reg = (T0 >> 8) & 0x1f; + int reg = (addr >> 8) & 0x1f; uint32_t oldreg; oldreg = env->mmuregs[reg]; switch(reg) { case 0: // Control Register env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) | - (T1 & 0x00ffffff); + (val & 0x00ffffff); // Mappings generated during no-fault mode or MMU // disabled mode are invalid in normal mode if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) != @@ -601,10 +605,10 @@ void helper_st_asi(int asi, int size) tlb_flush(env, 1); break; case 1: // Context Table Pointer Register - env->mmuregs[reg] = T1 & env->mmu_ctpr_mask; + env->mmuregs[reg] = val & env->mmu_ctpr_mask; break; case 2: // Context Register - env->mmuregs[reg] = T1 & env->mmu_cxr_mask; + env->mmuregs[reg] = val & env->mmu_cxr_mask; if (oldreg != env->mmuregs[reg]) { /* we flush when the MMU context changes because QEMU has no MMU context support */ @@ -615,16 +619,16 @@ void helper_st_asi(int asi, int size) case 4: // Synchronous Fault Address Register break; case 0x10: // TLB Replacement Control Register - env->mmuregs[reg] = T1 & env->mmu_trcr_mask; + env->mmuregs[reg] = val & env->mmu_trcr_mask; break; case 0x13: // Synchronous Fault Status Register with Read and Clear - env->mmuregs[3] = T1 & env->mmu_sfsr_mask; + env->mmuregs[3] = val & env->mmu_sfsr_mask; break; case 0x14: // Synchronous Fault Address Register - env->mmuregs[4] = T1; + env->mmuregs[4] = val; break; default: - env->mmuregs[reg] = T1; + env->mmuregs[reg] = val; break; } if (oldreg != env->mmuregs[reg]) { @@ -642,34 +646,34 @@ void helper_st_asi(int asi, int size) case 0xa: /* User data access */ switch(size) { case 1: - stb_user(T0, T1); + stb_user(addr, val); break; case 2: - stw_user(T0 & ~1, T1); + stw_user(addr & ~1, val); break; default: case 4: - stl_user(T0 & ~3, T1); + stl_user(addr & ~3, val); break; case 8: - stq_user(T0 & ~7, ((uint64_t)T1 << 32) | T2); + stq_user(addr & ~7, val); break; } break; case 0xb: /* Supervisor data access */ switch(size) { case 1: - stb_kernel(T0, T1); + stb_kernel(addr, val); break; case 2: - stw_kernel(T0 & ~1, T1); + stw_kernel(addr & ~1, val); break; default: case 4: - stl_kernel(T0 & ~3, T1); + stl_kernel(addr & ~3, val); break; case 8: - stq_kernel(T0 & ~7, ((uint64_t)T1 << 32) | T2); + stq_kernel(addr & ~7, val); break; } break; @@ -685,11 +689,11 @@ void helper_st_asi(int asi, int size) break; case 0x17: /* Block copy, sta access */ { - // value (T1) = src - // address (T0) = dst + // val = src + // addr = dst // copy 32 bytes unsigned int i; - uint32_t src = T1 & ~3, dst = T0 & ~3, temp; + uint32_t src = val & ~3, dst = addr & ~3, temp; for (i = 0; i < 32; i += 4, src += 4, dst += 4) { temp = ldl_kernel(src); @@ -699,14 +703,10 @@ void helper_st_asi(int asi, int size) break; case 0x1f: /* Block fill, stda access */ { - // value (T1, T2) - // address (T0) = dst - // fill 32 bytes + // addr = dst + // fill 32 bytes with val unsigned int i; - uint32_t dst = T0 & 7; - uint64_t val; - - val = (((uint64_t)T1) << 32) | T2; + uint32_t dst = addr & 7; for (i = 0; i < 32; i += 8, dst += 8) stq_kernel(dst, val); @@ -716,17 +716,17 @@ void helper_st_asi(int asi, int size) { switch(size) { case 1: - stb_phys(T0, T1); + stb_phys(addr, val); break; case 2: - stw_phys(T0 & ~1, T1); + stw_phys(addr & ~1, val); break; case 4: default: - stl_phys(T0 & ~3, T1); + stl_phys(addr & ~3, val); break; case 8: - stq_phys(T0 & ~7, ((uint64_t)T1 << 32) | T2); + stq_phys(addr & ~7, val); break; } } @@ -735,22 +735,21 @@ void helper_st_asi(int asi, int size) { switch(size) { case 1: - stb_phys((target_phys_addr_t)T0 - | ((target_phys_addr_t)(asi & 0xf) << 32), T1); + stb_phys((target_phys_addr_t)addr + | ((target_phys_addr_t)(asi & 0xf) << 32), val); break; case 2: - stw_phys((target_phys_addr_t)(T0 & ~1) - | ((target_phys_addr_t)(asi & 0xf) << 32), T1); + stw_phys((target_phys_addr_t)(addr & ~1) + | ((target_phys_addr_t)(asi & 0xf) << 32), val); break; case 4: default: - stl_phys((target_phys_addr_t)(T0 & ~3) - | ((target_phys_addr_t)(asi & 0xf) << 32), T1); + stl_phys((target_phys_addr_t)(addr & ~3) + | ((target_phys_addr_t)(asi & 0xf) << 32), val); break; case 8: - stq_phys((target_phys_addr_t)(T0 & ~7) - | ((target_phys_addr_t)(asi & 0xf) << 32), - ((uint64_t)T1 << 32) | T2); + stq_phys((target_phys_addr_t)(addr & ~7) + | ((target_phys_addr_t)(asi & 0xf) << 32), val); break; } } @@ -767,11 +766,11 @@ void helper_st_asi(int asi, int size) case 8: /* User code access, XXX */ case 9: /* Supervisor code access, XXX */ default: - do_unassigned_access(T0, 1, 0, asi); + do_unassigned_access(addr, 1, 0, asi); break; } #ifdef DEBUG_ASI - dump_asi("write", T0, asi, size, T1, T2); + dump_asi("write", addr, asi, size, val); #endif } @@ -779,9 +778,12 @@ void helper_st_asi(int asi, int size) #else /* TARGET_SPARC64 */ #ifdef CONFIG_USER_ONLY -void helper_ld_asi(int asi, int size, int sign) +uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) { uint64_t ret = 0; +#if defined(DEBUG_ASI) + target_ulong last_addr = addr; +#endif if (asi < 0x80) raise_exception(TT_PRIV_ACT); @@ -794,17 +796,17 @@ void helper_ld_asi(int asi, int size, int sign) { switch(size) { case 1: - ret = ldub_raw(T0); + ret = ldub_raw(addr); break; case 2: - ret = lduw_raw(T0 & ~1); + ret = lduw_raw(addr & ~1); break; case 4: - ret = ldl_raw(T0 & ~3); + ret = ldl_raw(addr & ~3); break; default: case 8: - ret = ldq_raw(T0 & ~7); + ret = ldq_raw(addr & ~7); break; } } @@ -858,11 +860,17 @@ void helper_ld_asi(int asi, int size, int sign) break; } } - T1 = ret; +#ifdef DEBUG_ASI + dump_asi("read ", last_addr, asi, size, ret); +#endif + return ret; } -void helper_st_asi(int asi, int size) +void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) { +#ifdef DEBUG_ASI + dump_asi("write", addr, asi, size, val); +#endif if (asi < 0x80) raise_exception(TT_PRIV_ACT); @@ -872,13 +880,13 @@ void helper_st_asi(int asi, int size) case 0x89: // Secondary LE switch(size) { case 2: - T0 = bswap16(T0); + addr = bswap16(addr); break; case 4: - T0 = bswap32(T0); + addr = bswap32(addr); break; case 8: - T0 = bswap64(T0); + addr = bswap64(addr); break; default: break; @@ -893,17 +901,17 @@ void helper_st_asi(int asi, int size) { switch(size) { case 1: - stb_raw(T0, T1); + stb_raw(addr, val); break; case 2: - stw_raw(T0 & ~1, T1); + stw_raw(addr & ~1, val); break; case 4: - stl_raw(T0 & ~3, T1); + stl_raw(addr & ~3, val); break; case 8: default: - stq_raw(T0 & ~7, T1); + stq_raw(addr & ~7, val); break; } } @@ -918,16 +926,19 @@ void helper_st_asi(int asi, int size) case 0x8a: // Primary no-fault LE, RO case 0x8b: // Secondary no-fault LE, RO default: - do_unassigned_access(T0, 1, 0, 1); + do_unassigned_access(addr, 1, 0, 1); return; } } #else /* CONFIG_USER_ONLY */ -void helper_ld_asi(int asi, int size, int sign) +uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) { uint64_t ret = 0; +#if defined(DEBUG_ASI) + target_ulong last_addr = addr; +#endif if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) @@ -944,50 +955,50 @@ void helper_ld_asi(int asi, int size, int sign) if (env->hpstate & HS_PRIV) { switch(size) { case 1: - ret = ldub_hypv(T0); + ret = ldub_hypv(addr); break; case 2: - ret = lduw_hypv(T0 & ~1); + ret = lduw_hypv(addr & ~1); break; case 4: - ret = ldl_hypv(T0 & ~3); + ret = ldl_hypv(addr & ~3); break; default: case 8: - ret = ldq_hypv(T0 & ~7); + ret = ldq_hypv(addr & ~7); break; } } else { switch(size) { case 1: - ret = ldub_kernel(T0); + ret = ldub_kernel(addr); break; case 2: - ret = lduw_kernel(T0 & ~1); + ret = lduw_kernel(addr & ~1); break; case 4: - ret = ldl_kernel(T0 & ~3); + ret = ldl_kernel(addr & ~3); break; default: case 8: - ret = ldq_kernel(T0 & ~7); + ret = ldq_kernel(addr & ~7); break; } } } else { switch(size) { case 1: - ret = ldub_user(T0); + ret = ldub_user(addr); break; case 2: - ret = lduw_user(T0 & ~1); + ret = lduw_user(addr & ~1); break; case 4: - ret = ldl_user(T0 & ~3); + ret = ldl_user(addr & ~3); break; default: case 8: - ret = ldq_user(T0 & ~7); + ret = ldq_user(addr & ~7); break; } } @@ -999,17 +1010,17 @@ void helper_ld_asi(int asi, int size, int sign) { switch(size) { case 1: - ret = ldub_phys(T0); + ret = ldub_phys(addr); break; case 2: - ret = lduw_phys(T0 & ~1); + ret = lduw_phys(addr & ~1); break; case 4: - ret = ldl_phys(T0 & ~3); + ret = ldl_phys(addr & ~3); break; default: case 8: - ret = ldq_phys(T0 & ~7); + ret = ldq_phys(addr & ~7); break; } break; @@ -1032,7 +1043,7 @@ void helper_ld_asi(int asi, int size, int sign) break; case 0x50: // I-MMU regs { - int reg = (T0 >> 3) & 0xf; + int reg = (addr >> 3) & 0xf; ret = env->immuregs[reg]; break; @@ -1049,7 +1060,7 @@ void helper_ld_asi(int asi, int size, int sign) for (i = 0; i < 64; i++) { // Valid, ctx match, vaddr match if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 && - env->itlb_tag[i] == T0) { + env->itlb_tag[i] == addr) { ret = env->itlb_tag[i]; break; } @@ -1058,7 +1069,7 @@ void helper_ld_asi(int asi, int size, int sign) } case 0x58: // D-MMU regs { - int reg = (T0 >> 3) & 0xf; + int reg = (addr >> 3) & 0xf; ret = env->dmmuregs[reg]; break; @@ -1070,7 +1081,7 @@ void helper_ld_asi(int asi, int size, int sign) for (i = 0; i < 64; i++) { // Valid, ctx match, vaddr match if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 && - env->dtlb_tag[i] == T0) { + env->dtlb_tag[i] == addr) { ret = env->dtlb_tag[i]; break; } @@ -1092,7 +1103,7 @@ void helper_ld_asi(int asi, int size, int sign) case 0x5f: // D-MMU demap, WO case 0x77: // Interrupt vector, WO default: - do_unassigned_access(T0, 0, 0, 1); + do_unassigned_access(addr, 0, 0, 1); ret = 0; break; } @@ -1141,11 +1152,17 @@ void helper_ld_asi(int asi, int size, int sign) break; } } - T1 = ret; +#ifdef DEBUG_ASI + dump_asi("read ", last_addr, asi, size, ret); +#endif + return ret; } -void helper_st_asi(int asi, int size) +void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) { +#ifdef DEBUG_ASI + dump_asi("write", addr, asi, size, val); +#endif if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) raise_exception(TT_PRIV_ACT); @@ -1161,13 +1178,13 @@ void helper_st_asi(int asi, int size) case 0x89: // Secondary LE switch(size) { case 2: - T0 = bswap16(T0); + addr = bswap16(addr); break; case 4: - T0 = bswap32(T0); + addr = bswap32(addr); break; case 8: - T0 = bswap64(T0); + addr = bswap64(addr); break; default: break; @@ -1185,50 +1202,50 @@ void helper_st_asi(int asi, int size) if (env->hpstate & HS_PRIV) { switch(size) { case 1: - stb_hypv(T0, T1); + stb_hypv(addr, val); break; case 2: - stw_hypv(T0 & ~1, T1); + stw_hypv(addr & ~1, val); break; case 4: - stl_hypv(T0 & ~3, T1); + stl_hypv(addr & ~3, val); break; case 8: default: - stq_hypv(T0 & ~7, T1); + stq_hypv(addr & ~7, val); break; } } else { switch(size) { case 1: - stb_kernel(T0, T1); + stb_kernel(addr, val); break; case 2: - stw_kernel(T0 & ~1, T1); + stw_kernel(addr & ~1, val); break; case 4: - stl_kernel(T0 & ~3, T1); + stl_kernel(addr & ~3, val); break; case 8: default: - stq_kernel(T0 & ~7, T1); + stq_kernel(addr & ~7, val); break; } } } else { switch(size) { case 1: - stb_user(T0, T1); + stb_user(addr, val); break; case 2: - stw_user(T0 & ~1, T1); + stw_user(addr & ~1, val); break; case 4: - stl_user(T0 & ~3, T1); + stl_user(addr & ~3, val); break; case 8: default: - stq_user(T0 & ~7, T1); + stq_user(addr & ~7, val); break; } } @@ -1240,17 +1257,17 @@ void helper_st_asi(int asi, int size) { switch(size) { case 1: - stb_phys(T0, T1); + stb_phys(addr, val); break; case 2: - stw_phys(T0 & ~1, T1); + stw_phys(addr & ~1, val); break; case 4: - stl_phys(T0 & ~3, T1); + stl_phys(addr & ~3, val); break; case 8: default: - stq_phys(T0 & ~7, T1); + stq_phys(addr & ~7, val); break; } } @@ -1271,7 +1288,7 @@ void helper_st_asi(int asi, int size) uint64_t oldreg; oldreg = env->lsu; - env->lsu = T1 & (DMMU_E | IMMU_E); + env->lsu = val & (DMMU_E | IMMU_E); // Mappings generated during D/I MMU disabled mode are // invalid in normal mode if (oldreg != env->lsu) { @@ -1285,7 +1302,7 @@ void helper_st_asi(int asi, int size) } case 0x50: // I-MMU regs { - int reg = (T0 >> 3) & 0xf; + int reg = (addr >> 3) & 0xf; uint64_t oldreg; oldreg = env->immuregs[reg]; @@ -1299,15 +1316,15 @@ void helper_st_asi(int asi, int size) case 8: return; case 3: // SFSR - if ((T1 & 1) == 0) - T1 = 0; // Clear SFSR + if ((val & 1) == 0) + val = 0; // Clear SFSR break; case 5: // TSB access case 6: // Tag access default: break; } - env->immuregs[reg] = T1; + env->immuregs[reg] = val; if (oldreg != env->immuregs[reg]) { DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]); } @@ -1324,7 +1341,7 @@ void helper_st_asi(int asi, int size) for (i = 0; i < 64; i++) { if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) { env->itlb_tag[i] = env->immuregs[6]; - env->itlb_tte[i] = T1; + env->itlb_tte[i] = val; return; } } @@ -1332,7 +1349,7 @@ void helper_st_asi(int asi, int size) for (i = 0; i < 64; i++) { if ((env->itlb_tte[i] & 0x40) == 0) { env->itlb_tag[i] = env->immuregs[6]; - env->itlb_tte[i] = T1; + env->itlb_tte[i] = val; return; } } @@ -1341,10 +1358,10 @@ void helper_st_asi(int asi, int size) } case 0x55: // I-MMU data access { - unsigned int i = (T0 >> 3) & 0x3f; + unsigned int i = (addr >> 3) & 0x3f; env->itlb_tag[i] = env->immuregs[6]; - env->itlb_tte[i] = T1; + env->itlb_tte[i] = val; return; } case 0x57: // I-MMU demap @@ -1352,7 +1369,7 @@ void helper_st_asi(int asi, int size) return; case 0x58: // D-MMU regs { - int reg = (T0 >> 3) & 0xf; + int reg = (addr >> 3) & 0xf; uint64_t oldreg; oldreg = env->dmmuregs[reg]; @@ -1361,11 +1378,11 @@ void helper_st_asi(int asi, int size) case 4: return; case 3: // SFSR - if ((T1 & 1) == 0) { - T1 = 0; // Clear SFSR, Fault address + if ((val & 1) == 0) { + val = 0; // Clear SFSR, Fault address env->dmmuregs[4] = 0; } - env->dmmuregs[reg] = T1; + env->dmmuregs[reg] = val; break; case 1: // Primary context case 2: // Secondary context @@ -1376,7 +1393,7 @@ void helper_st_asi(int asi, int size) default: break; } - env->dmmuregs[reg] = T1; + env->dmmuregs[reg] = val; if (oldreg != env->dmmuregs[reg]) { DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]); } @@ -1393,7 +1410,7 @@ void helper_st_asi(int asi, int size) for (i = 0; i < 64; i++) { if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) { env->dtlb_tag[i] = env->dmmuregs[6]; - env->dtlb_tte[i] = T1; + env->dtlb_tte[i] = val; return; } } @@ -1401,7 +1418,7 @@ void helper_st_asi(int asi, int size) for (i = 0; i < 64; i++) { if ((env->dtlb_tte[i] & 0x40) == 0) { env->dtlb_tag[i] = env->dmmuregs[6]; - env->dtlb_tte[i] = T1; + env->dtlb_tte[i] = val; return; } } @@ -1410,10 +1427,10 @@ void helper_st_asi(int asi, int size) } case 0x5d: // D-MMU data access { - unsigned int i = (T0 >> 3) & 0x3f; + unsigned int i = (addr >> 3) & 0x3f; env->dtlb_tag[i] = env->dmmuregs[6]; - env->dtlb_tte[i] = T1; + env->dtlb_tte[i] = val; return; } case 0x5f: // D-MMU demap @@ -1434,16 +1451,16 @@ void helper_st_asi(int asi, int size) case 0x8a: // Primary no-fault LE, RO case 0x8b: // Secondary no-fault LE, RO default: - do_unassigned_access(T0, 1, 0, 1); + do_unassigned_access(addr, 1, 0, 1); return; } } #endif /* CONFIG_USER_ONLY */ -void helper_ldf_asi(int asi, int size, int rd) +void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) { - target_ulong tmp_T0 = T0, tmp_T1 = T1; unsigned int i; + target_ulong val; switch (asi) { case 0xf0: // Block load primary @@ -1454,31 +1471,28 @@ void helper_ldf_asi(int asi, int size, int rd) raise_exception(TT_ILL_INSN); return; } - if (T0 & 0x3f) { + if (addr & 0x3f) { raise_exception(TT_UNALIGNED); return; } for (i = 0; i < 16; i++) { - helper_ld_asi(asi & 0x8f, 4, 0); - *(uint32_t *)&env->fpr[rd++] = T1; - T0 += 4; + *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, 0); + addr += 4; } - T0 = tmp_T0; - T1 = tmp_T1; return; default: break; } - helper_ld_asi(asi, size, 0); + val = helper_ld_asi(addr, asi, size, 0); switch(size) { default: case 4: - *((uint32_t *)&FT0) = T1; + *((uint32_t *)&FT0) = val; break; case 8: - *((int64_t *)&DT0) = T1; + *((int64_t *)&DT0) = val; break; #if defined(CONFIG_USER_ONLY) case 16: @@ -1486,13 +1500,12 @@ void helper_ldf_asi(int asi, int size, int rd) break; #endif } - T1 = tmp_T1; } -void helper_stf_asi(int asi, int size, int rd) +void helper_stf_asi(target_ulong addr, int asi, int size, int rd) { - target_ulong tmp_T0 = T0, tmp_T1 = T1; unsigned int i; + target_ulong val = 0; switch (asi) { case 0xf0: // Block store primary @@ -1503,17 +1516,15 @@ void helper_stf_asi(int asi, int size, int rd) raise_exception(TT_ILL_INSN); return; } - if (T0 & 0x3f) { + if (addr & 0x3f) { raise_exception(TT_UNALIGNED); return; } for (i = 0; i < 16; i++) { - T1 = *(uint32_t *)&env->fpr[rd++]; - helper_st_asi(asi & 0x8f, 4); - T0 += 4; + val = *(uint32_t *)&env->fpr[rd++]; + helper_st_asi(addr, val, asi & 0x8f, 4); + addr += 4; } - T0 = tmp_T0; - T1 = tmp_T1; return; default: @@ -1523,10 +1534,10 @@ void helper_stf_asi(int asi, int size, int rd) switch(size) { default: case 4: - T1 = *((uint32_t *)&FT0); + val = *((uint32_t *)&FT0); break; case 8: - T1 = *((int64_t *)&DT0); + val = *((int64_t *)&DT0); break; #if defined(CONFIG_USER_ONLY) case 16: @@ -1534,14 +1545,36 @@ void helper_stf_asi(int asi, int size, int rd) break; #endif } - helper_st_asi(asi, size); - T1 = tmp_T1; + helper_st_asi(addr, val, asi, size); } +target_ulong helper_cas_asi(target_ulong addr, target_ulong val1, + target_ulong val2, uint32_t asi) +{ + target_ulong ret; + + val1 &= 0xffffffffUL; + ret = helper_ld_asi(addr, asi, 4, 0); + ret &= 0xffffffffUL; + if (val1 == ret) + helper_st_asi(addr, val2 & 0xffffffffUL, asi, 4); + return ret; +} + +target_ulong helper_casx_asi(target_ulong addr, target_ulong val1, + target_ulong val2, uint32_t asi) +{ + target_ulong ret; + + ret = helper_ld_asi(addr, asi, 8, 0); + if (val1 == ret) + helper_st_asi(addr, val2, asi, 8); + return ret; +} #endif /* TARGET_SPARC64 */ #ifndef TARGET_SPARC64 -void helper_rett() +void helper_rett(void) { unsigned int cwp; @@ -1558,6 +1591,11 @@ void helper_rett() } #endif +uint64_t helper_pack64(target_ulong high, target_ulong low) +{ + return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff); +} + void helper_ldfsr(void) { int rnd_mode; @@ -1586,24 +1624,24 @@ void helper_debug() } #ifndef TARGET_SPARC64 -void do_wrpsr() +void helper_wrpsr(target_ulong new_psr) { - if ((T0 & PSR_CWP) >= NWINDOWS) + if ((new_psr & PSR_CWP) >= NWINDOWS) raise_exception(TT_ILL_INSN); else - PUT_PSR(env, T0); + PUT_PSR(env, new_psr); } -void do_rdpsr() +target_ulong helper_rdpsr(void) { - T0 = GET_PSR(env); + return GET_PSR(env); } #else -void do_popc() +target_ulong helper_popc(target_ulong val) { - T0 = ctpop64(T1); + return ctpop64(val); } static inline uint64_t *get_gregset(uint64_t pstate) @@ -1638,12 +1676,12 @@ static inline void change_pstate(uint64_t new_pstate) env->pstate = new_pstate; } -void do_wrpstate(void) +void helper_wrpstate(target_ulong new_state) { - change_pstate(T0 & 0xf3f); + change_pstate(new_state & 0xf3f); } -void do_done(void) +void helper_done(void) { env->tl--; env->pc = env->tnpc[env->tl]; @@ -1654,7 +1692,7 @@ void do_done(void) PUT_CWP64(env, env->tstate[env->tl] & 0xff); } -void do_retry(void) +void helper_retry(void) { env->tl--; env->pc = env->tpc[env->tl]; diff --git a/target-sparc/op_mem.h b/target-sparc/op_mem.h index 894fc36660..9e1a9c25f3 100644 --- a/target-sparc/op_mem.h +++ b/target-sparc/op_mem.h @@ -4,65 +4,6 @@ #define ADDR(x) (x) #endif -/*** Integer load ***/ -#define SPARC_LD_OP(name, qp) \ -void OPPROTO glue(glue(op_, name), MEMSUFFIX)(void) \ -{ \ - T1 = (target_ulong)glue(qp, MEMSUFFIX)(ADDR(T0)); \ -} - -#define SPARC_LD_OP_S(name, qp) \ - void OPPROTO glue(glue(op_, name), MEMSUFFIX)(void) \ - { \ - T1 = (target_long)glue(qp, MEMSUFFIX)(ADDR(T0)); \ - } - -#define SPARC_ST_OP(name, op) \ -void OPPROTO glue(glue(op_, name), MEMSUFFIX)(void) \ -{ \ - glue(op, MEMSUFFIX)(ADDR(T0), T1); \ -} - -SPARC_LD_OP(ld, ldl); -SPARC_LD_OP(ldub, ldub); -SPARC_LD_OP(lduh, lduw); -SPARC_LD_OP_S(ldsb, ldsb); -SPARC_LD_OP_S(ldsh, ldsw); - -/*** Integer store ***/ -SPARC_ST_OP(st, stl); -SPARC_ST_OP(stb, stb); -SPARC_ST_OP(sth, stw); - -void OPPROTO glue(op_std, MEMSUFFIX)(void) -{ - uint64_t tmp = ((uint64_t)T1 << 32) | (uint64_t)(T2 & 0xffffffff); - - glue(stq, MEMSUFFIX)(ADDR(T0), tmp); -} - -void OPPROTO glue(op_ldstub, MEMSUFFIX)(void) -{ - T1 = glue(ldub, MEMSUFFIX)(ADDR(T0)); - glue(stb, MEMSUFFIX)(ADDR(T0), 0xff); /* XXX: Should be Atomically */ -} - -void OPPROTO glue(op_swap, MEMSUFFIX)(void) -{ - target_ulong tmp = glue(ldl, MEMSUFFIX)(ADDR(T0)); - glue(stl, MEMSUFFIX)(ADDR(T0), T1); /* XXX: Should be Atomically */ - T1 = tmp; -} - -void OPPROTO glue(op_ldd, MEMSUFFIX)(void) -{ - uint64_t tmp; - - tmp = glue(ldq, MEMSUFFIX)(ADDR(T0)); - T1 = tmp >> 32; - T0 = tmp & 0xffffffff; -} - /*** Floating-point store ***/ void OPPROTO glue(op_stf, MEMSUFFIX) (void) { @@ -107,18 +48,4 @@ void OPPROTO glue(op_stqf, MEMSUFFIX) (void) } #endif -#ifdef TARGET_SPARC64 -void OPPROTO glue(op_lduw, MEMSUFFIX)(void) -{ - T1 = (uint64_t)(glue(ldl, MEMSUFFIX)(ADDR(T0)) & 0xffffffff); -} - -void OPPROTO glue(op_ldsw, MEMSUFFIX)(void) -{ - T1 = (int64_t)(glue(ldl, MEMSUFFIX)(ADDR(T0)) & 0xffffffff); -} - -SPARC_LD_OP(ldx, ldq); -SPARC_ST_OP(stx, stq); -#endif #undef MEMSUFFIX diff --git a/target-sparc/op_template.h b/target-sparc/op_template.h deleted file mode 100644 index f920615344..0000000000 --- a/target-sparc/op_template.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SPARC micro operations (templates for various register related - * operations) - * - * Copyright (c) 2003 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -void OPPROTO glue(op_movl_T0_, REGNAME)(void) -{ - T0 = REG; -} - -void OPPROTO glue(op_movl_T1_, REGNAME)(void) -{ - T1 = REG; -} - -void OPPROTO glue(op_movl_T2_, REGNAME)(void) -{ - T2 = REG; -} - -void OPPROTO glue(glue(op_movl_, REGNAME), _T0)(void) -{ - REG = T0; -} - -void OPPROTO glue(glue(op_movl_, REGNAME), _T1)(void) -{ - REG = T1; -} - -#undef REG -#undef REGNAME diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 6356136711..fd896855e9 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -36,6 +36,7 @@ #include "cpu.h" #include "exec-all.h" #include "disas.h" +#include "helper.h" #include "tcg-op.h" #define DEBUG_DISAS @@ -44,6 +45,11 @@ #define JUMP_PC 2 /* dynamic pc value which takes only two values according to jump_pc[T2] */ +/* global register indexes */ +static TCGv cpu_env, cpu_T[3], cpu_regwptr; +/* local register indexes (only used inside old micro ops) */ +static TCGv cpu_tmp0; + typedef struct DisasContext { target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ @@ -102,195 +108,6 @@ static int sign_extend(int x, int len) static void disas_sparc_insn(DisasContext * dc); -static GenOpFunc * const gen_op_movl_TN_reg[2][32] = { - { - gen_op_movl_g0_T0, - gen_op_movl_g1_T0, - gen_op_movl_g2_T0, - gen_op_movl_g3_T0, - gen_op_movl_g4_T0, - gen_op_movl_g5_T0, - gen_op_movl_g6_T0, - gen_op_movl_g7_T0, - gen_op_movl_o0_T0, - gen_op_movl_o1_T0, - gen_op_movl_o2_T0, - gen_op_movl_o3_T0, - gen_op_movl_o4_T0, - gen_op_movl_o5_T0, - gen_op_movl_o6_T0, - gen_op_movl_o7_T0, - gen_op_movl_l0_T0, - gen_op_movl_l1_T0, - gen_op_movl_l2_T0, - gen_op_movl_l3_T0, - gen_op_movl_l4_T0, - gen_op_movl_l5_T0, - gen_op_movl_l6_T0, - gen_op_movl_l7_T0, - gen_op_movl_i0_T0, - gen_op_movl_i1_T0, - gen_op_movl_i2_T0, - gen_op_movl_i3_T0, - gen_op_movl_i4_T0, - gen_op_movl_i5_T0, - gen_op_movl_i6_T0, - gen_op_movl_i7_T0, - }, - { - gen_op_movl_g0_T1, - gen_op_movl_g1_T1, - gen_op_movl_g2_T1, - gen_op_movl_g3_T1, - gen_op_movl_g4_T1, - gen_op_movl_g5_T1, - gen_op_movl_g6_T1, - gen_op_movl_g7_T1, - gen_op_movl_o0_T1, - gen_op_movl_o1_T1, - gen_op_movl_o2_T1, - gen_op_movl_o3_T1, - gen_op_movl_o4_T1, - gen_op_movl_o5_T1, - gen_op_movl_o6_T1, - gen_op_movl_o7_T1, - gen_op_movl_l0_T1, - gen_op_movl_l1_T1, - gen_op_movl_l2_T1, - gen_op_movl_l3_T1, - gen_op_movl_l4_T1, - gen_op_movl_l5_T1, - gen_op_movl_l6_T1, - gen_op_movl_l7_T1, - gen_op_movl_i0_T1, - gen_op_movl_i1_T1, - gen_op_movl_i2_T1, - gen_op_movl_i3_T1, - gen_op_movl_i4_T1, - gen_op_movl_i5_T1, - gen_op_movl_i6_T1, - gen_op_movl_i7_T1, - } -}; - -static GenOpFunc * const gen_op_movl_reg_TN[3][32] = { - { - gen_op_movl_T0_g0, - gen_op_movl_T0_g1, - gen_op_movl_T0_g2, - gen_op_movl_T0_g3, - gen_op_movl_T0_g4, - gen_op_movl_T0_g5, - gen_op_movl_T0_g6, - gen_op_movl_T0_g7, - gen_op_movl_T0_o0, - gen_op_movl_T0_o1, - gen_op_movl_T0_o2, - gen_op_movl_T0_o3, - gen_op_movl_T0_o4, - gen_op_movl_T0_o5, - gen_op_movl_T0_o6, - gen_op_movl_T0_o7, - gen_op_movl_T0_l0, - gen_op_movl_T0_l1, - gen_op_movl_T0_l2, - gen_op_movl_T0_l3, - gen_op_movl_T0_l4, - gen_op_movl_T0_l5, - gen_op_movl_T0_l6, - gen_op_movl_T0_l7, - gen_op_movl_T0_i0, - gen_op_movl_T0_i1, - gen_op_movl_T0_i2, - gen_op_movl_T0_i3, - gen_op_movl_T0_i4, - gen_op_movl_T0_i5, - gen_op_movl_T0_i6, - gen_op_movl_T0_i7, - }, - { - gen_op_movl_T1_g0, - gen_op_movl_T1_g1, - gen_op_movl_T1_g2, - gen_op_movl_T1_g3, - gen_op_movl_T1_g4, - gen_op_movl_T1_g5, - gen_op_movl_T1_g6, - gen_op_movl_T1_g7, - gen_op_movl_T1_o0, - gen_op_movl_T1_o1, - gen_op_movl_T1_o2, - gen_op_movl_T1_o3, - gen_op_movl_T1_o4, - gen_op_movl_T1_o5, - gen_op_movl_T1_o6, - gen_op_movl_T1_o7, - gen_op_movl_T1_l0, - gen_op_movl_T1_l1, - gen_op_movl_T1_l2, - gen_op_movl_T1_l3, - gen_op_movl_T1_l4, - gen_op_movl_T1_l5, - gen_op_movl_T1_l6, - gen_op_movl_T1_l7, - gen_op_movl_T1_i0, - gen_op_movl_T1_i1, - gen_op_movl_T1_i2, - gen_op_movl_T1_i3, - gen_op_movl_T1_i4, - gen_op_movl_T1_i5, - gen_op_movl_T1_i6, - gen_op_movl_T1_i7, - }, - { - gen_op_movl_T2_g0, - gen_op_movl_T2_g1, - gen_op_movl_T2_g2, - gen_op_movl_T2_g3, - gen_op_movl_T2_g4, - gen_op_movl_T2_g5, - gen_op_movl_T2_g6, - gen_op_movl_T2_g7, - gen_op_movl_T2_o0, - gen_op_movl_T2_o1, - gen_op_movl_T2_o2, - gen_op_movl_T2_o3, - gen_op_movl_T2_o4, - gen_op_movl_T2_o5, - gen_op_movl_T2_o6, - gen_op_movl_T2_o7, - gen_op_movl_T2_l0, - gen_op_movl_T2_l1, - gen_op_movl_T2_l2, - gen_op_movl_T2_l3, - gen_op_movl_T2_l4, - gen_op_movl_T2_l5, - gen_op_movl_T2_l6, - gen_op_movl_T2_l7, - gen_op_movl_T2_i0, - gen_op_movl_T2_i1, - gen_op_movl_T2_i2, - gen_op_movl_T2_i3, - gen_op_movl_T2_i4, - gen_op_movl_T2_i5, - gen_op_movl_T2_i6, - gen_op_movl_T2_i7, - } -}; - -static GenOpFunc1 * const gen_op_movl_TN_im[3] = { - gen_op_movl_T0_im, - gen_op_movl_T1_im, - gen_op_movl_T2_im -}; - -// Sign extending version -static GenOpFunc1 * const gen_op_movl_TN_sim[3] = { - gen_op_movl_T0_sim, - gen_op_movl_T1_sim, - gen_op_movl_T2_sim -}; - #ifdef TARGET_SPARC64 #define GEN32(func, NAME) \ static GenOpFunc * const NAME ## _table [64] = { \ @@ -375,307 +192,112 @@ GEN32(gen_op_store_QT1_fpr, gen_op_store_QT1_fpr_fprf); #endif #ifndef CONFIG_USER_ONLY -OP_LD_TABLE(ld); -OP_LD_TABLE(st); -OP_LD_TABLE(ldub); -OP_LD_TABLE(lduh); -OP_LD_TABLE(ldsb); -OP_LD_TABLE(ldsh); -OP_LD_TABLE(stb); -OP_LD_TABLE(sth); -OP_LD_TABLE(std); -OP_LD_TABLE(ldstub); -OP_LD_TABLE(swap); -OP_LD_TABLE(ldd); OP_LD_TABLE(stf); OP_LD_TABLE(stdf); OP_LD_TABLE(ldf); OP_LD_TABLE(lddf); - -#ifdef TARGET_SPARC64 -OP_LD_TABLE(lduw); -OP_LD_TABLE(ldsw); -OP_LD_TABLE(ldx); -OP_LD_TABLE(stx); -#endif #endif -/* asi moves */ -#ifdef TARGET_SPARC64 -static inline void gen_ld_asi(int insn, int size, int sign) -{ - int asi, offset; - - if (IS_IMM) { - offset = GET_FIELD(insn, 25, 31); - gen_op_ld_asi_reg(offset, size, sign); - } else { - asi = GET_FIELD(insn, 19, 26); - gen_op_ld_asi(asi, size, sign); - } -} - -static inline void gen_st_asi(int insn, int size) -{ - int asi, offset; - - if (IS_IMM) { - offset = GET_FIELD(insn, 25, 31); - gen_op_st_asi_reg(offset, size); - } else { - asi = GET_FIELD(insn, 19, 26); - gen_op_st_asi(asi, size); - } -} - -static inline void gen_ldf_asi(int insn, int size, int rd) -{ - int asi, offset; - - if (IS_IMM) { - offset = GET_FIELD(insn, 25, 31); - gen_op_ldf_asi_reg(offset, size, rd); - } else { - asi = GET_FIELD(insn, 19, 26); - gen_op_ldf_asi(asi, size, rd); - } -} - -static inline void gen_stf_asi(int insn, int size, int rd) -{ - int asi, offset; - - if (IS_IMM) { - offset = GET_FIELD(insn, 25, 31); - gen_op_stf_asi_reg(offset, size, rd); - } else { - asi = GET_FIELD(insn, 19, 26); - gen_op_stf_asi(asi, size, rd); - } -} +#ifdef TARGET_ABI32 +#define ABI32_MASK(addr) tcg_gen_andi_i64(addr, addr, 0xffffffffULL); +#else +#define ABI32_MASK(addr) +#endif -static inline void gen_swap_asi(int insn) +static inline void gen_movl_simm_T1(int32_t val) { - int asi, offset; - - if (IS_IMM) { - offset = GET_FIELD(insn, 25, 31); - gen_op_swap_asi_reg(offset); - } else { - asi = GET_FIELD(insn, 19, 26); - gen_op_swap_asi(asi); - } + tcg_gen_movi_tl(cpu_T[1], val); } -static inline void gen_ldstub_asi(int insn) +static inline void gen_movl_reg_TN(int reg, TCGv tn) { - int asi, offset; - - if (IS_IMM) { - offset = GET_FIELD(insn, 25, 31); - gen_op_ldstub_asi_reg(offset); - } else { - asi = GET_FIELD(insn, 19, 26); - gen_op_ldstub_asi(asi); + if (reg == 0) + tcg_gen_movi_tl(tn, 0); + else if (reg < 8) + tcg_gen_ld_tl(tn, cpu_env, offsetof(CPUState, gregs[reg])); + else { + tcg_gen_ld_ptr(cpu_regwptr, cpu_env, offsetof(CPUState, regwptr)); // XXX + tcg_gen_ld_tl(tn, cpu_regwptr, (reg - 8) * sizeof(target_ulong)); } } -static inline void gen_ldda_asi(int insn) +static inline void gen_movl_reg_T0(int reg) { - int asi, offset; - - if (IS_IMM) { - offset = GET_FIELD(insn, 25, 31); - gen_op_ldda_asi_reg(offset); - } else { - asi = GET_FIELD(insn, 19, 26); - gen_op_ldda_asi(asi); - } + gen_movl_reg_TN(reg, cpu_T[0]); } -static inline void gen_stda_asi(int insn) +static inline void gen_movl_reg_T1(int reg) { - int asi, offset; - - if (IS_IMM) { - offset = GET_FIELD(insn, 25, 31); - gen_op_stda_asi_reg(offset); - } else { - asi = GET_FIELD(insn, 19, 26); - gen_op_stda_asi(asi); - } + gen_movl_reg_TN(reg, cpu_T[1]); } -static inline void gen_cas_asi(int insn) +static inline void gen_movl_TN_reg(int reg, TCGv tn) { - int asi, offset; - - if (IS_IMM) { - offset = GET_FIELD(insn, 25, 31); - gen_op_cas_asi_reg(offset); - } else { - asi = GET_FIELD(insn, 19, 26); - gen_op_cas_asi(asi); + if (reg == 0) + return; + else if (reg < 8) + tcg_gen_st_tl(tn, cpu_env, offsetof(CPUState, gregs[reg])); + else { + tcg_gen_ld_ptr(cpu_regwptr, cpu_env, offsetof(CPUState, regwptr)); // XXX + tcg_gen_st_tl(tn, cpu_regwptr, (reg - 8) * sizeof(target_ulong)); } } -static inline void gen_casx_asi(int insn) -{ - int asi, offset; - - if (IS_IMM) { - offset = GET_FIELD(insn, 25, 31); - gen_op_casx_asi_reg(offset); - } else { - asi = GET_FIELD(insn, 19, 26); - gen_op_casx_asi(asi); - } -} - -#elif !defined(CONFIG_USER_ONLY) - -static inline void gen_ld_asi(int insn, int size, int sign) -{ - int asi; - - asi = GET_FIELD(insn, 19, 26); - gen_op_ld_asi(asi, size, sign); -} - -static inline void gen_st_asi(int insn, int size) -{ - int asi; - - asi = GET_FIELD(insn, 19, 26); - gen_op_st_asi(asi, size); -} - -static inline void gen_ldstub_asi(int insn) -{ - int asi; - - asi = GET_FIELD(insn, 19, 26); - gen_op_ldstub_asi(asi); -} - -static inline void gen_swap_asi(int insn) -{ - int asi; - - asi = GET_FIELD(insn, 19, 26); - gen_op_swap_asi(asi); -} - -static inline void gen_ldda_asi(int insn) -{ - int asi; - - asi = GET_FIELD(insn, 19, 26); - gen_op_ld_asi(asi, 8, 0); -} - -static inline void gen_stda_asi(int insn) -{ - int asi; - - asi = GET_FIELD(insn, 19, 26); - gen_op_st_asi(asi, 8); -} -#endif - -static inline void gen_movl_imm_TN(int reg, uint32_t imm) -{ - gen_op_movl_TN_im[reg](imm); -} - -static inline void gen_movl_imm_T1(uint32_t val) -{ - gen_movl_imm_TN(1, val); -} - -static inline void gen_movl_imm_T0(uint32_t val) -{ - gen_movl_imm_TN(0, val); -} - -static inline void gen_movl_simm_TN(int reg, int32_t imm) -{ - gen_op_movl_TN_sim[reg](imm); -} - -static inline void gen_movl_simm_T1(int32_t val) +static inline void gen_movl_T0_reg(int reg) { - gen_movl_simm_TN(1, val); + gen_movl_TN_reg(reg, cpu_T[0]); } -static inline void gen_movl_simm_T0(int32_t val) +static inline void gen_movl_T1_reg(int reg) { - gen_movl_simm_TN(0, val); + gen_movl_TN_reg(reg, cpu_T[1]); } -static inline void gen_movl_reg_TN(int reg, int t) +static inline void gen_op_movl_T0_env(size_t offset) { - if (reg) - gen_op_movl_reg_TN[t][reg] (); - else - gen_movl_imm_TN(t, 0); + tcg_gen_ld_i32(cpu_T[0], cpu_env, offset); } -static inline void gen_movl_reg_T0(int reg) +static inline void gen_op_movl_env_T0(size_t offset) { - gen_movl_reg_TN(reg, 0); + tcg_gen_st_i32(cpu_T[0], cpu_env, offset); } -static inline void gen_movl_reg_T1(int reg) +static inline void gen_op_movtl_T0_env(size_t offset) { - gen_movl_reg_TN(reg, 1); + tcg_gen_ld_tl(cpu_T[0], cpu_env, offset); } -static inline void gen_movl_reg_T2(int reg) +static inline void gen_op_movtl_env_T0(size_t offset) { - gen_movl_reg_TN(reg, 2); + tcg_gen_st_tl(cpu_T[0], cpu_env, offset); } -static inline void gen_movl_TN_reg(int reg, int t) +static inline void gen_op_add_T1_T0(void) { - if (reg) - gen_op_movl_TN_reg[t][reg] (); + tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); } -static inline void gen_movl_T0_reg(int reg) +static inline void gen_op_or_T1_T0(void) { - gen_movl_TN_reg(reg, 0); + tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]); } -static inline void gen_movl_T1_reg(int reg) +static inline void gen_op_xor_T1_T0(void) { - gen_movl_TN_reg(reg, 1); + tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]); } static inline void gen_jmp_im(target_ulong pc) { -#ifdef TARGET_SPARC64 - if (pc == (uint32_t)pc) { - gen_op_jmp_im(pc); - } else { - gen_op_jmp_im64(pc >> 32, pc); - } -#else - gen_op_jmp_im(pc); -#endif + tcg_gen_movi_tl(cpu_tmp0, pc); + tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, pc)); } static inline void gen_movl_npc_im(target_ulong npc) { -#ifdef TARGET_SPARC64 - if (npc == (uint32_t)npc) { - gen_op_movl_npc_im(npc); - } else { - gen_op_movq_npc_im64(npc >> 32, npc); - } -#else - gen_op_movl_npc_im(npc); -#endif + tcg_gen_movi_tl(cpu_tmp0, npc); + tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, npc)); } static inline void gen_goto_tb(DisasContext *s, int tb_num, @@ -1095,6 +717,270 @@ static int gen_trap_ifnofpu(DisasContext * dc) return 0; } +/* asi moves */ +#ifdef TARGET_SPARC64 +static inline void gen_ld_asi(int insn, int size, int sign) +{ + int asi, offset; + TCGv r_size, r_sign; + + r_size = tcg_temp_new(TCG_TYPE_I32); + r_sign = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_movi_i32(r_size, size); + tcg_gen_movi_i32(r_sign, sign); + if (IS_IMM) { + offset = GET_FIELD(insn, 25, 31); + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset); + tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUSPARCState, asi)); + } else { + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(cpu_T[1], asi); + } + tcg_gen_helper_1_4(helper_ld_asi, cpu_T[1], cpu_T[0], cpu_T[1], r_size, + r_sign); +} + +static inline void gen_st_asi(int insn, int size) +{ + int asi, offset; + TCGv r_asi, r_size; + + r_asi = tcg_temp_new(TCG_TYPE_I32); + r_size = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_movi_i32(r_size, size); + if (IS_IMM) { + offset = GET_FIELD(insn, 25, 31); + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset); + tcg_gen_ld_i32(r_asi, cpu_env, offsetof(CPUSPARCState, asi)); + } else { + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(r_asi, asi); + } + tcg_gen_helper_0_4(helper_st_asi, cpu_T[0], cpu_T[1], r_asi, r_size); +} + +static inline void gen_ldf_asi(int insn, int size, int rd) +{ + int asi, offset; + TCGv r_asi, r_size, r_rd; + + r_asi = tcg_temp_new(TCG_TYPE_I32); + r_size = tcg_temp_new(TCG_TYPE_I32); + r_rd = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_movi_i32(r_size, size); + tcg_gen_movi_i32(r_rd, rd); + if (IS_IMM) { + offset = GET_FIELD(insn, 25, 31); + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset); + tcg_gen_ld_i32(r_asi, cpu_env, offsetof(CPUSPARCState, asi)); + } else { + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(r_asi, asi); + } + tcg_gen_helper_0_4(helper_ldf_asi, cpu_T[0], r_asi, r_size, r_rd); +} + +static inline void gen_stf_asi(int insn, int size, int rd) +{ + int asi, offset; + TCGv r_asi, r_size, r_rd; + + r_asi = tcg_temp_new(TCG_TYPE_I32); + r_size = tcg_temp_new(TCG_TYPE_I32); + r_rd = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_movi_i32(r_size, size); + tcg_gen_movi_i32(r_rd, rd); + if (IS_IMM) { + offset = GET_FIELD(insn, 25, 31); + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset); + tcg_gen_ld_i32(r_asi, cpu_env, offsetof(CPUSPARCState, asi)); + } else { + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(r_asi, asi); + } + tcg_gen_helper_0_4(helper_stf_asi, cpu_T[0], r_asi, r_size, r_rd); +} + +static inline void gen_swap_asi(int insn) +{ + int asi, offset; + TCGv r_size, r_sign, r_temp; + + r_size = tcg_temp_new(TCG_TYPE_I32); + r_sign = tcg_temp_new(TCG_TYPE_I32); + r_temp = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_movi_i32(r_size, 4); + tcg_gen_movi_i32(r_sign, 0); + if (IS_IMM) { + offset = GET_FIELD(insn, 25, 31); + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset); + tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUSPARCState, asi)); + } else { + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(cpu_T[1], asi); + } + tcg_gen_helper_1_4(helper_ld_asi, r_temp, cpu_T[0], cpu_T[1], r_size, + r_sign); + tcg_gen_helper_0_4(helper_st_asi, cpu_T[0], cpu_T[1], r_size, r_sign); + tcg_gen_mov_i32(cpu_T[1], r_temp); +} + +static inline void gen_ldda_asi(int insn) +{ + int asi, offset; + TCGv r_size, r_sign, r_dword; + + r_size = tcg_temp_new(TCG_TYPE_I32); + r_sign = tcg_temp_new(TCG_TYPE_I32); + r_dword = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_movi_i32(r_size, 8); + tcg_gen_movi_i32(r_sign, 0); + if (IS_IMM) { + offset = GET_FIELD(insn, 25, 31); + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset); + tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUSPARCState, asi)); + } else { + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(cpu_T[1], asi); + } + tcg_gen_helper_1_4(helper_ld_asi, r_dword, cpu_T[0], cpu_T[1], r_size, + r_sign); + tcg_gen_trunc_i64_i32(cpu_T[0], r_dword); + tcg_gen_shri_i64(r_dword, r_dword, 32); + tcg_gen_trunc_i64_i32(cpu_T[1], r_dword); +} + +static inline void gen_cas_asi(int insn, int rd) +{ + int asi, offset; + TCGv r_val1, r_asi; + + r_val1 = tcg_temp_new(TCG_TYPE_I32); + r_asi = tcg_temp_new(TCG_TYPE_I32); + gen_movl_reg_TN(rd, r_val1); + if (IS_IMM) { + offset = GET_FIELD(insn, 25, 31); + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset); + tcg_gen_ld_i32(r_asi, cpu_env, offsetof(CPUSPARCState, asi)); + } else { + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(r_asi, asi); + } + tcg_gen_helper_1_4(helper_cas_asi, cpu_T[1], cpu_T[0], r_val1, cpu_T[1], + r_asi); +} + +static inline void gen_casx_asi(int insn, int rd) +{ + int asi, offset; + TCGv r_val1, r_asi; + + r_val1 = tcg_temp_new(TCG_TYPE_I64); + r_asi = tcg_temp_new(TCG_TYPE_I32); + gen_movl_reg_TN(rd, r_val1); + if (IS_IMM) { + offset = GET_FIELD(insn, 25, 31); + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset); + tcg_gen_ld_i32(r_asi, cpu_env, offsetof(CPUSPARCState, asi)); + } else { + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(r_asi, asi); + } + tcg_gen_helper_1_4(helper_casx_asi, cpu_T[1], cpu_T[0], r_val1, cpu_T[1], + r_asi); +} + +#elif !defined(CONFIG_USER_ONLY) + +static inline void gen_ld_asi(int insn, int size, int sign) +{ + int asi; + TCGv r_size, r_sign, r_dword; + + r_size = tcg_temp_new(TCG_TYPE_I32); + r_sign = tcg_temp_new(TCG_TYPE_I32); + r_dword = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_movi_i32(r_size, size); + tcg_gen_movi_i32(r_sign, sign); + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(cpu_T[1], asi); + tcg_gen_helper_1_4(helper_ld_asi, r_dword, cpu_T[0], cpu_T[1], r_size, + r_sign); + tcg_gen_trunc_i64_i32(cpu_T[1], r_dword); +} + +static inline void gen_st_asi(int insn, int size) +{ + int asi; + TCGv r_dword, r_asi, r_size; + + r_dword = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_extu_i32_i64(r_dword, cpu_T[1]); + r_asi = tcg_temp_new(TCG_TYPE_I32); + r_size = tcg_temp_new(TCG_TYPE_I32); + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(r_asi, asi); + tcg_gen_movi_i32(r_size, size); + tcg_gen_helper_0_4(helper_st_asi, cpu_T[0], r_dword, r_asi, r_size); +} + +static inline void gen_swap_asi(int insn) +{ + int asi; + TCGv r_size, r_sign, r_temp; + + r_size = tcg_temp_new(TCG_TYPE_I32); + r_sign = tcg_temp_new(TCG_TYPE_I32); + r_temp = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_movi_i32(r_size, 4); + tcg_gen_movi_i32(r_sign, 0); + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(cpu_T[1], asi); + tcg_gen_helper_1_4(helper_ld_asi, r_temp, cpu_T[0], cpu_T[1], r_size, + r_sign); + tcg_gen_helper_0_4(helper_st_asi, cpu_T[0], cpu_T[1], r_size, r_sign); + tcg_gen_mov_i32(cpu_T[1], r_temp); +} + +static inline void gen_ldda_asi(int insn) +{ + int asi; + TCGv r_size, r_sign, r_dword; + + r_size = tcg_temp_new(TCG_TYPE_I32); + r_sign = tcg_temp_new(TCG_TYPE_I32); + r_dword = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_movi_i32(r_size, 8); + tcg_gen_movi_i32(r_sign, 0); + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(cpu_T[1], asi); + tcg_gen_helper_1_4(helper_ld_asi, r_dword, cpu_T[0], cpu_T[1], r_size, + r_sign); + tcg_gen_trunc_i64_i32(cpu_T[0], r_dword); + tcg_gen_shri_i64(r_dword, r_dword, 32); + tcg_gen_trunc_i64_i32(cpu_T[1], r_dword); +} +#endif + +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) +static inline void gen_ldstub_asi(int insn) +{ + int asi; + TCGv r_dword, r_asi, r_size; + + gen_ld_asi(insn, 1, 0); + + r_dword = tcg_temp_new(TCG_TYPE_I64); + r_asi = tcg_temp_new(TCG_TYPE_I32); + r_size = tcg_temp_new(TCG_TYPE_I32); + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(r_dword, 0xff); + tcg_gen_movi_i32(r_asi, asi); + tcg_gen_movi_i32(r_size, 1); + tcg_gen_helper_0_4(helper_st_asi, cpu_T[0], r_dword, r_asi, r_size); +} +#endif + /* before an instruction, dc->pc must be static */ static void disas_sparc_insn(DisasContext * dc) { @@ -1179,7 +1065,7 @@ static void disas_sparc_insn(DisasContext * dc) if (rd) { // nop #endif uint32_t value = GET_FIELD(insn, 10, 31); - gen_movl_imm_T0(value << 10); + tcg_gen_movi_tl(cpu_T[0], value << 10); gen_movl_T0_reg(rd); #if defined(OPTIM) } @@ -1196,15 +1082,7 @@ static void disas_sparc_insn(DisasContext * dc) /*CALL*/ { target_long target = GET_FIELDs(insn, 2, 31) << 2; -#ifdef TARGET_SPARC64 - if (dc->pc == (uint32_t)dc->pc) { - gen_op_movl_T0_im(dc->pc); - } else { - gen_op_movq_T0_im64(dc->pc >> 32, dc->pc); - } -#else - gen_op_movl_T0_im(dc->pc); -#endif + tcg_gen_movi_tl(cpu_T[0], dc->pc); gen_movl_T0_reg(15); target += dc->pc; gen_mov_pc_npc(dc); @@ -1221,14 +1099,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_movl_reg_T0(rs1); if (IS_IMM) { rs2 = GET_FIELD(insn, 25, 31); -#if defined(OPTIM) - if (rs2 != 0) { -#endif - gen_movl_simm_T1(rs2); - gen_op_add_T1_T0(); -#if defined(OPTIM) - } -#endif + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], rs2); } else { rs2 = GET_FIELD(insn, 27, 31); #if defined(OPTIM) @@ -1243,7 +1114,7 @@ static void disas_sparc_insn(DisasContext * dc) cond = GET_FIELD(insn, 3, 6); if (cond == 0x8) { save_state(dc); - gen_op_trap_T0(); + tcg_gen_helper_0_1(helper_trap, cpu_T[0]); } else if (cond != 0) { #ifdef TARGET_SPARC64 /* V9 icc/xcc */ @@ -1261,7 +1132,7 @@ static void disas_sparc_insn(DisasContext * dc) save_state(dc); gen_cond[0][cond](); #endif - gen_op_trapcc_T0(); + tcg_gen_helper_0_2(helper_trapcc, cpu_T[0], cpu_T[2]); } gen_op_next_insn(); tcg_gen_exit_tb(0); @@ -1298,11 +1169,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_movl_T0_reg(rd); break; case 0x5: /* V9 rdpc */ - if (dc->pc == (uint32_t)dc->pc) { - gen_op_movl_T0_im(dc->pc); - } else { - gen_op_movq_T0_im64(dc->pc >> 32, dc->pc); - } + tcg_gen_movi_tl(cpu_T[0], dc->pc); gen_movl_T0_reg(rd); break; case 0x6: /* V9 rdfprs */ @@ -1344,7 +1211,7 @@ static void disas_sparc_insn(DisasContext * dc) #ifndef TARGET_SPARC64 if (!supervisor(dc)) goto priv_insn; - gen_op_rdpsr(); + tcg_gen_helper_1_0(helper_rdpsr, cpu_T[0]); #else if (!hypervisor(dc)) goto priv_insn; @@ -1399,7 +1266,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr)); break; case 6: // pstate - gen_op_rdpstate(); + gen_op_movl_T0_env(offsetof(CPUSPARCState, pstate)); break; case 7: // tl gen_op_movl_T0_env(offsetof(CPUSPARCState, tl)); @@ -2078,24 +1945,19 @@ static void disas_sparc_insn(DisasContext * dc) rs1 = GET_FIELD(insn, 13, 17); if (rs1 == 0) { - // or %g0, x, y -> mov T1, x; mov y, T1 + // or %g0, x, y -> mov T0, x; mov y, T0 if (IS_IMM) { /* immediate */ rs2 = GET_FIELDs(insn, 19, 31); - gen_movl_simm_T1(rs2); + tcg_gen_movi_tl(cpu_T[0], (int)rs2); } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); - gen_movl_reg_T1(rs2); + gen_movl_reg_T0(rs2); } - gen_movl_T1_reg(rd); } else { gen_movl_reg_T0(rs1); if (IS_IMM) { /* immediate */ - // or x, #0, y -> mov T1, x; mov y, T1 rs2 = GET_FIELDs(insn, 19, 31); - if (rs2 != 0) { - gen_movl_simm_T1(rs2); - gen_op_or_T1_T0(); - } + tcg_gen_ori_tl(cpu_T[0], cpu_T[0], (int)rs2); } else { /* register */ // or x, %g0, y -> mov T1, x; mov y, T1 rs2 = GET_FIELD(insn, 27, 31); @@ -2104,8 +1966,8 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_or_T1_T0(); } } - gen_movl_T0_reg(rd); } + gen_movl_T0_reg(rd); #endif #ifdef TARGET_SPARC64 } else if (xop == 0x25) { /* sll, V9 sllx */ @@ -2113,45 +1975,73 @@ static void disas_sparc_insn(DisasContext * dc) gen_movl_reg_T0(rs1); if (IS_IMM) { /* immediate */ rs2 = GET_FIELDs(insn, 20, 31); - gen_movl_simm_T1(rs2); + if (insn & (1 << 12)) { + tcg_gen_shli_i64(cpu_T[0], cpu_T[0], rs2 & 0x3f); + } else { + tcg_gen_andi_i64(cpu_T[0], cpu_T[0], 0xffffffffULL); + tcg_gen_shli_i64(cpu_T[0], cpu_T[0], rs2 & 0x1f); + } } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); gen_movl_reg_T1(rs2); + if (insn & (1 << 12)) { + tcg_gen_andi_i64(cpu_T[1], cpu_T[1], 0x3f); + tcg_gen_shl_i64(cpu_T[0], cpu_T[0], cpu_T[1]); + } else { + tcg_gen_andi_i64(cpu_T[1], cpu_T[1], 0x1f); + tcg_gen_andi_i64(cpu_T[0], cpu_T[0], 0xffffffffULL); + tcg_gen_shl_i64(cpu_T[0], cpu_T[0], cpu_T[1]); + } } - if (insn & (1 << 12)) - gen_op_sllx(); - else - gen_op_sll(); gen_movl_T0_reg(rd); } else if (xop == 0x26) { /* srl, V9 srlx */ rs1 = GET_FIELD(insn, 13, 17); gen_movl_reg_T0(rs1); if (IS_IMM) { /* immediate */ rs2 = GET_FIELDs(insn, 20, 31); - gen_movl_simm_T1(rs2); + if (insn & (1 << 12)) { + tcg_gen_shri_i64(cpu_T[0], cpu_T[0], rs2 & 0x3f); + } else { + tcg_gen_andi_i64(cpu_T[0], cpu_T[0], 0xffffffffULL); + tcg_gen_shri_i64(cpu_T[0], cpu_T[0], rs2 & 0x1f); + } } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); gen_movl_reg_T1(rs2); + if (insn & (1 << 12)) { + tcg_gen_andi_i64(cpu_T[1], cpu_T[1], 0x3f); + tcg_gen_shr_i64(cpu_T[0], cpu_T[0], cpu_T[1]); + } else { + tcg_gen_andi_i64(cpu_T[1], cpu_T[1], 0x1f); + tcg_gen_andi_i64(cpu_T[0], cpu_T[0], 0xffffffffULL); + tcg_gen_shr_i64(cpu_T[0], cpu_T[0], cpu_T[1]); + } } - if (insn & (1 << 12)) - gen_op_srlx(); - else - gen_op_srl(); gen_movl_T0_reg(rd); } else if (xop == 0x27) { /* sra, V9 srax */ rs1 = GET_FIELD(insn, 13, 17); gen_movl_reg_T0(rs1); if (IS_IMM) { /* immediate */ rs2 = GET_FIELDs(insn, 20, 31); - gen_movl_simm_T1(rs2); + if (insn & (1 << 12)) { + tcg_gen_sari_i64(cpu_T[0], cpu_T[0], rs2 & 0x3f); + } else { + tcg_gen_andi_i64(cpu_T[0], cpu_T[0], 0xffffffffULL); + tcg_gen_ext_i32_i64(cpu_T[0], cpu_T[0]); + tcg_gen_sari_i64(cpu_T[0], cpu_T[0], rs2 & 0x1f); + } } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); gen_movl_reg_T1(rs2); + if (insn & (1 << 12)) { + tcg_gen_andi_i64(cpu_T[1], cpu_T[1], 0x3f); + tcg_gen_sar_i64(cpu_T[0], cpu_T[0], cpu_T[1]); + } else { + tcg_gen_andi_i64(cpu_T[1], cpu_T[1], 0x1f); + tcg_gen_andi_i64(cpu_T[0], cpu_T[0], 0xffffffffULL); + tcg_gen_sar_i64(cpu_T[0], cpu_T[0], cpu_T[1]); + } } - if (insn & (1 << 12)) - gen_op_srax(); - else - gen_op_sra(); gen_movl_T0_reg(rd); #endif } else if (xop < 0x36) { @@ -2173,17 +2063,17 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_add_T1_T0(); break; case 0x1: - gen_op_and_T1_T0(); + tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]); if (xop & 0x10) gen_op_logic_T0_cc(); break; case 0x2: - gen_op_or_T1_T0(); + tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]); if (xop & 0x10) gen_op_logic_T0_cc(); break; case 0x3: - gen_op_xor_T1_T0(); + tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]); if (xop & 0x10) gen_op_logic_T0_cc(); break; @@ -2191,7 +2081,7 @@ static void disas_sparc_insn(DisasContext * dc) if (xop & 0x10) gen_op_sub_T1_T0_cc(); else - gen_op_sub_T1_T0(); + tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); break; case 0x5: gen_op_andn_T1_T0(); @@ -2216,7 +2106,7 @@ static void disas_sparc_insn(DisasContext * dc) break; #ifdef TARGET_SPARC64 case 0x9: /* V9 mulx */ - gen_op_mulx_T1_T0(); + tcg_gen_mul_i64(cpu_T[0], cpu_T[0], cpu_T[1]); break; #endif case 0xa: @@ -2280,15 +2170,18 @@ static void disas_sparc_insn(DisasContext * dc) break; #ifndef TARGET_SPARC64 case 0x25: /* sll */ - gen_op_sll(); + tcg_gen_andi_i32(cpu_T[1], cpu_T[1], 0x1f); + tcg_gen_shl_i32(cpu_T[0], cpu_T[0], cpu_T[1]); gen_movl_T0_reg(rd); break; case 0x26: /* srl */ - gen_op_srl(); + tcg_gen_andi_i32(cpu_T[1], cpu_T[1], 0x1f); + tcg_gen_shr_i32(cpu_T[0], cpu_T[0], cpu_T[1]); gen_movl_T0_reg(rd); break; case 0x27: /* sra */ - gen_op_sra(); + tcg_gen_andi_i32(cpu_T[1], cpu_T[1], 0x1f); + tcg_gen_sar_i32(cpu_T[0], cpu_T[0], cpu_T[1]); gen_movl_T0_reg(rd); break; #endif @@ -2329,7 +2222,7 @@ static void disas_sparc_insn(DisasContext * dc) case 0xf: /* V9 sir, nop if user */ #if !defined(CONFIG_USER_ONLY) if (supervisor(dc)) - gen_op_sir(); + ; // XXX #endif break; case 0x13: /* Graphics Status */ @@ -2400,7 +2293,7 @@ static void disas_sparc_insn(DisasContext * dc) } #else gen_op_xor_T1_T0(); - gen_op_wrpsr(); + tcg_gen_helper_0_1(helper_wrpsr, cpu_T[0]); save_state(dc); gen_op_next_insn(); tcg_gen_exit_tb(0); @@ -2434,8 +2327,8 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr)); break; case 6: // pstate - gen_op_wrpstate(); save_state(dc); + tcg_gen_helper_0_1(helper_wrpstate, cpu_T[0]); gen_op_next_insn(); tcg_gen_exit_tb(0); dc->is_br = 1; @@ -2476,7 +2369,8 @@ static void disas_sparc_insn(DisasContext * dc) goto illegal_insn; } #else - gen_op_wrwim(); + tcg_gen_andi_i32(cpu_T[0], cpu_T[0], ((1 << NWINDOWS) - 1)); + gen_op_movl_env_T0(offsetof(CPUSPARCState, wim)); #endif } break; @@ -2564,7 +2458,8 @@ static void disas_sparc_insn(DisasContext * dc) rs2 = GET_FIELD_SP(insn, 0, 4); gen_movl_reg_T1(rs2); } - gen_op_popc(); + tcg_gen_helper_1_1(helper_popc, cpu_T[0], + cpu_T[1]); gen_movl_T0_reg(rd); } case 0x2f: /* V9 movr */ @@ -3003,14 +2898,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_movl_reg_T0(rs1); if (IS_IMM) { /* immediate */ rs2 = GET_FIELDs(insn, 19, 31); -#if defined(OPTIM) - if (rs2) { -#endif - gen_movl_simm_T1(rs2); - gen_op_add_T1_T0(); -#if defined(OPTIM) - } -#endif + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], (int)rs2); } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); #if defined(OPTIM) @@ -3025,7 +2913,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_restore(); gen_mov_pc_npc(dc); gen_op_check_align_T0_3(); - gen_op_movl_npc_T0(); + tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUSPARCState, npc)); dc->npc = DYNAMIC_PC; goto jmp_insn; #endif @@ -3034,14 +2922,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_movl_reg_T0(rs1); if (IS_IMM) { /* immediate */ rs2 = GET_FIELDs(insn, 19, 31); -#if defined(OPTIM) - if (rs2) { -#endif - gen_movl_simm_T1(rs2); - gen_op_add_T1_T0(); -#if defined(OPTIM) - } -#endif + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], (int)rs2); } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); #if defined(OPTIM) @@ -3057,20 +2938,12 @@ static void disas_sparc_insn(DisasContext * dc) case 0x38: /* jmpl */ { if (rd != 0) { -#ifdef TARGET_SPARC64 - if (dc->pc == (uint32_t)dc->pc) { - gen_op_movl_T1_im(dc->pc); - } else { - gen_op_movq_T1_im64(dc->pc >> 32, dc->pc); - } -#else - gen_op_movl_T1_im(dc->pc); -#endif + tcg_gen_movi_tl(cpu_T[1], dc->pc); gen_movl_T1_reg(rd); } gen_mov_pc_npc(dc); gen_op_check_align_T0_3(); - gen_op_movl_npc_T0(); + tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUSPARCState, npc)); dc->npc = DYNAMIC_PC; } goto jmp_insn; @@ -3081,14 +2954,14 @@ static void disas_sparc_insn(DisasContext * dc) goto priv_insn; gen_mov_pc_npc(dc); gen_op_check_align_T0_3(); - gen_op_movl_npc_T0(); + tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUSPARCState, npc)); dc->npc = DYNAMIC_PC; - gen_op_rett(); + tcg_gen_helper_0_0(helper_rett); } goto jmp_insn; #endif case 0x3b: /* flush */ - gen_op_flush_T0(); + tcg_gen_helper_0_1(helper_flush, cpu_T[0]); break; case 0x3c: /* save */ save_state(dc); @@ -3109,14 +2982,14 @@ static void disas_sparc_insn(DisasContext * dc) goto priv_insn; dc->npc = DYNAMIC_PC; dc->pc = DYNAMIC_PC; - gen_op_done(); + tcg_gen_helper_0_0(helper_done); goto jmp_insn; case 1: if (!supervisor(dc)) goto priv_insn; dc->npc = DYNAMIC_PC; dc->pc = DYNAMIC_PC; - gen_op_retry(); + tcg_gen_helper_0_0(helper_retry); goto jmp_insn; default: goto illegal_insn; @@ -3144,14 +3017,7 @@ static void disas_sparc_insn(DisasContext * dc) } else if (IS_IMM) { /* immediate */ rs2 = GET_FIELDs(insn, 19, 31); -#if defined(OPTIM) - if (rs2 != 0) { -#endif - gen_movl_simm_T1(rs2); - gen_op_add_T1_T0(); -#if defined(OPTIM) - } -#endif + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], (int)rs2); } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); #if defined(OPTIM) @@ -3167,42 +3033,58 @@ static void disas_sparc_insn(DisasContext * dc) (xop > 0x17 && xop <= 0x1d ) || (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) { switch (xop) { - case 0x0: /* load word */ + case 0x0: /* load unsigned word */ gen_op_check_align_T0_3(); -#ifndef TARGET_SPARC64 - gen_op_ldst(ld); -#else - gen_op_ldst(lduw); -#endif + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_ld32u(cpu_T[1], cpu_T[0], dc->mem_idx); break; case 0x1: /* load unsigned byte */ - gen_op_ldst(ldub); + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_ld8u(cpu_T[1], cpu_T[0], dc->mem_idx); break; case 0x2: /* load unsigned halfword */ gen_op_check_align_T0_1(); - gen_op_ldst(lduh); + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_ld16u(cpu_T[1], cpu_T[0], dc->mem_idx); break; case 0x3: /* load double word */ if (rd & 1) goto illegal_insn; - gen_op_check_align_T0_7(); - gen_op_ldst(ldd); - gen_movl_T0_reg(rd + 1); + else { + TCGv r_dword; + + r_dword = tcg_temp_new(TCG_TYPE_I64); + gen_op_check_align_T0_7(); + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_ld64(r_dword, cpu_T[0], dc->mem_idx); + tcg_gen_trunc_i64_i32(cpu_T[0], r_dword); + gen_movl_T0_reg(rd + 1); + tcg_gen_shri_i64(r_dword, r_dword, 32); + tcg_gen_trunc_i64_i32(cpu_T[1], r_dword); + } break; case 0x9: /* load signed byte */ - gen_op_ldst(ldsb); + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_ld8s(cpu_T[1], cpu_T[0], dc->mem_idx); break; case 0xa: /* load signed halfword */ gen_op_check_align_T0_1(); - gen_op_ldst(ldsh); + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_ld16s(cpu_T[1], cpu_T[0], dc->mem_idx); break; case 0xd: /* ldstub -- XXX: should be atomically */ - gen_op_ldst(ldstub); + tcg_gen_movi_i32(cpu_tmp0, 0xff); + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_ld8s(cpu_T[1], cpu_T[0], dc->mem_idx); + tcg_gen_qemu_st8(cpu_tmp0, cpu_T[0], dc->mem_idx); break; case 0x0f: /* swap register with memory. Also atomically */ gen_op_check_align_T0_3(); gen_movl_reg_T1(rd); - gen_op_ldst(swap); + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_ld32u(cpu_tmp0, cpu_T[0], dc->mem_idx); + tcg_gen_qemu_st32(cpu_T[1], cpu_T[0], dc->mem_idx); + tcg_gen_mov_i32(cpu_T[1], cpu_tmp0); break; #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) case 0x10: /* load word alternate */ @@ -3297,11 +3179,13 @@ static void disas_sparc_insn(DisasContext * dc) #ifdef TARGET_SPARC64 case 0x08: /* V9 ldsw */ gen_op_check_align_T0_3(); - gen_op_ldst(ldsw); + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_ld32s(cpu_T[1], cpu_T[0], dc->mem_idx); break; case 0x0b: /* V9 ldx */ gen_op_check_align_T0_7(); - gen_op_ldst(ldx); + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_ld64(cpu_T[1], cpu_T[0], dc->mem_idx); break; case 0x18: /* V9 ldswa */ gen_op_check_align_T0_3(); @@ -3374,27 +3258,37 @@ static void disas_sparc_insn(DisasContext * dc) xop == 0xe || xop == 0x1e) { gen_movl_reg_T1(rd); switch (xop) { - case 0x4: + case 0x4: /* store word */ gen_op_check_align_T0_3(); - gen_op_ldst(st); + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_st32(cpu_T[1], cpu_T[0], dc->mem_idx); break; - case 0x5: - gen_op_ldst(stb); + case 0x5: /* store byte */ + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_st8(cpu_T[1], cpu_T[0], dc->mem_idx); break; - case 0x6: + case 0x6: /* store halfword */ gen_op_check_align_T0_1(); - gen_op_ldst(sth); + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_st16(cpu_T[1], cpu_T[0], dc->mem_idx); break; - case 0x7: + case 0x7: /* store double word */ if (rd & 1) goto illegal_insn; - gen_op_check_align_T0_7(); - flush_T2(dc); - gen_movl_reg_T2(rd + 1); - gen_op_ldst(std); + else { + TCGv r_dword, r_low; + + gen_op_check_align_T0_7(); + r_dword = tcg_temp_new(TCG_TYPE_I64); + r_low = tcg_temp_new(TCG_TYPE_I32); + gen_movl_reg_TN(rd + 1, r_low); + tcg_gen_helper_1_2(helper_pack64, r_dword, cpu_T[1], + r_low); + tcg_gen_qemu_st64(r_dword, cpu_T[0], dc->mem_idx); + } break; #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) - case 0x14: + case 0x14: /* store word alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; @@ -3404,7 +3298,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_check_align_T0_3(); gen_st_asi(insn, 4); break; - case 0x15: + case 0x15: /* store byte alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; @@ -3413,7 +3307,7 @@ static void disas_sparc_insn(DisasContext * dc) #endif gen_st_asi(insn, 1); break; - case 0x16: + case 0x16: /* store halfword alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; @@ -3423,7 +3317,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_check_align_T0_1(); gen_st_asi(insn, 2); break; - case 0x17: + case 0x17: /* store double word alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; @@ -3432,16 +3326,41 @@ static void disas_sparc_insn(DisasContext * dc) #endif if (rd & 1) goto illegal_insn; - gen_op_check_align_T0_7(); - flush_T2(dc); - gen_movl_reg_T2(rd + 1); - gen_stda_asi(insn); + else { + int asi; + TCGv r_dword, r_temp, r_size; + + gen_op_check_align_T0_7(); + r_dword = tcg_temp_new(TCG_TYPE_I64); + r_temp = tcg_temp_new(TCG_TYPE_I32); + r_size = tcg_temp_new(TCG_TYPE_I32); + gen_movl_reg_TN(rd + 1, r_temp); + tcg_gen_helper_1_2(helper_pack64, r_dword, cpu_T[1], + r_temp); +#ifdef TARGET_SPARC64 + if (IS_IMM) { + int offset; + + offset = GET_FIELD(insn, 25, 31); + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset); + tcg_gen_ld_i32(r_dword, cpu_env, offsetof(CPUSPARCState, asi)); + } else { +#endif + asi = GET_FIELD(insn, 19, 26); + tcg_gen_movi_i32(r_temp, asi); +#ifdef TARGET_SPARC64 + } +#endif + tcg_gen_movi_i32(r_size, 8); + tcg_gen_helper_0_4(helper_st_asi, cpu_T[0], r_dword, r_temp, r_size); + } break; #endif #ifdef TARGET_SPARC64 case 0x0e: /* V9 stx */ gen_op_check_align_T0_7(); - gen_op_ldst(stx); + ABI32_MASK(cpu_T[0]); + tcg_gen_qemu_st64(cpu_T[1], cpu_T[0], dc->mem_idx); break; case 0x1e: /* V9 stxa */ gen_op_check_align_T0_7(); @@ -3522,16 +3441,12 @@ static void disas_sparc_insn(DisasContext * dc) break; case 0x3c: /* V9 casa */ gen_op_check_align_T0_3(); - flush_T2(dc); - gen_movl_reg_T2(rd); - gen_cas_asi(insn); + gen_cas_asi(insn, rd); gen_movl_T1_reg(rd); break; case 0x3e: /* V9 casxa */ gen_op_check_align_T0_7(); - flush_T2(dc); - gen_movl_reg_T2(rd); - gen_casx_asi(insn); + gen_casx_asi(insn, rd); gen_movl_T1_reg(rd); break; #else @@ -3597,6 +3512,10 @@ static void disas_sparc_insn(DisasContext * dc) #endif } +static void tcg_macro_func(TCGContext *s, int macro_id, const int *dead_args) +{ +} + static inline int gen_intermediate_code_internal(TranslationBlock * tb, int spc, CPUSPARCState *env) { @@ -3615,13 +3534,16 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, dc->fpu_enabled = cpu_fpu_enabled(env); gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; + cpu_tmp0 = tcg_temp_new(TCG_TYPE_TL); + cpu_regwptr = tcg_temp_new(TCG_TYPE_PTR); // XXX + do { if (env->nb_breakpoints > 0) { for(j = 0; j < env->nb_breakpoints; j++) { if (env->breakpoints[j] == dc->pc) { if (dc->pc != pc_start) save_state(dc); - gen_op_debug(); + tcg_gen_helper_0_0(helper_debug); tcg_gen_exit_tb(0); dc->is_br = 1; goto exit_gen_loop; @@ -3748,6 +3670,7 @@ CPUSPARCState *cpu_sparc_init(const char *cpu_model) { CPUSPARCState *env; const sparc_def_t *def; + static int inited; def = cpu_sparc_find_by_name(cpu_model); if (!def) @@ -3769,6 +3692,28 @@ CPUSPARCState *cpu_sparc_init(const char *cpu_model) env->mmuregs[0] |= def->mmu_version; cpu_sparc_set_id(env, 0); #endif + + /* init various static tables */ + if (!inited) { + inited = 1; + + tcg_set_macro_func(&tcg_ctx, tcg_macro_func); + cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env"); + //#if TARGET_LONG_BITS > HOST_LONG_BITS +#ifdef TARGET_SPARC64 + cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL, + TCG_AREG0, offsetof(CPUState, t0), "T0"); + cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL, + TCG_AREG0, offsetof(CPUState, t1), "T1"); + cpu_T[2] = tcg_global_mem_new(TCG_TYPE_TL, + TCG_AREG0, offsetof(CPUState, t2), "T2"); +#else + cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG1, "T0"); + cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1"); + cpu_T[2] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "T2"); +#endif + } + cpu_reset(env); return env; |