e2k: Move TCG translation parts into single file.

The TCG translation was splitted into multiple files and
it was painful because it has a lot of cross references.

Reorg FX helpers.

Signed-off-by: Denis Drakhnya <numas13@gmail.com>
This commit is contained in:
Denis Drakhnia 2021-03-05 18:47:33 +02:00 committed by Denis Drakhnia
parent 17be44b21b
commit 6fb98e718e
16 changed files with 5846 additions and 6810 deletions

View File

@ -2375,7 +2375,7 @@ static void handle_query_e2k_tags_read(GArray *params, void *user_ctx)
} }
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
int tag = (tags >> i * E2K_TAG_SIZE) & 0x3; int tag = (tags >> (i * 2)) & 0x3;
g_string_append_c(gdbserver_state.str_buf, tag); g_string_append_c(gdbserver_state.str_buf, tag);
} }

View File

@ -883,6 +883,10 @@ typedef enum {
ARGS_XDX = args3(X, D, X), ARGS_XDX = args3(X, D, X),
ARGS_XXS = args3(X, X, S), ARGS_XXS = args3(X, X, S),
ARGS_XXD = args3(X, X, D), ARGS_XXD = args3(X, X, D),
ARGS_SXS = args3(S, X, S),
ARGS_DXD = args3(D, X, D),
ARGS_SXX = args3(S, X, X),
ARGS_DXX = args3(D, X, X),
ARGS_XXX = args3(X, X, X), ARGS_XXX = args3(X, X, X),
ARGS_QSS = args3(Q, S, S), ARGS_QSS = args3(Q, S, S),
ARGS_QSD = args3(Q, S, D), ARGS_QSD = args3(Q, S, D),
@ -1024,15 +1028,15 @@ static AlopDesc alops[] = {
{ X(OP_FXDIVXX), ALOPF1, ARGS_XXX, SHORT, 0x4f, 1, -1, CHAN_5, { -1 } }, { X(OP_FXDIVXX), ALOPF1, ARGS_XXX, SHORT, 0x4f, 1, -1, CHAN_5, { -1 } },
{ X(OP_FXDIVXD), ALOPF1, ARGS_XXD, SHORT, 0x4d, 1, -1, CHAN_5, { -1 } }, { X(OP_FXDIVXD), ALOPF1, ARGS_XXD, SHORT, 0x4d, 1, -1, CHAN_5, { -1 } },
{ X(OP_FXDIVXS), ALOPF1, ARGS_XXS, SHORT, 0x4c, 1, -1, CHAN_5, { -1 } }, { X(OP_FXDIVXS), ALOPF1, ARGS_XXS, SHORT, 0x4c, 1, -1, CHAN_5, { -1 } },
{ X(OP_FXDIVTSS), ALOPF1, ARGS_XSS, SHORT, 0x60, 1, -1, CHAN_5, { -1 } }, { X(OP_FXDIVTSS), ALOPF1, ARGS_SXS, SHORT, 0x60, 1, -1, CHAN_5, { -1 } },
{ X(OP_FXDIVTDD), ALOPF1, ARGS_XDD, SHORT, 0x61, 1, -1, CHAN_5, { -1 } }, { X(OP_FXDIVTDD), ALOPF1, ARGS_DXD, SHORT, 0x61, 1, -1, CHAN_5, { -1 } },
{ X(OP_FXDIVTSX), ALOPF1, ARGS_XSX, SHORT, 0x62, 1, -1, CHAN_5, { -1 } }, { X(OP_FXDIVTSX), ALOPF1, ARGS_SXX, SHORT, 0x62, 1, -1, CHAN_5, { -1 } },
{ X(OP_FXDIVTDX), ALOPF1, ARGS_XDX, SHORT, 0x63, 1, -1, CHAN_5, { -1 } }, { X(OP_FXDIVTDX), ALOPF1, ARGS_DXX, SHORT, 0x63, 1, -1, CHAN_5, { -1 } },
{ X(OP_FXSQRTUSX), ALOPF1, ARGS_XSX, SHORT, 0x5a, 1, -1, CHAN_5, { -1 } }, { X(OP_FXSQRTUSX), ALOPF1, ARGS_SXX, SHORT, 0x5a, 1, -1, CHAN_5, { -1 } },
{ X(OP_FXSQRTUDX), ALOPF1, ARGS_XDX, SHORT, 0x5b, 1, -1, CHAN_5, { -1 } }, { X(OP_FXSQRTUDX), ALOPF1, ARGS_DXX, SHORT, 0x5b, 1, -1, CHAN_5, { -1 } },
{ X(OP_FXSQRTUXX), ALOPF1, ARGS_XXX, SHORT, 0x59, 1, -1, CHAN_5, { -1 } }, { X(OP_FXSQRTUXX), ALOPF1, ARGS_XXX, SHORT, 0x59, 1, -1, CHAN_5, { -1 } },
{ X(OP_FXSQRTTSX), ALOPF1, ARGS_XSX, SHORT, 0x5e, 1, -1, CHAN_5, { -1 } }, { X(OP_FXSQRTTSX), ALOPF1, ARGS_SXX, SHORT, 0x5e, 1, -1, CHAN_5, { -1 } },
{ X(OP_FXSQRTTDX), ALOPF1, ARGS_XDX, SHORT, 0x5f, 1, -1, CHAN_5, { -1 } }, { X(OP_FXSQRTTDX), ALOPF1, ARGS_DXX, SHORT, 0x5f, 1, -1, CHAN_5, { -1 } },
{ X(OP_FXSQRTTXX), ALOPF1, ARGS_XXX, SHORT, 0x5d, 1, -1, CHAN_5, { -1 } }, { X(OP_FXSQRTTXX), ALOPF1, ARGS_XXX, SHORT, 0x5d, 1, -1, CHAN_5, { -1 } },
{ X(OP_MOVIF), ALOPF1, ARGS_DSX, SHORT, 0x5e, 1, -1, CHAN_14, { -1 } }, { X(OP_MOVIF), ALOPF1, ARGS_DSX, SHORT, 0x5e, 1, -1, CHAN_14, { -1 } },
{ X(OP_VFSI), ALOPF1, ARGS_SDD, SHORT, 0x63, 1, -1, CHAN_14, { -1 } }, { X(OP_VFSI), ALOPF1, ARGS_SDD, SHORT, 0x63, 1, -1, CHAN_14, { -1 } },

View File

@ -34,10 +34,13 @@ void e2k_tcg_initialize(void);
#define MMU_USER_IDX 1 #define MMU_USER_IDX 1
#define CPU_RESOLVING_TYPE TYPE_E2K_CPU #define CPU_RESOLVING_TYPE TYPE_E2K_CPU
#define E2K_TAG_SIZE 2 /* 2-bit tag for 32-bit value */
#define E2K_REG_LEN sizeof(uint64_t) #define E2K_REG_LEN sizeof(uint64_t)
#define E2K_REG_SIZE (E2K_REG_LEN * 8) #define E2K_REG_SIZE (E2K_REG_LEN * 8)
#define E2K_REG_TAGS_SIZE (E2K_TAG_SIZE * 2) /* two tags for 32-bit halves */
#define E2K_TAG_MASK_32 0x03
#define E2K_TAG_MASK_64 0x0f
#define E2K_TAG_MASK_80 E2K_TAG_MASK_64
#define E2K_TAG_MASK_128 0xff
#define E2K_WR_COUNT 64 /* %rN [0, 64) */ #define E2K_WR_COUNT 64 /* %rN [0, 64) */
#define E2K_BR_COUNT 128 /* %b[N] [0, 128) */ #define E2K_BR_COUNT 128 /* %b[N] [0, 128) */
@ -710,7 +713,7 @@ typedef struct CPUArchState {
/* temporaries for FX/SIMD ops */ /* temporaries for FX/SIMD ops */
E2KReg t0, t1, t2, t3; E2KReg t0, t1, t2, t3;
E2KReg tmp[3]; E2KReg tmp[8];
E2KReg al_result[6]; E2KReg al_result[6];
/* DAM */ /* DAM */

View File

@ -2,7 +2,6 @@
#include "qemu/log.h" #include "qemu/log.h"
#include "qemu/host-utils.h" #include "qemu/host-utils.h"
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "translate.h"
void helper_signal_frame(CPUE2KState *env, int wbs, target_ulong ret_ip); void helper_signal_frame(CPUE2KState *env, int wbs, target_ulong ret_ip);

View File

@ -10,22 +10,19 @@
#define dh_is_signed_f80 dh_is_signed_ptr #define dh_is_signed_f80 dh_is_signed_ptr
DEF_HELPER_2(raise_exception, noreturn, env, int) DEF_HELPER_2(raise_exception, noreturn, env, int)
DEF_HELPER_1(syscall, noreturn, env)
DEF_HELPER_1(break_restore_state, void, env)
DEF_HELPER_1(expand_stacks, void, env)
DEF_HELPER_4(call, void, env, i64, int, tl)
DEF_HELPER_2(prep_return, i64, env, int) DEF_HELPER_2(prep_return, i64, env, int)
DEF_HELPER_1(return, void, env) DEF_HELPER_1(return, void, env)
DEF_HELPER_1(signal_return, void, env) DEF_HELPER_1(signal_return, void, env)
DEF_HELPER_4(call, void, env, i64, int, tl)
DEF_HELPER_1(expand_stacks, void, env)
DEF_HELPER_1(syscall, void, env)
DEF_HELPER_2(sxt, i64, i64, i32)
DEF_HELPER_2(state_reg_read_i64, i64, env, int)
DEF_HELPER_2(state_reg_read_i32, i32, env, int)
DEF_HELPER_3(state_reg_write_i64, void, env, int, i64)
DEF_HELPER_3(state_reg_write_i32, void, env, int, i32)
DEF_HELPER_2(getsp, i64, env, i32) /* FIXME: return tl? */
DEF_HELPER_1(break_restore_state, void, env)
DEF_HELPER_4(setwd, void, env, int, int, int) DEF_HELPER_4(setwd, void, env, int, int, int)
DEF_HELPER_2(probe_read_access, int, env, tl)
DEF_HELPER_2(probe_write_access, int, env, tl) DEF_HELPER_FLAGS_2(probe_read_access, TCG_CALL_NO_RWG, int, env, tl)
DEF_HELPER_FLAGS_2(probe_write_access, TCG_CALL_NO_RWG, int, env, tl)
DEF_HELPER_1(aau_load_program, void, env) DEF_HELPER_1(aau_load_program, void, env)
DEF_HELPER_4(mova_ptr, tl, env, int, int, int) DEF_HELPER_4(mova_ptr, tl, env, int, int, int)
@ -33,214 +30,259 @@ DEF_HELPER_3(aau_am, void, env, int, int)
DEF_HELPER_4(dam_lock_addr, void, env, i64, int, int) DEF_HELPER_4(dam_lock_addr, void, env, i64, int, int)
DEF_HELPER_4(dam_unlock_addr, int, env, i64, int, int) DEF_HELPER_4(dam_unlock_addr, int, env, i64, int, int)
DEF_HELPER_2(getsp, i64, env, i32)
DEF_HELPER_FLAGS_2(rrd, TCG_CALL_NO_WG_SE, i64, env, int)
DEF_HELPER_3(rwd, void, env, int, i64)
DEF_HELPER_3(rws, void, env, int, i32)
DEF_HELPER_FLAGS_2(sxt, TCG_CALL_NO_RWG_SE, i64, i64, i32)
/* Packed Min/Max */ /* Packed Min/Max */
DEF_HELPER_2(pminub, i64, i64, i64) DEF_HELPER_FLAGS_2(pminub, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pminsb, i64, i64, i64) DEF_HELPER_FLAGS_2(pminsb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pminuh, i64, i64, i64) DEF_HELPER_FLAGS_2(pminuh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pminsh, i64, i64, i64) DEF_HELPER_FLAGS_2(pminsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pminuw, i64, i64, i64) DEF_HELPER_FLAGS_2(pminuw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pminsw, i64, i64, i64) DEF_HELPER_FLAGS_2(pminsw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmaxub, i64, i64, i64) DEF_HELPER_FLAGS_2(pmaxub, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmaxsb, i64, i64, i64) DEF_HELPER_FLAGS_2(pmaxsb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmaxuh, i64, i64, i64) DEF_HELPER_FLAGS_2(pmaxuh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmaxsh, i64, i64, i64) DEF_HELPER_FLAGS_2(pmaxsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmaxuw, i64, i64, i64) DEF_HELPER_FLAGS_2(pmaxuw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmaxsw, i64, i64, i64) DEF_HELPER_FLAGS_2(pmaxsw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed Cmp */ /* Packed Cmp */
DEF_HELPER_2(pcmpeqb, i64, i64, i64) DEF_HELPER_FLAGS_2(pcmpeqb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pcmpeqh, i64, i64, i64) DEF_HELPER_FLAGS_2(pcmpeqh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pcmpeqw, i64, i64, i64) DEF_HELPER_FLAGS_2(pcmpeqw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pcmpeqd, i64, i64, i64) DEF_HELPER_FLAGS_2(pcmpeqd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pcmpgtb, i64, i64, i64) DEF_HELPER_FLAGS_2(pcmpgtb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pcmpgth, i64, i64, i64) DEF_HELPER_FLAGS_2(pcmpgth, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pcmpgtw, i64, i64, i64) DEF_HELPER_FLAGS_2(pcmpgtw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pcmpgtd, i64, i64, i64) DEF_HELPER_FLAGS_2(pcmpgtd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Pached Horizontal Add */ /* Pached Horizontal Add */
DEF_HELPER_2(phaddh, i64, i64, i64) DEF_HELPER_FLAGS_2(phaddh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(phaddw, i64, i64, i64) DEF_HELPER_FLAGS_2(phaddw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(phaddsh, i64, i64, i64) DEF_HELPER_FLAGS_2(phaddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed Horizontal Sub */ /* Packed Horizontal Sub */
DEF_HELPER_2(phsubh, i64, i64, i64) DEF_HELPER_FLAGS_2(phsubh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(phsubw, i64, i64, i64) DEF_HELPER_FLAGS_2(phsubw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(phsubsh, i64, i64, i64) DEF_HELPER_FLAGS_2(phsubsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed Add using saturation */ /* Packed Add using saturation */
DEF_HELPER_2(paddsb, i64, i64, i64) DEF_HELPER_FLAGS_2(paddsb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(paddsh, i64, i64, i64) DEF_HELPER_FLAGS_2(paddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(paddusb, i64, i64, i64) DEF_HELPER_FLAGS_2(paddusb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(paddush, i64, i64, i64) DEF_HELPER_FLAGS_2(paddush, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed Sub using saturation */ /* Packed Sub using saturation */
DEF_HELPER_2(psubsb, i64, i64, i64) DEF_HELPER_FLAGS_2(psubsb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(psubsh, i64, i64, i64) DEF_HELPER_FLAGS_2(psubsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(psubusb, i64, i64, i64) DEF_HELPER_FLAGS_2(psubusb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(psubush, i64, i64, i64) DEF_HELPER_FLAGS_2(psubush, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed shifts */ /* Packed shifts */
DEF_HELPER_2(psllh, i64, i64, i64) DEF_HELPER_FLAGS_2(psllh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(psllw, i64, i64, i64) DEF_HELPER_FLAGS_2(psllw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(psrlh, i64, i64, i64) DEF_HELPER_FLAGS_2(psrlh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(psrlw, i64, i64, i64) DEF_HELPER_FLAGS_2(psrlw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed shifts with sign */ /* Packed shifts with sign */
DEF_HELPER_2(psrah, i64, i64, i64) DEF_HELPER_FLAGS_2(psrah, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(psraw, i64, i64, i64) DEF_HELPER_FLAGS_2(psraw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed Mul */ /* Packed Mul */
DEF_HELPER_2(pmaddh, i64, i64, i64) DEF_HELPER_FLAGS_2(pmaddh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmaddubsh, i64, i64, i64) DEF_HELPER_FLAGS_2(pmaddubsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmulhh, i64, i64, i64) DEF_HELPER_FLAGS_2(pmulhh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmullh, i64, i64, i64) DEF_HELPER_FLAGS_2(pmullh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmulhuh, i64, i64, i64) DEF_HELPER_FLAGS_2(pmulhuh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmulubhh, i64, i64, i64) DEF_HELPER_FLAGS_2(pmulubhh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmulhrsh, i64, i64, i64) DEF_HELPER_FLAGS_2(pmulhrsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed Sign Mul */ /* Packed Sign Mul */
DEF_HELPER_2(psignb, i64, i64, i64) DEF_HELPER_FLAGS_2(psignb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(psignh, i64, i64, i64) DEF_HELPER_FLAGS_2(psignh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(psignw, i64, i64, i64) DEF_HELPER_FLAGS_2(psignw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed Move Mask */ /* Packed Move Mask */
DEF_HELPER_2(pmovmskb, i64, i64, i64) DEF_HELPER_FLAGS_2(pmovmskb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmovmskps, i64, i64, i64) DEF_HELPER_FLAGS_2(pmovmskps, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pmovmskpd, i64, i64, i64) DEF_HELPER_FLAGS_2(pmovmskpd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed packs */ /* Packed packs */
DEF_HELPER_2(packsshb, i64, i64, i64) DEF_HELPER_FLAGS_2(packsshb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(packushb, i64, i64, i64) DEF_HELPER_FLAGS_2(packushb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(packsswh, i64, i64, i64) DEF_HELPER_FLAGS_2(packsswh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(packuswh, i64, i64, i64) DEF_HELPER_FLAGS_2(packuswh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed unpacks */ /* Packed unpacks */
DEF_HELPER_2(punpcklbh, i64, i64, i64) DEF_HELPER_FLAGS_2(punpcklbh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(punpcklhw, i64, i64, i64) DEF_HELPER_FLAGS_2(punpcklhw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(punpcklwd, i64, i64, i64) DEF_HELPER_FLAGS_2(punpcklwd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(punpckhbh, i64, i64, i64) DEF_HELPER_FLAGS_2(punpckhbh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(punpckhhw, i64, i64, i64) DEF_HELPER_FLAGS_2(punpckhhw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(punpckhwd, i64, i64, i64) DEF_HELPER_FLAGS_2(punpckhwd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed shuffle */ /* Packed shuffle */
DEF_HELPER_3(pshufb, i64, i64, i64, i64) DEF_HELPER_FLAGS_3(pshufb, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
DEF_HELPER_3(pmerge, i64, i64, i64, i64) DEF_HELPER_FLAGS_3(pmerge, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
DEF_HELPER_2(pshufh, i64, i64, i32) DEF_HELPER_FLAGS_2(pshufh, TCG_CALL_NO_RWG_SE, i64, i64, i32)
DEF_HELPER_3(pshufw, i64, i64, i64, i32) DEF_HELPER_FLAGS_3(pshufw, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32)
/* Packed uncategorized */ /* Packed uncategorized */
DEF_HELPER_2(psadbw, i64, i64, i64) DEF_HELPER_FLAGS_2(psadbw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pavgusb, i64, i64, i64) DEF_HELPER_FLAGS_2(pavgusb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(pavgush, i64, i64, i64) DEF_HELPER_FLAGS_2(pavgush, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(phminposuh, i64, i64, i64) DEF_HELPER_FLAGS_2(phminposuh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_2(mpsadbh, i64, i64, i64) DEF_HELPER_FLAGS_2(mpsadbh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_4(plog, i64, i32, i64, i64, i64) DEF_HELPER_FLAGS_4(plog, TCG_CALL_NO_RWG_SE, i64, i32, i64, i64, i64)
/* Float 32/64 Ops */ /* Float 32/64 Ops */
#define DEF_HELPER_3_32_64(name) \ DEF_HELPER_FLAGS_3(fadds, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_3(name##s, i32, env, i32, i32) \ DEF_HELPER_FLAGS_3(fsubs, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_3(name##d, i64, env, i64, i64) DEF_HELPER_FLAGS_3(fmuls, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_3_32_64(fadd) DEF_HELPER_FLAGS_3(fdivs, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_3_32_64(fsub) DEF_HELPER_FLAGS_3(fmins, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_3_32_64(fmin) DEF_HELPER_FLAGS_3(fmaxs, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_3_32_64(fmax) DEF_HELPER_FLAGS_3(fscales, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_3_32_64(fmul)
DEF_HELPER_3_32_64(fdiv) DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(fscaled, i64, env, i64, i32) DEF_HELPER_FLAGS_3(fsubd, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(fscales, i32, env, i32, i32) DEF_HELPER_FLAGS_3(fmuld, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_2(frcps, i32, env, i32) DEF_HELPER_FLAGS_3(fdivd, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_2(fsqrts, i32, env, i32) DEF_HELPER_FLAGS_3(fmind, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_2(frsqrts, i32, env, i32) DEF_HELPER_FLAGS_3(fmaxd, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(fsqrttd, i64, env, i64, i64) DEF_HELPER_FLAGS_3(fscaled, TCG_CALL_NO_RWG, i64, env, i64, i32)
DEF_HELPER_FLAGS_2(frcps, TCG_CALL_NO_RWG, i32, env, i32)
DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_RWG, i32, env, i32)
DEF_HELPER_FLAGS_2(frsqrts, TCG_CALL_NO_RWG, i32, env, i32)
DEF_HELPER_FLAGS_3(fsqrttd, TCG_CALL_NO_RWG, i64, env, i64, i64)
/* Packed Float ops */ /* Packed Float ops */
DEF_HELPER_3(pfadds, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfadds, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfsubs, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfsubs, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfmuls, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfmuls, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfmaxs, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfmaxs, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfmins, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfmins, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfhadds, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfhadds, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfhsubs, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfhsubs, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfaddsubs, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfaddsubs, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfstoifs, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfstoifs, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_2(pistofs, i64, env, i64) DEF_HELPER_FLAGS_2(pistofs, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_2(pfstois, i64, env, i64) DEF_HELPER_FLAGS_2(pfstois, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_2(pfstoistr, i64, env, i64) DEF_HELPER_FLAGS_2(pfstoistr, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_3(pfcmpeqs, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfcmpeqs, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfcmplts, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfcmplts, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfcmples, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfcmples, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfcmpuods, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfcmpuods, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfcmpneqs, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfcmpneqs, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfcmpnlts, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfcmpnlts, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfcmpnles, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfcmpnles, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(pfcmpods, i64, env, i64, i64) DEF_HELPER_FLAGS_3(pfcmpods, TCG_CALL_NO_RWG, i64, env, i64, i64)
/* Float x80 ops */ /* Float x80 ops */
DEF_HELPER_3(fxaddxx, void, env, f80, f80) #define DEF_FX_OP2(op) \
DEF_HELPER_3(fxsubxx, void, env, f80, f80) DEF_HELPER_FLAGS_3(glue(op, ss), TCG_CALL_NO_RWG, i32, env, f80, i32) \
DEF_HELPER_3(fxrsubxx, void, env, f80, f80) DEF_HELPER_FLAGS_3(glue(op, dd), TCG_CALL_NO_RWG, i64, env, f80, i64) \
DEF_HELPER_3(fxmulxx, void, env, f80, f80) DEF_HELPER_FLAGS_4(glue(op, sx), TCG_CALL_NO_RWG, void, f80, env, f80, i32) \
DEF_HELPER_3(fxdivxx, void, env, f80, f80) DEF_HELPER_FLAGS_4(glue(op, dx), TCG_CALL_NO_RWG, void, f80, env, f80, i64) \
DEF_HELPER_3(fxscalesx, void, env, f80, i32) DEF_HELPER_FLAGS_4(glue(op, xx), TCG_CALL_NO_RWG, void, f80, env, f80, f80) \
DEF_HELPER_3(fxsqrttxx, void, env, f80, f80) DEF_HELPER_FLAGS_3(glue(op, xd), TCG_CALL_NO_RWG, i64, env, f80, f80) \
DEF_HELPER_FLAGS_3(glue(op, xs), TCG_CALL_NO_RWG, i32, env, f80, f80)
/* Float 32/64/80 Comparisons */ DEF_FX_OP2(fxadd)
#define DEF_HELPER_3_32_64_80(name) \ DEF_FX_OP2(fxsub)
DEF_HELPER_3_32_64(f##name) \ DEF_FX_OP2(fxmul)
DEF_HELPER_3(fx##name##x, i64, env, f80, f80) DEF_FX_OP2(fxdiv)
DEF_HELPER_3_32_64_80(cmpeq)
DEF_HELPER_3_32_64_80(cmpneq) #undef DEF_FX_OP2
DEF_HELPER_3_32_64_80(cmple)
DEF_HELPER_3_32_64_80(cmpnle) DEF_HELPER_FLAGS_3(fxdivtss, TCG_CALL_NO_RWG, f32, env, f32, f80)
DEF_HELPER_3_32_64_80(cmplt) DEF_HELPER_FLAGS_3(fxdivtdd, TCG_CALL_NO_RWG, f64, env, f64, f80)
DEF_HELPER_3_32_64_80(cmpnlt) DEF_HELPER_FLAGS_4(fxdivtsx, TCG_CALL_NO_RWG, void, f80, env, f32, f80)
DEF_HELPER_3_32_64_80(cmpuod) DEF_HELPER_FLAGS_4(fxdivtdx, TCG_CALL_NO_RWG, void, f80, env, f64, f80)
DEF_HELPER_3_32_64_80(cmpod)
DEF_HELPER_FLAGS_3(fxrsubss, TCG_CALL_NO_RWG, i32, env, f80, i32)
DEF_HELPER_FLAGS_3(fxrsubdd, TCG_CALL_NO_RWG, i64, env, f80, i64)
DEF_HELPER_FLAGS_4(fxrsubsx, TCG_CALL_NO_RWG, void, f80, env, f80, i32)
DEF_HELPER_FLAGS_4(fxrsubdx, TCG_CALL_NO_RWG, void, f80, env, f80, i64)
DEF_HELPER_FLAGS_4(fxsqrttsx, TCG_CALL_NO_RWG, void, f80, env, i32, f80)
DEF_HELPER_FLAGS_4(fxsqrttdx, TCG_CALL_NO_RWG, void, f80, env, i64, f80)
DEF_HELPER_FLAGS_4(fxsqrttxx, TCG_CALL_NO_RWG, void, f80, env, f80, f80)
DEF_HELPER_FLAGS_4(fxscalesx, TCG_CALL_NO_RWG, void, f80, env, f80, i32)
DEF_HELPER_FLAGS_3(fxcmpodsf, TCG_CALL_NO_RWG, i32, env, f80, f32)
DEF_HELPER_FLAGS_3(fxcmpudsf, TCG_CALL_NO_RWG, i32, env, f80, f32)
DEF_HELPER_FLAGS_3(fxcmpoddf, TCG_CALL_NO_RWG, i32, env, f80, f64)
DEF_HELPER_FLAGS_3(fxcmpuddf, TCG_CALL_NO_RWG, i32, env, f80, f64)
DEF_HELPER_FLAGS_3(fxcmpodxf, TCG_CALL_NO_RWG, i32, env, f80, f80)
DEF_HELPER_FLAGS_3(fxcmpudxf, TCG_CALL_NO_RWG, i32, env, f80, f80)
/* Float Comparisons */
#define DEF_HELPER_FP_CMP(P, S, R, A, B) \
DEF_HELPER_FLAGS_3(glue(glue(P, cmpeq), S), TCG_CALL_NO_RWG, R, env, A, B) \
DEF_HELPER_FLAGS_3(glue(glue(P, cmpneq), S), TCG_CALL_NO_RWG, R, env, A, B) \
DEF_HELPER_FLAGS_3(glue(glue(P, cmple), S), TCG_CALL_NO_RWG, R, env, A, B) \
DEF_HELPER_FLAGS_3(glue(glue(P, cmpnle), S), TCG_CALL_NO_RWG, R, env, A, B) \
DEF_HELPER_FLAGS_3(glue(glue(P, cmplt), S), TCG_CALL_NO_RWG, R, env, A, B) \
DEF_HELPER_FLAGS_3(glue(glue(P, cmpnlt), S), TCG_CALL_NO_RWG, R, env, A, B) \
DEF_HELPER_FLAGS_3(glue(glue(P, cmpuod), S), TCG_CALL_NO_RWG, R, env, A, B) \
DEF_HELPER_FLAGS_3(glue(glue(P, cmpod), S), TCG_CALL_NO_RWG, R, env, A, B)
DEF_HELPER_FP_CMP(f, s, i32, i32, i32)
DEF_HELPER_FP_CMP(f, d, i64, i64, i64)
DEF_HELPER_FP_CMP(fx, s, i64, f80, i32)
DEF_HELPER_FP_CMP(fx, d, i64, f80, i64)
DEF_HELPER_FP_CMP(fx, x, i64, f80, f80)
/* Float Flag Comparisons */ /* Float Flag Comparisons */
DEF_HELPER_3(fcmpodsf, i32, env, i32, i32) DEF_HELPER_FLAGS_3(fcmpodsf, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_3(fcmpudsf, i32, env, i32, i32) DEF_HELPER_FLAGS_3(fcmpudsf, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_3(fcmpoddf, i32, env, i64, i64) DEF_HELPER_FLAGS_3(fcmpoddf, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(fcmpuddf, i32, env, i64, i64) DEF_HELPER_FLAGS_3(fcmpuddf, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(fxcmpodxf, i32, env, f80, f80)
DEF_HELPER_3(fxcmpudxf, i32, env, f80, f80)
/* Float Conversions */ /* Float Conversions */
DEF_HELPER_2(fstois, i32, env, i32) DEF_HELPER_FLAGS_2(fstofd, TCG_CALL_NO_RWG, i64, env, i32)
DEF_HELPER_2(istofs, i32, env, i32) DEF_HELPER_FLAGS_3(fstofx, TCG_CALL_NO_RWG, void, f80, env, i32)
DEF_HELPER_2(fstoistr, i32, env, i32)
DEF_HELPER_3(fstofx, void, f80, env, i32)
DEF_HELPER_3(istofx, void, f80, env, i32)
DEF_HELPER_2(fdtoid, i64, env, i64) DEF_HELPER_FLAGS_2(fdtofs, TCG_CALL_NO_RWG, i32, env, i64)
DEF_HELPER_2(idtofd, i64, env, i64) DEF_HELPER_FLAGS_3(fdtofx, TCG_CALL_NO_RWG, void, f80, env, i64)
DEF_HELPER_2(fdtoidtr, i64, env, i64)
DEF_HELPER_3(fdtofx, void, f80, env, i64)
DEF_HELPER_3(idtofx, void, f80, env, i64)
DEF_HELPER_2(fstofd, i64, env, i32) DEF_HELPER_FLAGS_2(fxtofs, TCG_CALL_NO_RWG, i32, env, f80)
DEF_HELPER_2(fstoid, i64, env, i32) DEF_HELPER_FLAGS_2(fxtofd, TCG_CALL_NO_RWG, i64, env, f80)
DEF_HELPER_2(istofd, i64, env, i32)
DEF_HELPER_2(fstoidtr, i64, env, i32)
DEF_HELPER_2(fdtofs, i32, env, i64) DEF_HELPER_FLAGS_2(istofs, TCG_CALL_NO_RWG, i32, env, i32)
DEF_HELPER_2(fdtois, i32, env, i64) DEF_HELPER_FLAGS_2(istofd, TCG_CALL_NO_RWG, i64, env, i32)
DEF_HELPER_2(idtofs, i32, env, i64) DEF_HELPER_FLAGS_3(istofx, TCG_CALL_NO_RWG, void, f80, env, i32)
DEF_HELPER_2(fdtoistr, i32, env, i64)
DEF_HELPER_2(fxtofs, i32, env, f80) DEF_HELPER_FLAGS_2(idtofs, TCG_CALL_NO_RWG, i32, env, i64)
DEF_HELPER_2(fxtois, i32, env, f80) DEF_HELPER_FLAGS_2(idtofd, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_2(fxtoistr, i32, env, f80) DEF_HELPER_FLAGS_3(idtofx, TCG_CALL_NO_RWG, void, f80, env, i64)
DEF_HELPER_2(fxtofd, i64, env, f80) DEF_HELPER_FLAGS_2(fstois, TCG_CALL_NO_RWG, i32, env, i32)
DEF_HELPER_2(fxtoid, i64, env, f80) DEF_HELPER_FLAGS_2(fstoid, TCG_CALL_NO_RWG, i64, env, i32)
DEF_HELPER_2(fxtoidtr, i64, env, f80) DEF_HELPER_FLAGS_2(fstoistr, TCG_CALL_NO_RWG, i32, env, i32)
DEF_HELPER_FLAGS_2(fstoidtr, TCG_CALL_NO_RWG, i64, env, i32)
DEF_HELPER_FLAGS_2(fdtois, TCG_CALL_NO_RWG, i32, env, i64)
DEF_HELPER_FLAGS_2(fdtoid, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_2(fdtoistr, TCG_CALL_NO_RWG, i32, env, i64)
DEF_HELPER_FLAGS_2(fdtoidtr, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_2(fxtois, TCG_CALL_NO_RWG, i32, env, f80)
DEF_HELPER_FLAGS_2(fxtoistr, TCG_CALL_NO_RWG, i32, env, f80)
DEF_HELPER_FLAGS_2(fxtoid, TCG_CALL_NO_RWG, i64, env, f80)
DEF_HELPER_FLAGS_2(fxtoidtr, TCG_CALL_NO_RWG, i64, env, f80)
/* Float Rounding */ /* Float Rounding */
DEF_HELPER_3(fstoifs, i32, env, i32, i32) DEF_HELPER_FLAGS_3(fstoifs, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_3(fdtoifd, i64, env, i64, i64) DEF_HELPER_FLAGS_3(fdtoifd, TCG_CALL_NO_RWG, i64, env, i64, i64)
#undef DEF_HELPER_3_32_64_80
#undef DEF_HELPER_3_32_64

View File

@ -75,217 +75,17 @@ void e2k_update_fp_status(CPUE2KState *env)
set_float_rounding_mode(rm[env->pfpfr.rc], &env->fp_status); set_float_rounding_mode(rm[env->pfpfr.rc], &env->fp_status);
} }
#define GENERATE_SIMPLE_FLOAT2_OP(name, function, size) \
uint##size##_t HELPER(name)(CPUE2KState *env, uint##size##_t x, uint##size##_t y) \
{ \
int old_flags = fp_save_exception_flags(env); \
float##size z = float##size##_##function (make_float##size (x), make_float##size (y), &env->fp_status); \
fp_merge_exception_flags(env, old_flags); \
return float##size##_val(z); \
}
#define GENERATE_SIMPLE_FLOAT2_OPS_32_64(name, function) \
GENERATE_SIMPLE_FLOAT2_OP(glue(name, s), function, 32) \
GENERATE_SIMPLE_FLOAT2_OP(glue(name, d), function, 64)
#define GENERATE_CMP_FLOAT2_OP(ret_type, name, expr, op, in_type, cvt_macro) \
ret_type HELPER(name)(CPUE2KState *env, in_type x, in_type y) \
{ \
int old_flags = fp_save_exception_flags(env); \
ret_type z = expr op(cvt_macro(x), cvt_macro(y), &env->fp_status); \
fp_merge_exception_flags(env, old_flags); \
return z ? -1 : 0; \
}
#define GENERATE_CMP_XFLOAT2_OP(ret_type, name, expr, op, in_type, cvt_macro) \
ret_type HELPER(name)(CPUE2KState *env, in_type x, in_type y) \
{ \
int old_flags = fx_save_exception_flags(env); \
ret_type z = expr op(cvt_macro(x), cvt_macro(y), &env->fx_status); \
fx_merge_exception_flags(env, old_flags); \
return z ? -1 : 0; \
}
#define GENERATE_CMP_FLOAT2_OPS_32_64_80(name, expr, op) \
GENERATE_CMP_FLOAT2_OP(uint32_t, glue3(f, name, s), expr, glue(float32_, op), uint32_t, make_float32) \
GENERATE_CMP_FLOAT2_OP(uint64_t, glue3(f, name, d), expr, glue(float64_, op), uint64_t, make_float32) \
GENERATE_CMP_XFLOAT2_OP(uint64_t, glue3(fx, name, x), expr, glue(floatx80_, op), floatx80*, deref)
#define GENERATE_CVT_FLOAT1_OP(name, from_t, to_t, size_from, size_to, func_from, func_to) \
size_to HELPER(name)(CPUE2KState *env, size_from x) \
{\
int old_flags = fp_save_exception_flags(env); \
size_to z = func_to( glue3(from_t, _to_, to_t) (func_from(x), &env->fp_status) );\
fp_merge_exception_flags(env, old_flags); \
return z; \
}
#define GENERATE_CVT_XFLOAT1_OP(name, from_t, to_t, size_from, size_to, func_from, func_to) \
size_to HELPER(name)(CPUE2KState *env, size_from x) \
{\
int old_flags = fx_save_exception_flags(env); \
size_to z = func_to( glue3(from_t, _to_, to_t) (func_from(x), &env->fx_status) );\
fx_merge_exception_flags(env, old_flags); \
return z; \
}
GENERATE_SIMPLE_FLOAT2_OPS_32_64(fadd, add)
GENERATE_SIMPLE_FLOAT2_OPS_32_64(fsub, sub)
GENERATE_SIMPLE_FLOAT2_OPS_32_64(fmin, min)
GENERATE_SIMPLE_FLOAT2_OPS_32_64(fmax, max)
GENERATE_SIMPLE_FLOAT2_OPS_32_64(fmul, mul)
GENERATE_SIMPLE_FLOAT2_OPS_32_64(fdiv, div)
GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpeq, , eq)
GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpneq, !, eq)
GENERATE_CMP_FLOAT2_OPS_32_64_80(cmple, , le)
GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpnle, !, le)
GENERATE_CMP_FLOAT2_OPS_32_64_80(cmplt, , lt)
GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpnlt, !, lt)
GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpuod, , unordered)
GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpod, !, unordered)
GENERATE_CVT_FLOAT1_OP(fstois, float32, int32, uint32_t, uint32_t, make_float32, ident)
GENERATE_CVT_FLOAT1_OP(istofs, int32, float32, uint32_t, uint32_t, ident, float32_val)
GENERATE_CVT_FLOAT1_OP(fstoistr, float32, int32_round_to_zero, uint32_t, uint32_t, make_float32, ident)
GENERATE_CVT_FLOAT1_OP(fdtoid, float64, int64, uint64_t, uint64_t, make_float64, ident)
GENERATE_CVT_FLOAT1_OP(idtofd, int64, float64, uint64_t, uint64_t, ident, float64_val)
GENERATE_CVT_FLOAT1_OP(fdtoidtr, float64, int64_round_to_zero, uint64_t, uint64_t, make_float64, ident)
GENERATE_CVT_FLOAT1_OP(fstofd, float32, float64, uint32_t, uint64_t, make_float32, float64_val)
GENERATE_CVT_FLOAT1_OP(fstoid, float32, int64, uint32_t, uint64_t, make_float32, ident)
GENERATE_CVT_FLOAT1_OP(istofd, int32, float64, uint32_t, uint64_t, ident, float64_val)
GENERATE_CVT_FLOAT1_OP(fstoidtr, float32, int64_round_to_zero, uint32_t, uint64_t, make_float32, ident)
GENERATE_CVT_FLOAT1_OP(fdtofs, float64, float32, uint64_t, uint32_t, make_float64, float32_val)
GENERATE_CVT_FLOAT1_OP(fdtois, float64, int32, uint64_t, uint32_t, make_float64, ident)
GENERATE_CVT_FLOAT1_OP(idtofs, int64, float32, uint64_t, uint32_t, ident, float32_val)
GENERATE_CVT_FLOAT1_OP(fdtoistr, float64, int32_round_to_zero, uint64_t, uint32_t, make_float64, ident)
GENERATE_CVT_XFLOAT1_OP(fxtofs, floatx80, float32, floatx80*, uint32_t, deref, float32_val)
GENERATE_CVT_XFLOAT1_OP(fxtois, floatx80, int32, floatx80*, uint32_t, deref, ident)
GENERATE_CVT_XFLOAT1_OP(fxtoistr, floatx80, int32_round_to_zero, floatx80*, uint32_t, deref, ident)
GENERATE_CVT_XFLOAT1_OP(fxtofd, floatx80, float64, floatx80*, uint64_t, deref, float64_val)
GENERATE_CVT_XFLOAT1_OP(fxtoid, floatx80, int64, floatx80*, uint64_t, deref, ident)
GENERATE_CVT_XFLOAT1_OP(fxtoidtr, floatx80, int64_round_to_zero, floatx80*, uint64_t, deref, ident)
void HELPER(fstofx)(floatx80 *ret, CPUE2KState *env, uint32_t x)
{
int old_flags = fp_save_exception_flags(env);
*ret = float32_to_floatx80(make_float32(x), &env->fp_status);
fp_merge_exception_flags(env, old_flags);
}
void HELPER(fdtofx)(floatx80 *ret, CPUE2KState *env, uint64_t x)
{
int old_flags = fp_save_exception_flags(env);
*ret = float64_to_floatx80(make_float64(x), &env->fp_status);
fp_merge_exception_flags(env, old_flags);
}
void HELPER(istofx)(floatx80 *ret, CPUE2KState *env, uint32_t x)
{
int old_flags = fx_save_exception_flags(env);
*ret = int32_to_floatx80(x, &env->fx_status);
fx_merge_exception_flags(env, old_flags);
}
void HELPER(idtofx)(floatx80 *ret, CPUE2KState *env, uint64_t x)
{
int old_flags = fx_save_exception_flags(env);
*ret = int64_to_floatx80(x, &env->fx_status);
fx_merge_exception_flags(env, old_flags);
}
#define GEN_OP2_XX(name, op) \
void HELPER(name)(CPUE2KState *env, floatx80 *x, floatx80 *y) \
{ \
int old_flags = fx_save_exception_flags(env); \
*x = glue(floatx80_, op)(*x, *y, &env->fx_status); \
fx_merge_exception_flags(env, old_flags); \
}
GEN_OP2_XX(fxaddxx, add)
GEN_OP2_XX(fxsubxx, sub)
GEN_OP2_XX(fxmulxx, mul)
GEN_OP2_XX(fxdivxx, div)
void HELPER(fxrsubxx)(CPUE2KState *env, floatx80 *x, floatx80 *y)
{
int old_flags = fx_save_exception_flags(env);
*x = floatx80_sub(*y, *x, &env->fx_status);
fx_merge_exception_flags(env, old_flags);
}
#define GENERATE_FCMPODF(op, IN, F, cvt_macro, status, save_flags, merge_flags) \
uint32_t HELPER(op)(CPUE2KState *env, IN _x, IN _y) \
{ \
int old_flags = save_flags(env); \
uint32_t ret; \
F x = cvt_macro(_x); \
F y = cvt_macro(_y); \
if (glue(F, _is_any_nan)(x) || glue(F, _is_any_nan)(y)) { \
ret = 0x45; \
} else { \
FloatRelation relation = glue(F, _compare_quiet)(x, y, status); \
switch(relation) \
{ \
case float_relation_less: \
ret = 0x01; \
break; \
case float_relation_greater: \
ret = 0x00; \
break; \
case float_relation_equal: \
ret = 0x40; \
break; \
case float_relation_unordered: \
default: \
ret = 0x45; \
break; \
} \
} \
merge_flags(env, old_flags); \
return ret; \
}
GENERATE_FCMPODF(fcmpodsf, uint32_t, float32, make_float32, &env->fp_status,
fp_save_exception_flags, fp_merge_exception_flags)
GENERATE_FCMPODF(fcmpoddf, uint64_t, float64, make_float64, &env->fp_status,
fp_save_exception_flags, fp_merge_exception_flags)
GENERATE_FCMPODF(fxcmpodxf, floatx80 *, floatx80, deref, &env->fx_status,
fx_save_exception_flags, fx_merge_exception_flags)
/* didn't found any difference between these instruction
so keep it that way for now */
uint32_t HELPER(fcmpudsf)(CPUE2KState *env, float32 x, float32 y)
{
return HELPER(fcmpodsf)(env, x, y);
}
uint32_t HELPER(fcmpuddf)(CPUE2KState *env, float64 x, float64 y)
{
return HELPER(fcmpoddf)(env, x, y);
}
uint32_t HELPER(fxcmpudxf)(CPUE2KState *env, floatx80 *x, floatx80 *y)
{
return HELPER(fxcmpodxf)(env, x, y);
}
#define TOIF_RC_CURRENT 0x4 #define TOIF_RC_CURRENT 0x4
#define TOIF_RC_IGNORE_INEXACT 0x8 #define TOIF_RC_IGNORE_INEXACT 0x8
static inline void toif_set_round_mode(CPUE2KState *env, uint32_t flags, static inline void toif_set_round_mode(uint32_t flags, float_status *s)
float_status *s)
{ {
if ((flags & TOIF_RC_CURRENT) == 0) { if ((flags & TOIF_RC_CURRENT) == 0) {
set_float_rounding_mode(rm[flags & FP_RC_CHOP], s); set_float_rounding_mode(rm[flags & FP_RC_CHOP], s);
} }
} }
static inline void toif_clear_inexact(CPUE2KState *env, uint32_t flags, static inline void toif_clear_inexact(uint32_t flags, float_status *s)
float_status *s)
{ {
if(flags & TOIF_RC_IGNORE_INEXACT) { if(flags & TOIF_RC_IGNORE_INEXACT) {
int new_flags = get_float_exception_flags(s); int new_flags = get_float_exception_flags(s);
@ -294,59 +94,6 @@ static inline void toif_clear_inexact(CPUE2KState *env, uint32_t flags,
} }
} }
uint32_t HELPER(fstoifs)(CPUE2KState *env, uint32_t flags, uint32_t f)
{
int old_flags = fp_save_exception_flags(env);
FloatRoundMode oldrm = get_float_rounding_mode(&env->fp_status);
uint32_t ret;
toif_set_round_mode(env, flags, &env->fp_status);
ret = float32_val(float32_round_to_int(make_float32(f), &env->fp_status));
set_float_rounding_mode(oldrm, &env->fp_status);
toif_clear_inexact(env, flags, &env->fp_status);
fp_merge_exception_flags(env, old_flags);
return ret;
}
uint64_t HELPER(fdtoifd)(CPUE2KState *env, uint64_t flags, uint64_t f)
{
int old_flags = fp_save_exception_flags(env);
FloatRoundMode oldrm = get_float_rounding_mode(&env->fp_status);
uint64_t ret;
toif_set_round_mode(env, flags, &env->fp_status);
ret = float64_val(float64_round_to_int(make_float64(f), &env->fp_status));
set_float_rounding_mode(oldrm, &env->fp_status);
toif_clear_inexact(env, flags, &env->fp_status);
fp_merge_exception_flags(env, old_flags);
return ret;
}
/* TODO: test if valid, test exception flags */
uint32_t HELPER(frcps)(CPUE2KState *env, uint32_t x)
{
int old_flags = fp_save_exception_flags(env);
uint32_t y = float32_div(float32_one, make_float32(x), &env->fp_status);
fp_merge_exception_flags(env, old_flags);
return float32_val(y);
}
uint32_t HELPER(fsqrts)(CPUE2KState *env, uint32_t x)
{
int old_flags = fp_save_exception_flags(env);
uint32_t y = float32_sqrt(make_float32(x), &env->fp_status);
fp_merge_exception_flags(env, old_flags);
return float32_val(y);
}
uint32_t HELPER(frsqrts)(CPUE2KState *env, uint32_t x)
{
int old_flags = fp_save_exception_flags(env);
uint32_t y = float32_div(float32_one,
float32_sqrt(make_float32(x), &env->fp_status),
&env->fp_status);
fp_merge_exception_flags(env, old_flags);
return float32_val(y);
}
#ifdef TARGET_E2K_PRECISE_FSQRTID #ifdef TARGET_E2K_PRECISE_FSQRTID
uint64 HELPER(fsqrtid)(CPUE2KState *env, uint64_t x) uint64 HELPER(fsqrtid)(CPUE2KState *env, uint64_t x)
{ {
@ -355,21 +102,6 @@ uint64 HELPER(fsqrtid)(CPUE2KState *env, uint64_t x)
} }
#endif #endif
uint64_t HELPER(fsqrttd)(CPUE2KState *env, uint64_t x, uint64_t unused)
{
int old_flags = fp_save_exception_flags(env);
uint64_t y = float64_sqrt(make_float64(x), &env->fp_status);
fp_merge_exception_flags(env, old_flags);
return float64_val(y);
}
void HELPER(fxsqrttxx)(CPUE2KState *env, floatx80 *x, floatx80 *unused)
{
int old_flags = fx_save_exception_flags(env);
*x = floatx80_sqrt(*x, &env->fx_status);
fx_merge_exception_flags(env, old_flags);
}
#define IMPL_FSCALE(name, ty, exp_len, exp_off, mul, cvt) \ #define IMPL_FSCALE(name, ty, exp_len, exp_off, mul, cvt) \
ty HELPER(name)(CPUE2KState *env, ty src1, uint32_t src2) \ ty HELPER(name)(CPUE2KState *env, ty src1, uint32_t src2) \
{ \ { \
@ -398,26 +130,315 @@ void HELPER(fxsqrttxx)(CPUE2KState *env, floatx80 *x, floatx80 *unused)
IMPL_FSCALE(fscaled, uint64_t, 11, 52, helper_fmuld, uint64_to_float64) IMPL_FSCALE(fscaled, uint64_t, 11, 52, helper_fmuld, uint64_to_float64)
IMPL_FSCALE(fscales, uint32_t, 8, 23, helper_fmuls, uint32_to_float32) IMPL_FSCALE(fscales, uint32_t, 8, 23, helper_fmuls, uint32_to_float32)
void HELPER(fxscalesx)(CPUE2KState *env, floatx80 *src1, uint32_t src2) void HELPER(fxscalesx)(floatx80 *r, CPUE2KState *env, floatx80 *a, uint32_t b)
{ {
floatx80 s2; floatx80 v;
int32_t p = (int32_t) src2; int32_t p = (int32_t) b;
uint16_t max = (1 << 15) - 1; uint16_t max = (1 << 15) - 1;
int16_t bias = max >> 1; int16_t bias = max >> 1;
if (p <= -bias) { if (p <= -bias) {
s2.high = 0; v.high = 0;
p += bias + 62; p += bias + 62;
if (p >= 0 && p < 63) { if (p >= 0 && p < 63) {
s2.low = 1ULL << p; v.low = 1ULL << p;
} else { } else {
s2.low = p == -1; v.low = p == -1;
} }
} else if (p > bias) { } else if (p > bias) {
s2.low = 1UL << 63; v.low = 1UL << 63;
s2.high = max; v.high = max;
} else { } else {
s2.low = 1UL << 63; v.low = 1UL << 63;
s2.high = bias + p; v.high = bias + p;
} }
helper_fxmulxx(env, src1, &s2); helper_fxmulxx(r, env, a, &v);
} }
#define type_name_i32 int32
#define type_name_i64 int64
#define type_name_f32 float32
#define type_name_f64 float64
#define type_name_f80 floatx80
#define type_name(S) glue(type_name_, S)
#define arg_type_i32 uint32_t
#define arg_type_i64 uint64_t
#define arg_type_f32 uint32_t
#define arg_type_f64 uint64_t
#define arg_type_f80 floatx80 *
#define arg_type(S) glue(arg_type_, S)
#define ret_arg_i32
#define ret_arg_i64
#define ret_arg_f32
#define ret_arg_f64
#define ret_arg_f80 floatx80 *ret,
#define ret_arg(S) glue(ret_arg_, S)
#define ret_type_i32 uint32_t
#define ret_type_i64 uint64_t
#define ret_type_f32 uint32_t
#define ret_type_f64 uint64_t
#define ret_type_f80 void
#define ret_type(S) glue(ret_type_, S)
#define make_i32(v) (v)
#define make_i64(v) (v)
#define make_f32(v) make_float32(v)
#define make_f64(v) make_float64(v)
#define make_f80(v) (*(v))
#define make(S, v) glue(make_, S)(v)
#define type_i32 uint32_t
#define type_i64 uint64_t
#define type_f32 float32
#define type_f64 float64
#define type_f80 floatx80
#define type(S) glue(type_, S)
#define int32_to_int32(v, s) (v)
#define int64_to_int64(v, s) (v)
#define float32_to_float32(v, s) (v)
#define float64_to_float64(v, s) (v)
#define floatx80_to_floatx80(v, s) (v)
#define convert(F, T, v, s) glue3(type_name(F), _to_, type_name(T))(v, s)
#define ret_i32(v) return (v)
#define ret_i64(v) return (v)
#define ret_f32(v) return float32_val(v)
#define ret_f64(v) return float64_val(v)
#define ret_f80(v) *ret = v
#define ret(S, v) glue(ret_, S)(v)
#define fpu_mov(x, s) (x)
#define ident(x) (x)
#define not(x) (!(x))
#define IMPL_ALOPF2_FPU_BASIC(FPU, name, S2, R, T2, TR, op) \
ret_type(R) HELPER(name)(ret_arg(R) CPUE2KState *env, arg_type(S2) s2) \
{ \
int old_flags = glue(FPU, _save_exception_flags)(env); \
float_status *s = &env->glue(FPU, _status); \
type(T2) t2 = convert(S2, T2, make(S2, s2), s); \
type(TR) tr = op(t2, s); \
type(R) r = convert(TR, R, tr, s); \
glue(FPU, _merge_exception_flags)(env, old_flags); \
ret(R, r); \
}
#define IMPL_ALOPF2_FPU(FPU, name, S2, R, op) \
IMPL_ALOPF2_FPU_BASIC(FPU, name, S2, R, S2, R, op)
#define IMPL_ALOPF2_FP(name, S2, R, op) \
IMPL_ALOPF2_FPU_BASIC(fp, name, R, S2, R, S2, op)
#define IMPL_ALOPF2_FPU_CVT(FPU, name, S2, R) \
IMPL_ALOPF2_FPU_BASIC(FPU, name, S2, R, R, R, fpu_mov)
#define IMPL_ALOPF1_FPU(FPU, name, S1, S2, R, T1, T2, TR, op) \
ret_type(R) HELPER(name)(ret_arg(R) CPUE2KState *env, \
arg_type(S1) s1, arg_type(S2) s2) \
{ \
int old_flags = glue(FPU, _save_exception_flags)(env); \
float_status *s = &env->glue(FPU, _status); \
type(T1) t1 = convert(S1, T1, make(S1, s1), s); \
type(T2) t2 = convert(S2, T2, make(S2, s2), s); \
type(TR) tr = op(t1, t2, s); \
type(R) r = convert(TR, R, tr, s); \
glue(FPU, _merge_exception_flags)(env, old_flags); \
ret(R, r); \
}
#define IMPL_ALOPF1_FX(name, S1, S2, R, op) \
IMPL_ALOPF1_FPU(fx, name, S1, S2, R, f80, f80, f80, op)
#define IMPL_ALOPF1_FP(name, S1, S2, R, op) \
IMPL_ALOPF1_FPU(fp, name, S1, S2, R, S1, S2, R, op)
#define IMPL_ALOPF1_FPU_CMP_BASIC(FPU, name, S1, S2, R, T1, T2, TR, op1, op2) \
ret_type(R) HELPER(name)(ret_arg(R) CPUE2KState *env, \
arg_type(S1) s1, arg_type(S2) s2) \
{ \
int old_flags = glue(FPU, _save_exception_flags)(env); \
float_status *s = &env->glue(FPU, _status); \
type(T1) t1 = convert(S1, T1, make(S1, s1), s); \
type(T2) t2 = convert(S2, T2, make(S2, s2), s); \
type(TR) tr = op2(op1(t1, t2, s)) ? -1 : 0; \
type(R) r = convert(TR, R, tr, s); \
glue(FPU, _merge_exception_flags)(env, old_flags); \
ret(R, r); \
}
#define IMPL_ALOPF1_FPU_CMP(FPU, name, S1, S2, R, T, op1, op2) \
IMPL_ALOPF1_FPU_CMP_BASIC(FPU, name, S1, S2, R, T, T, R, op1, op2)
#define IMPL_ALOPF1_FX_MANY(name, op) \
IMPL_ALOPF1_FX(glue3(fx, name, ss), f80, f32, f32, op) \
IMPL_ALOPF1_FX(glue3(fx, name, dd), f80, f64, f64, op) \
IMPL_ALOPF1_FX(glue3(fx, name, sx), f80, f32, f80, op) \
IMPL_ALOPF1_FX(glue3(fx, name, dx), f80, f64, f80, op) \
IMPL_ALOPF1_FX(glue3(fx, name, xx), f80, f80, f80, op) \
IMPL_ALOPF1_FX(glue3(fx, name, xd), f80, f80, f64, op) \
IMPL_ALOPF1_FX(glue3(fx, name, xs), f80, f80, f32, op)
IMPL_ALOPF1_FX_MANY(add, floatx80_add)
IMPL_ALOPF1_FX_MANY(sub, floatx80_sub)
IMPL_ALOPF1_FX_MANY(mul, floatx80_mul)
IMPL_ALOPF1_FX_MANY(div, floatx80_div)
#define floatx80_rsub(x, y, s) floatx80_sub(y, x, s)
IMPL_ALOPF1_FX(fxrsubss, f80, f32, f32, floatx80_rsub)
IMPL_ALOPF1_FX(fxrsubdd, f80, f64, f64, floatx80_rsub)
IMPL_ALOPF1_FX(fxrsubsx, f80, f32, f80, floatx80_rsub)
IMPL_ALOPF1_FX(fxrsubdx, f80, f64, f80, floatx80_rsub)
IMPL_ALOPF1_FX(fxdivtss, f32, f80, f32, floatx80_div)
IMPL_ALOPF1_FX(fxdivtdd, f64, f80, f64, floatx80_div)
IMPL_ALOPF1_FX(fxdivtsx, f32, f80, f80, floatx80_div)
IMPL_ALOPF1_FX(fxdivtdx, f64, f80, f80, floatx80_div)
static floatx80 fxsqrtt(floatx80 a, floatx80 b, float_status *s)
{
// TODO: fxsqrtt
return floatx80_sqrt(a, s);
}
IMPL_ALOPF1_FX(fxsqrttsx, f32, f80, f80, fxsqrtt)
IMPL_ALOPF1_FX(fxsqrttdx, f64, f80, f80, fxsqrtt)
IMPL_ALOPF1_FX(fxsqrttxx, f80, f80, f80, fxsqrtt)
#define CMPODF_BASIC(p, x, y, s) ({ \
uint32_t ret = 0x45; \
if (!glue(p, _is_any_nan)(x) && !glue(p, _is_any_nan)(y)) { \
FloatRelation relation = glue(p, _compare_quiet)(x, y, s); \
switch (relation) { \
case float_relation_greater: ret = 0x00; break; \
case float_relation_less: ret = 0x01; break; \
case float_relation_equal: ret = 0x40; break; \
case float_relation_unordered: ret = 0x45; break; \
} \
} \
ret;\
})
#define FXCMPODF(x, y, s) CMPODF_BASIC(floatx80, x, y, s)
#define FCMPODDF(x, y, s) CMPODF_BASIC(float64, x, y, s)
#define FCMPODSF(x, y, s) CMPODF_BASIC(float32, x, y, s)
// TODO: cmpudf
#define FXCMPUDF FXCMPODF
#define FCMPUDSF FCMPODSF
#define FCMPUDDF FCMPODDF
#define IMPL_CMPF_FX(name, S1, S2, op) \
IMPL_ALOPF1_FPU(fx, name, S1, S2, i32, f80, f80, i32, op)
IMPL_CMPF_FX(fxcmpodsf, f80, f32, FXCMPODF)
IMPL_CMPF_FX(fxcmpoddf, f80, f64, FXCMPODF)
IMPL_CMPF_FX(fxcmpodxf, f80, f80, FXCMPODF)
IMPL_CMPF_FX(fxcmpudsf, f80, f32, FXCMPUDF)
IMPL_CMPF_FX(fxcmpuddf, f80, f64, FXCMPUDF)
IMPL_CMPF_FX(fxcmpudxf, f80, f80, FXCMPUDF)
#define IMPL_CMPF_FP(name, T, R, op) \
IMPL_ALOPF1_FPU(fp, name, T, T, R, T, T, R, op)
IMPL_CMPF_FP(fcmpodsf, f32, i32, FCMPODSF)
IMPL_CMPF_FP(fcmpoddf, f64, i64, FCMPODDF)
IMPL_CMPF_FP(fcmpudsf, f32, i32, FCMPUDSF)
IMPL_CMPF_FP(fcmpuddf, f64, i64, FCMPUDDF)
#define cmp_op(T, op) glue3(type_name(T), _, op)
#define IMPL_ALOPF1_FPU_CMP_ALL(F, P, S, T, R, A, B) \
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmpeq, S), A, B, R, T, cmp_op(T, eq), ident) \
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmpneq, S), A, B, R, T, cmp_op(T, eq), not) \
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmple, S), A, B, R, T, cmp_op(T, le), ident) \
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmpnle, S), A, B, R, T, cmp_op(T, le), not) \
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmplt, S), A, B, R, T, cmp_op(T, lt), ident) \
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmpnlt, S), A, B, R, T, cmp_op(T, lt), not) \
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmpuod, S), A, B, R, T, cmp_op(T, unordered), ident) \
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmpod, S), A, B, R, T, cmp_op(T, unordered), not)
IMPL_ALOPF1_FPU_CMP_ALL(fp, f, s, f32, i32, f32, f32)
IMPL_ALOPF1_FPU_CMP_ALL(fp, f, d, f64, i64, f64, f64)
IMPL_ALOPF1_FPU_CMP_ALL(fx, fx, s, f80, i64, f80, f32)
IMPL_ALOPF1_FPU_CMP_ALL(fx, fx, d, f80, i64, f80, f64)
IMPL_ALOPF1_FPU_CMP_ALL(fx, fx, x, f80, i64, f80, f80)
IMPL_ALOPF2_FPU_CVT(fp, fstofd, f32, f64)
IMPL_ALOPF2_FPU_CVT(fx, fstofx, f32, f80)
IMPL_ALOPF2_FPU_CVT(fp, fstois, f32, i32)
IMPL_ALOPF2_FPU_CVT(fp, fstoid, f32, i64)
IMPL_ALOPF2_FPU_CVT(fp, fdtofs, f64, f32)
IMPL_ALOPF2_FPU_CVT(fx, fdtofx, f64, f80)
IMPL_ALOPF2_FPU_CVT(fp, fdtois, f64, i32)
IMPL_ALOPF2_FPU_CVT(fp, fdtoid, f64, i64)
IMPL_ALOPF2_FPU_CVT(fx, fxtofs, f80, f32)
IMPL_ALOPF2_FPU_CVT(fx, fxtofd, f80, f64)
IMPL_ALOPF2_FPU_CVT(fx, fxtois, f80, i32)
IMPL_ALOPF2_FPU_CVT(fx, fxtoid, f80, i64)
IMPL_ALOPF2_FPU_CVT(fp, istofs, i32, f32)
IMPL_ALOPF2_FPU_CVT(fp, istofd, i32, f64)
IMPL_ALOPF2_FPU_CVT(fx, istofx, i32, f80)
IMPL_ALOPF2_FPU_CVT(fp, idtofs, i64, f32)
IMPL_ALOPF2_FPU_CVT(fp, idtofd, i64, f64)
IMPL_ALOPF2_FPU_CVT(fx, idtofx, i64, f80)
IMPL_ALOPF2_FPU(fp, fstoistr, f32, i32, float32_to_int32_round_to_zero)
IMPL_ALOPF2_FPU(fp, fstoidtr, f32, i64, float32_to_int64_round_to_zero)
IMPL_ALOPF2_FPU(fp, fdtoistr, f64, i32, float64_to_int32_round_to_zero)
IMPL_ALOPF2_FPU(fp, fdtoidtr, f64, i64, float64_to_int64_round_to_zero)
IMPL_ALOPF2_FPU(fx, fxtoistr, f80, i32, floatx80_to_int32_round_to_zero)
IMPL_ALOPF2_FPU(fx, fxtoidtr, f80, i64, floatx80_to_int64_round_to_zero)
#define IMPL_FTOIF(name, A, B) \
static type(B) name(type(A) flags, type(B) f, float_status *s) \
{ \
FloatRoundMode oldrm = get_float_rounding_mode(s); \
type(B) ret; \
\
toif_set_round_mode(flags, s); \
ret = glue(type_name(B), _round_to_int)(f, s); \
set_float_rounding_mode(oldrm, s); \
toif_clear_inexact(flags, s); \
return ret; \
}
IMPL_FTOIF(fstoifs, i32, f32)
IMPL_FTOIF(fdtoifd, i64, f64)
IMPL_ALOPF1_FP(fstoifs, i32, f32, f32, fstoifs)
IMPL_ALOPF1_FP(fdtoifd, i64, f64, f64, fdtoifd)
/* TODO: frcps: test if valid, test exception flags */
#define frcps(a, s) float32_div(float32_one, a, s)
#define frsqrts(a, s) float32_div(float32_one, float32_sqrt(a, s), s)
static float64 fsqrttd(float64 a, float64 b, float_status *s)
{
// TODO: fxsqrtt
return float64_sqrt(a, s);
}
#define IMPL_ALOPF1_FP_MANY(S, T) \
IMPL_ALOPF1_FP(glue(fadd, S), T, T, T, glue(type_name(T), _add)) \
IMPL_ALOPF1_FP(glue(fsub, S), T, T, T, glue(type_name(T), _sub)) \
IMPL_ALOPF1_FP(glue(fmul, S), T, T, T, glue(type_name(T), _mul)) \
IMPL_ALOPF1_FP(glue(fdiv, S), T, T, T, glue(type_name(T), _div)) \
IMPL_ALOPF1_FP(glue(fmin, S), T, T, T, glue(type_name(T), _min)) \
IMPL_ALOPF1_FP(glue(fmax, S), T, T, T, glue(type_name(T), _max))
IMPL_ALOPF1_FP_MANY(s, f32)
IMPL_ALOPF1_FP_MANY(d, f64)
IMPL_ALOPF2_FP(fsqrts, f32, f32, float32_sqrt)
IMPL_ALOPF2_FP(frcps, f32, f32, frcps)
IMPL_ALOPF2_FP(frsqrts, f32, f32, frsqrts)
IMPL_ALOPF1_FP(fsqrttd, f64, f64, f64, fsqrttd)

View File

@ -5,9 +5,8 @@
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "qemu/host-utils.h" #include "qemu/host-utils.h"
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "translate.h"
uint64_t helper_sxt(uint64_t x, uint32_t y) uint64_t HELPER(sxt)(uint64_t x, uint32_t y)
{ {
int size; int size;
@ -36,7 +35,7 @@ static uint64_t cr_read(CPUE2KState *env, size_t offset)
return cpu_ldq_le_data(env, addr); return cpu_ldq_le_data(env, addr);
} }
uint64_t helper_state_reg_read_i64(CPUE2KState *env, int idx) uint64_t HELPER(rrd)(CPUE2KState *env, int idx)
{ {
switch (idx) { switch (idx) {
case 0x01: return e2k_state_wd(env); /* %wd */ case 0x01: return e2k_state_wd(env); /* %wd */
@ -75,12 +74,7 @@ uint64_t helper_state_reg_read_i64(CPUE2KState *env, int idx)
} }
} }
uint32_t helper_state_reg_read_i32(CPUE2KState *env, int idx) void HELPER(rwd)(CPUE2KState *env, int idx, uint64_t val)
{
return helper_state_reg_read_i64(env, idx);
}
void helper_state_reg_write_i64(CPUE2KState *env, int idx, uint64_t val)
{ {
switch(idx) { switch(idx) {
case 0x80: /* %upsr */ case 0x80: /* %upsr */
@ -110,7 +104,7 @@ void helper_state_reg_write_i64(CPUE2KState *env, int idx, uint64_t val)
} }
} }
void helper_state_reg_write_i32(CPUE2KState *env, int idx, uint32_t val) void HELPER(rws)(CPUE2KState *env, int idx, uint32_t val)
{ {
switch (idx) { switch (idx) {
case 0x80: /* %upsr */ case 0x80: /* %upsr */
@ -134,7 +128,7 @@ void helper_state_reg_write_i32(CPUE2KState *env, int idx, uint32_t val)
} }
} }
uint64_t helper_getsp(CPUE2KState *env, uint32_t src2) uint64_t HELPER(getsp)(CPUE2KState *env, uint32_t src2)
{ {
int32_t s2 = src2 & ~0xf; int32_t s2 = src2 & ~0xf;

View File

@ -4,7 +4,6 @@
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "qemu/host-utils.h" #include "qemu/host-utils.h"
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "translate.h"
int HELPER(probe_read_access)(CPUE2KState *env, target_ulong addr) int HELPER(probe_read_access)(CPUE2KState *env, target_ulong addr)
{ {

View File

@ -5,7 +5,6 @@
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "qemu/host-utils.h" #include "qemu/host-utils.h"
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "translate.h"
static uint8_t reverse_bits(uint8_t b) static uint8_t reverse_bits(uint8_t b)
{ {
@ -143,7 +142,8 @@ GEN_HELPER_PACKED_HORIZONTAL_OP(phsubsh, sh, sub, satsh)
#define GEN_HELPER_PACKED_SCALAR_BINOP(name, type, op) \ #define GEN_HELPER_PACKED_SCALAR_BINOP(name, type, op) \
GEN_HELPER_PACKED_SCALAR(name, type, { \ GEN_HELPER_PACKED_SCALAR(name, type, { \
dst.type[i] = s1.type[i] op s2; \ int max = sizeof(s1.type[0]) * 8 - 1; \
dst.type[i] = s2 < s1.type[i] op ( s2 < max ? s2 : max); \
}) })
GEN_HELPER_PACKED_SCALAR_BINOP(psllh, uh, <<) GEN_HELPER_PACKED_SCALAR_BINOP(psllh, uh, <<)
@ -153,25 +153,26 @@ GEN_HELPER_PACKED_SCALAR_BINOP(psrlw, uw, >>)
#define GEN_HELPER_PACKED_SRA(name, type, t) \ #define GEN_HELPER_PACKED_SRA(name, type, t) \
GEN_HELPER_PACKED_SCALAR(name, type, { \ GEN_HELPER_PACKED_SCALAR(name, type, { \
dst.type[i] = (t) s1.type[i] >> s2; \ int max = sizeof(s1.type[0]) * 8 - 1; \
dst.type[i] = (t) s1.type[i] >> (s2 < max ? s2 : max); \
}) })
GEN_HELPER_PACKED_SRA(psrah, sh, int32_t) GEN_HELPER_PACKED_SRA(psrah, sh, int32_t)
GEN_HELPER_PACKED_SRA(psraw, sw, int64_t) GEN_HELPER_PACKED_SRA(psraw, sw, int64_t)
#define GEN_HELPER_PACKED_MAD(name, dst_type, type, cast, op) \ #define GEN_HELPER_PACKED_MAD(name, dst_type, t0, t1, cast, op) \
GEN_HELPER_PACKED(name, dst_type, { \ GEN_HELPER_PACKED(name, dst_type, { \
int j = i * 2; \ int j = i * 2; \
dst.dst_type[i] = op( \ dst.dst_type[i] = op( \
(cast) s1.type[j + 1] * s2.type[j + 1] + \ (cast) s1.t0[j + 1] * s2.t1[j + 1] + \
(cast) s1.type[j ] * s2.type[j ] \ (cast) s1.t0[j ] * s2.t1[j ] \
); \ ); \
}) })
GEN_HELPER_PACKED_MAD(pmaddh, sw, sh, int32_t, ident) GEN_HELPER_PACKED_MAD(pmaddh, sw, sh, sh, int32_t, ident)
GEN_HELPER_PACKED_MAD(pmaddubsh, sh, ub, int16_t, satsh) GEN_HELPER_PACKED_MAD(pmaddubsh, sh, sb, ub, int32_t, satsh)
GEN_HELPER_PACKED(psadbw, ub, { dst.uw[0] += s1.ub[i] - s2.ub[i]; }) GEN_HELPER_PACKED(psadbw, ub, { dst.uw[0] += abs(s1.ub[i] - s2.ub[i]); })
GEN_HELPER_PACKED(pavgusb, ub, { dst.ub[i] = (s1.ub[i] + s2.ub[i] + 1) >> 1; }) GEN_HELPER_PACKED(pavgusb, ub, { dst.ub[i] = (s1.ub[i] + s2.ub[i] + 1) >> 1; })
GEN_HELPER_PACKED(pavgush, uh, { dst.uh[i] = (s1.uh[i] + s2.uh[i] + 1) >> 1; }) GEN_HELPER_PACKED(pavgush, uh, { dst.uh[i] = (s1.uh[i] + s2.uh[i] + 1) >> 1; })
@ -187,7 +188,7 @@ GEN_HELPER_PACKED_MULH(pmulhuh, uh, uint32_t, shr16)
GEN_HELPER_PACKED_MULH(pmulhrsh, sh, int32_t, shr14_add1_shr1) GEN_HELPER_PACKED_MULH(pmulhrsh, sh, int32_t, shr14_add1_shr1)
GEN_HELPER_PACKED(pmulubhh, uh, { \ GEN_HELPER_PACKED(pmulubhh, uh, { \
dst.uh[i] = (((int16_t) s1.ub[i] * s2.sh[i]) + s1.ub[i]) >> 8; \ dst.uh[i] = ((int16_t) s1.ub[i] * s2.sh[i] + 0x80) >> 8; \
}) })
GEN_HELPER_PACKED(mpsadbh, uh, { \ GEN_HELPER_PACKED(mpsadbh, uh, { \
@ -246,28 +247,19 @@ uint64_t HELPER(pshufb)(uint64_t src1, uint64_t src2, uint64_t src3)
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
uint8_t desc = s3.ub[i]; uint8_t desc = s3.ub[i];
int index = extract8(desc, 0, 3); int index = desc & 7;
uint8_t byte; uint8_t byte = desc & 8 ? s1.ub[index] : s2.ub[index];
if (desc < 0x80) { byte = desc & 0x10 ? ~byte : byte;
byte = desc & 0x08 ? s1.ub[index] : s2.ub[index]; byte = desc & 0x20 ? reverse_bits(byte) : byte;
byte = desc & 0x40 ? (byte & 0x80 ? 0xff : 0) : byte;
switch(desc >> 5) { if (desc & 0x80) {
case 0x1: byte = reverse_bits(byte); break; switch ((desc & 0x70) >> 4) {
case 0x2: byte = (byte & 0x80) != 0 ? 0xff : 0; break; case 2: byte = 0x7f; break;
case 0x3: byte = (byte & 1) != 0 ? 0xff : 0; break; case 4: byte = 0x80; break;
default: break; case 6: byte = 0xff; break;
} default: byte = 0; break;
if (desc & 0x10) {
byte = ~byte;
}
} else {
switch(desc >> 6) {
case 0xa: byte = 0x7f; break;
case 0xc: byte = 0x80; break;
case 0xe: byte = 0xff; break;
default: byte = 0; break;
} }
} }

View File

@ -9,10 +9,6 @@ e2k_ss.add(files(
'helper_sm.c', 'helper_sm.c',
'helper_vec.c', 'helper_vec.c',
'translate.c', 'translate.c',
'translate/alc.c',
'translate/aau.c',
'translate/plu.c',
'translate/state.c',
)) ))
# no softmmu support yet # no softmmu support yet

File diff suppressed because it is too large Load Diff

View File

@ -1,599 +0,0 @@
#ifndef E2K_TRANSLATE_H
#define E2K_TRANSLATE_H
#include "tcg/tcg-op.h"
#include "exec/translator.h"
#define DYNAMIC -1
#define IS_BASED(i) (((i) & 0x80) == 0)
#define IS_REGULAR(i) (((i) & 0xc0) == 0x80)
#define IS_IMM5(i) (((i) & 0xe0) == 0xc0)
#define IS_IMM4(i) (((i) & 0xf0) == 0xc0)
#define IS_LIT(i) (((i) & 0xf0) == 0xd0)
#define IS_LIT16_LO(i) (((i) & 0x0e) == 0x00)
#define IS_LIT16_HI(i) (((i) & 0x0e) == 0x04)
#define IS_LIT32(i) (((i) & 0x0c) == 0x08)
#define IS_LIT64(i) (((i) & 0x0c) == 0x0c)
#define IS_GLOBAL(i) (((i) & 0xe0) == 0xe0)
#define GET_BASED(i) ((i) & 0x7f)
#define GET_REGULAR(i) ((i) & 0x3f)
#define GET_IMM5(i) ((i) & 0x1f)
#define GET_IMM4(i) ((i) & 0x0f)
#define GET_LIT(i) ((i) & 0x03)
#define GET_GLOBAL(i) ((i) & 0x1f)
typedef enum {
ALES_NONE = 0x00,
ALES_PRESENT = 0x01,
ALES_ALLOCATED = 0x02,
} AlesFlag;
typedef struct {
TCGv_i32 cdi[32];
TCGv_i64 pib[32];
} CPUE2KAauPrefStateTCG;
typedef struct CPUE2KStateTCG {
TCGv pc;
TCGv npc;
TCGv_i64 ctprs[3];
TCGv_i32 ct_cond;
TCGv_i32 is_bp; /* breakpoint flag */
TCGv_i32 wdbl;
TCGv_i32 wd_base; /* holds wbs * 2 */
TCGv_i32 wd_size; /* holds wsz * 2 */
TCGv_i32 boff; /* holds rbs * 2 */
TCGv_i32 bsize; /* holds rsz * 2 + 2 */
TCGv_i32 bcur; /* holds rcur * 2 */
TCGv_i64 pregs;
TCGv_i32 psize; /* holds psz */
TCGv_i32 pcur; /* holds pcur */
TCGv_i64 last_value;
/* lsr */
TCGv_i32 lsr_lcnt;
TCGv_i32 lsr_ecnt;
TCGv_i32 lsr_vlc;
TCGv_i32 lsr_over;
TCGv_i32 lsr_pcnt;
TCGv_i32 lsr_strmd;
/* AAU */
TCGv_i32 aasti[16];
TCGv_i32 aasti_tags;
TCGv_i32 aaind[16];
TCGv_i32 aaind_tags;
TCGv_i32 aaincr[8];
TCGv_i32 aaincr_tags;
TCGv_i64 aad_lo[32];
TCGv_i64 aad_hi[32];
CPUE2KAauPrefStateTCG aapl, aapr;
} CPUE2KStateTCG;
extern struct CPUE2KStateTCG e2k_cs;
typedef struct {
uint32_t hs;
uint32_t ss;
uint32_t als[6];
uint32_t cs0;
uint16_t ales[6];
uint32_t cs1;
uint16_t aas[6];
uint32_t lts[4];
uint32_t pls[3];
uint32_t cds[3];
bool ss_present;
bool als_present[6];
bool cs0_present;
AlesFlag ales_present[6];
bool cs1_present;
bool aas_present[6];
bool lts_present[4];
bool pls_present[3];
bool cds_present[3];
} UnpackedBundle;
typedef struct {
int32_t sdisp; /* CS0 28:0 */
} Cs0IBranch, Cs0Puttsd;
typedef struct {
int32_t sdisp; /* CS0 28:0 */
uint8_t ipd; /* SS 31:30 */
uint8_t ctpr; /* CS0 31:30 */
uint8_t opc;
} Cs0Disp;
typedef struct {
uint32_t disp; /* CS0 28:0 */
uint8_t ipd; /* SS 31:30 */
uint8_t ctpr; /* CS0 31:30 */
} Cs0SDisp;
typedef struct {
uint8_t ipd;
} Cs0Return;
typedef struct {
uint32_t disp; /* 28:4 */
uint8_t prefr; /* 2:0 */
uint8_t ipd; /* 3 */
} Cs0Pref;
typedef enum {
CS0_NONE,
CS0_IBRANCH,
CS0_PREF,
CS0_PUTTSD,
CS0_DONE,
CS0_HRET,
CS0_GLAUNCH,
CS0_DISP,
CS0_SDISP,
CS0_GETTSD,
CS0_RETURN,
} Cs0Type;
typedef struct {
Cs0Type type;
union {
Cs0IBranch ibranch;
Cs0Puttsd puttsd;
Cs0Disp disp;
Cs0SDisp sdisp;
Cs0Pref pref;
Cs0Return ret;
};
} Cs0;
typedef enum {
SETR_VFRPSZ = 0x01,
SETR_WD = 0x02,
SETR_BN = 0x04,
SETR_BP = 0x08,
} SetrType;
typedef struct {
SetrType type;
uint8_t rpsz;
uint8_t wsz;
bool nfx;
bool dbl;
uint8_t rbs;
uint8_t rsz;
uint8_t rcur;
uint8_t psz;
} Cs1Setr;
typedef struct {
bool ma_c;
bool fl_c;
bool ld_c;
bool st_c;
bool all_e;
bool all_c;
/* v2+ */
bool trap;
/* v5+ */
bool sal;
bool sas;
} Cs1Wait;
typedef struct {
uint8_t wbs;
uint8_t disp;
} Cs1HCall;
typedef struct {
bool flushr;
bool flushc;
} Cs1Flush;
typedef struct {
bool chkm4;
uint8_t dmask;
uint8_t umask;
} Cs1Vfbg;
typedef enum {
CS1_NONE,
CS1_SETR,
CS1_SETEI,
CS1_SETSFT,
CS1_WAIT,
CS1_CALL,
CS1_HCALL,
CS1_MAS,
CS1_FLUSH,
CS1_VFBG,
} Cs1Type;
typedef struct {
Cs1Type type;
union {
Cs1Setr setr;
uint8_t ei;
Cs1Wait wait;
uint8_t call_wbs;
Cs1HCall hcall;
uint8_t mas[6];
Cs1Flush flush;
Cs1Vfbg vfbg;
};
} Cs1;
typedef enum {
ALOPF_NONE,
ALOPF1,
ALOPF1_MERGE,
ALOPF2,
ALOPF3,
ALOPF7,
ALOPF8,
ALOPF10,
ALOPF11,
ALOPF11_MERGE,
ALOPF11_LIT8,
ALOPF12,
ALOPF12_PSHUFH,
ALOPF12_IBRANCHD,
ALOPF12_ICALLD,
ALOPF13,
ALOPF15,
ALOPF16,
ALOPF17,
ALOPF21,
ALOPF21_ICOMB,
ALOPF21_FCOMB,
ALOPF21_PFCOMB,
ALOPF21_LCOMB,
ALOPF22,
} Alopf;
typedef struct {
Alopf format;
uint32_t op;
const char *name;
} Alop;
typedef struct {
Cs0 cs0;
Cs1 cs1;
Alop alops[6];
} Bundle;
typedef enum {
AL_RESULT_NONE = 0,
AL_RESULT_SIZE_MASK = 0x3,
AL_RESULT_32 = 0x00,
AL_RESULT_64 = 0x01,
AL_RESULT_80 = 0x02,
AL_RESULT_128 = 0x03,
AL_RESULT_TYPE_MASK = 0xc,
AL_RESULT_REG = 0x04,
AL_RESULT_PREG = 0x08,
AL_RESULT_CTPR = 0x0c,
AL_RESULT_REG32 = AL_RESULT_REG | AL_RESULT_32,
AL_RESULT_REG64 = AL_RESULT_REG | AL_RESULT_64,
AL_RESULT_REG80 = AL_RESULT_REG | AL_RESULT_80,
AL_RESULT_REG128 = AL_RESULT_REG | AL_RESULT_128,
AL_RESULT_CTPR32 = AL_RESULT_CTPR | AL_RESULT_32,
AL_RESULT_CTPR64 = AL_RESULT_CTPR | AL_RESULT_64,
} AlResultType;
#define e2k_al_result_size(x) ((x) & AL_RESULT_SIZE_MASK)
#define e2k_al_result_type(x) ((x) & AL_RESULT_TYPE_MASK)
typedef struct {
AlResultType type;
/* check tag for 32-bit ops if wdbl is set */
bool check_tag;
/* poison result if tag is not zero */
bool poison;
/* Is 32-bit op affected by wdbl */
bool dbl;
union {
struct {
TCGv_i32 index;
TCGv_i32 tag;
union {
TCGv_i32 v32;
TCGv_i64 v64;
};
union {
TCGv_i32 x32; /* FX ops */
TCGv_i64 x64; /* SIMD ops v5+ */
};
} reg;
struct {
int index;
union {
TCGv_i32 v32;
TCGv_i64 v64;
};
} ctpr;
struct {
int index;
TCGv_i32 val;
} preg;
};
} AlResult;
typedef struct {
bool is_set;
uint8_t dst;
TCGv_i32 index;
TCGv_i32 tag;
TCGv_i64 value;
} AauResult;
typedef struct {
int reg; // -1 means do not write
TCGv_i32 value;
} PlResult;
typedef enum {
CT_NONE,
CT_IBRANCH,
CT_JUMP,
CT_CALL,
} ControlTransferType;
typedef struct {
ControlTransferType type;
union {
target_ulong target;
TCGv_i64 ctpr;
} u;
int wbs;
uint8_t cond_type;
uint8_t psrc;
} ControlTransfer;
typedef struct DisasContext {
DisasContextBase base;
UnpackedBundle bundle;
Bundle bundle2;
target_ulong pc;
int jump_ctpr;
int mmuidx;
uint8_t mas[6];
bool loop_mode;
TCGv_i32 is_epilogue;
/* optional, can be NULL */
TCGv_i32 mlock;
int version;
/* Force ILLOP for bad instruction format for cases where real CPU
do not generate it. */
bool strict;
// Temporary values.
TCGv_i32 t32[64];
TCGv_i64 t64[32];
TCGv ttl[8];
// Allocated temporary values count.
int t32_len;
int t64_len;
int ttl_len;
/* Delayed illegal tag check */
TCGv_i32 illtag;
bool do_check_illtag;
/* Delayed window bounds check */
int wd_size;
int max_r;
int max_r_src;
int max_r_dst;
int bsize;
int max_b;
int max_b_cur;
TCGv_i64 cond[6];
AlResult al_results[6];
TCGv_i32 al_cond[6];
AauResult aau_results[4];
int aau_am[4];
PlResult pl_results[3];
ControlTransfer ct;
} DisasContext;
static inline void gen_save_pc(target_ulong pc)
{
tcg_gen_movi_tl(e2k_cs.pc, pc);
}
static inline void gen_save_cpu_state(DisasContext *ctx)
{
gen_save_pc(ctx->pc);
}
static inline void gen_tr_exception(DisasContext *ctx, int exception_index)
{
TCGv_i32 t0 = tcg_const_i32(exception_index);
ctx->base.is_jmp = DISAS_NORETURN;
gen_save_cpu_state(ctx);
gen_helper_raise_exception(cpu_env, t0);
tcg_temp_free_i32(t0);
}
#define IMPL_GEN_TR_EXCP(name, excp) \
static inline void name(DisasContext *ctx) \
{ \
gen_tr_exception(ctx, excp); \
}
IMPL_GEN_TR_EXCP(gen_tr_excp_illopc, EXCP_ILLEGAL_OPCODE)
IMPL_GEN_TR_EXCP(gen_tr_excp_illopn, EXCP_ILLEGAL_OPERAND)
IMPL_GEN_TR_EXCP(gen_tr_excp_window_bounds, EXCP_WINDOW_BOUNDS)
IMPL_GEN_TR_EXCP(gen_tr_excp_array_bounds, EXCP_ARRAY_BOUNDS)
static inline void gen_exception(int excp)
{
TCGv_i32 t0 = tcg_const_i32(excp);
// TODO: check if need to save state
gen_helper_raise_exception(cpu_env, t0);
tcg_temp_free_i32(t0);
}
#define IMPL_GEN_EXCP(name, excp) \
static inline void name(void) \
{ \
gen_exception(excp); \
}
IMPL_GEN_EXCP(gen_excp_illopc, EXCP_ILLEGAL_OPCODE)
IMPL_GEN_EXCP(gen_excp_window_bounds, EXCP_WINDOW_BOUNDS)
#define e2k_todo(ctx, fmt, ...) \
qemu_log(TARGET_FMT_lx ": " fmt " (%s:%d)\n", ctx->pc, \
## __VA_ARGS__, __FILE__, __LINE__)
#define e2k_todo_illop(ctx, fmt, ...) \
e2k_todo(ctx, fmt, ## __VA_ARGS__); \
gen_tr_excp_illopc(ctx)
static inline TCGv_i32 e2k_get_temp_i32(DisasContext *dc)
{
assert(dc->t32_len < ARRAY_SIZE(dc->t32));
return dc->t32[dc->t32_len++] = tcg_temp_local_new_i32();
}
static inline TCGv_i32 e2k_get_const_i32(DisasContext *dc, uint32_t value)
{
assert(dc->t32_len < ARRAY_SIZE(dc->t32));
return dc->t32[dc->t32_len++] = tcg_const_local_i32(value);
}
static inline TCGv_i64 e2k_get_temp_i64(DisasContext *dc)
{
assert(dc->t64_len < ARRAY_SIZE(dc->t64));
return dc->t64[dc->t64_len++] = tcg_temp_local_new_i64();
}
static inline TCGv_i64 e2k_get_const_i64(DisasContext *dc, uint64_t value)
{
assert(dc->t64_len < ARRAY_SIZE(dc->t64));
return dc->t64[dc->t64_len++] = tcg_const_local_i64(value);
}
static inline TCGv e2k_get_temp(DisasContext *dc)
{
assert(dc->ttl_len < ARRAY_SIZE(dc->ttl));
return dc->ttl[dc->ttl_len++] = tcg_temp_local_new();
}
static inline TCGv e2k_get_const(DisasContext *dc, target_ulong value)
{
assert(dc->ttl_len < ARRAY_SIZE(dc->ttl));
return dc->ttl[dc->ttl_len++] = tcg_const_local_tl(value);
}
static inline void e2k_gen_lcntex(TCGv_i32 ret)
{
tcg_gen_setcondi_i32(TCG_COND_EQ, ret, e2k_cs.lsr_lcnt, 0);
}
void e2k_gen_store_preg(int idx, TCGv_i32 val);
void e2k_gen_reg_tag_read_i64(TCGv_i32 ret, TCGv_i32 idx);
void e2k_gen_reg_tag_read_i32(TCGv_i32 ret, TCGv_i32 idx);
void e2k_gen_reg_tag_write_i64(TCGv_i32 value, TCGv_i32 idx);
void e2k_gen_reg_tag_write_i32(TCGv_i32 value, TCGv_i32 idx);
static inline void e2k_gen_reg_tag_writei_i64(int value, TCGv_i32 idx)
{
TCGv_i32 t0 = tcg_const_i32(value);
e2k_gen_reg_tag_write_i64(t0, idx);
tcg_temp_free_i32(t0);
}
static inline void e2k_gen_reg_tag_writei_i32(int value, TCGv_i32 idx)
{
TCGv_i32 t0 = tcg_const_i32(value);
e2k_gen_reg_tag_write_i32(t0, idx);
tcg_temp_free_i32(t0);
}
static inline void e2k_gen_reg_tag_extract_lo(TCGv_i32 ret, TCGv_i32 tags)
{
tcg_gen_andi_i32(ret, tags, GEN_MASK(0, E2K_TAG_SIZE));
}
static inline void e2k_gen_reg_tag_extract_hi(TCGv_i32 ret, TCGv_i32 tags)
{
tcg_gen_shri_i32(ret, tags, E2K_TAG_SIZE);
}
void e2k_gen_reg_tag_check_i64(TCGv_i32 ret, TCGv_i32 tag);
void e2k_gen_reg_tag_check_i32(TCGv_i32 ret, TCGv_i32 tag);
void e2k_gen_reg_index_from_wregi(TCGv_i32 ret, int idx);
void e2k_gen_reg_index_from_bregi(TCGv_i32 ret, int idx);
void e2k_gen_reg_index_from_gregi(TCGv_i32 ret, int idx);
static inline void e2k_gen_reg_index(DisasContext *ctx, TCGv_i32 ret, uint8_t arg)
{
if (IS_BASED(arg)) {
e2k_gen_reg_index_from_bregi(ret, GET_BASED(arg));
} else if (IS_REGULAR(arg)) {
e2k_gen_reg_index_from_wregi(ret, GET_REGULAR(arg));
} else if (IS_GLOBAL(arg)) {
e2k_gen_reg_index_from_gregi(ret, GET_GLOBAL(arg));
} else {
gen_tr_exception(ctx, EXCP_ILLEGAL_OPERAND);
}
}
void e2k_gen_reg_lo_read_i64(TCGv_i64 ret, TCGv_i32 idx);
void e2k_gen_reg_lo_read_i32(TCGv_i32 ret, TCGv_i32 idx);
void e2k_gen_reg_lo_write_i64(TCGv_i64 value, TCGv_i32 idx);
void e2k_gen_reg_lo_write_i32(TCGv_i32 value, TCGv_i32 idx);
void e2k_gen_reg_hi_read_i64(TCGv_i64 ret, TCGv_i32 idx);
void e2k_gen_reg_hi_read_i32(TCGv_i32 ret, TCGv_i32 idx);
void e2k_gen_reg_hi_read16u_i32(TCGv_i32 ret, TCGv_i32 idx);
void e2k_gen_reg_hi_write_i64(TCGv_i64 value, TCGv_i32 idx);
void e2k_gen_reg_hi_write_i32(TCGv_i32 value, TCGv_i32 idx);
void e2k_gen_reg_hi_write16u_i32(TCGv_i32 value, TCGv_i32 idx);
void e2k_gen_preg_i32(TCGv_i32 ret, int reg);
void e2k_gen_cond_i32(DisasContext *ctx, TCGv_i32 ret, uint8_t psrc);
static inline void e2k_gen_is_loop_end_i32(TCGv_i32 ret)
{
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 t2 = tcg_temp_new_i32();
tcg_gen_setcondi_i32(TCG_COND_EQ, t0, e2k_cs.lsr_ecnt, 0);
tcg_gen_setcondi_i32(TCG_COND_LTU, t1, e2k_cs.lsr_lcnt, 2);
tcg_gen_and_i32(t2, t0, t1);
tcg_gen_and_i32(ret, t2, e2k_cs.lsr_vlc);
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
}
void e2k_decode_jmp(DisasContext *ctx);
void e2k_stubs_commit(DisasContext *ctx);
void alc_init(DisasContext *ctx);
void e2k_alc_decode(DisasContext *ctx);
void e2k_alc_execute(DisasContext *ctx);
void e2k_alc_commit(DisasContext *ctx);
void e2k_aau_execute(DisasContext *ctx);
void e2k_aau_commit(DisasContext *ctx);
void e2k_plu_execute(DisasContext *ctx);
void e2k_plu_commit(DisasContext *ctx);
#endif

View File

@ -1,188 +0,0 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "exec/log.h"
#include "translate.h"
typedef struct {
int chan;
union {
struct {
uint16_t am: 1;
uint16_t ind: 5;
uint16_t area: 6;
uint16_t opc: 3;
uint16_t be: 1;
};
uint16_t aas;
};
uint8_t dst;
} Mova;
static void gen_load_prefetch_program(DisasContext *ctx)
{
gen_helper_aau_load_program(cpu_env);
}
static void gen_aau_result(DisasContext *ctx, Mova *instr, TCGv_i64 dst,
TCGv_i32 tag)
{
AauResult *res = &ctx->aau_results[instr->chan];
res->is_set = true;
res->index = e2k_get_temp_i32(ctx);
res->value = dst;
res->tag = tag;
if (IS_REGULAR(instr->dst)) {
res->dst = instr->dst;
} else {
res->dst = 0;
e2k_gen_reg_index(ctx, res->index, instr->dst);
}
}
static void gen_checked_ld(DisasContext *ctx, Mova *instr, TCGv ptr)
{
TCGLabel *l0 = gen_new_label();
TCGLabel *l1 = gen_new_label();
TCGv_i32 tag = e2k_get_temp_i32(ctx);
TCGv_i64 dst = e2k_get_temp_i64(ctx);
MemOp memop = instr->be ? MO_BE : MO_LE;
switch(instr->opc) {
case 1: memop |= MO_8; break; /* movab */
case 2: memop |= MO_16; break; /* movah */
case 3: memop |= MO_32; break; /* movaw */
case 4: memop |= MO_64; break; /* movad */
default:
g_assert_not_reached();
break;
}
tcg_gen_brcondi_tl(TCG_COND_NE, ptr, 0, l0);
/* if address is invalid */
tcg_gen_movi_i32(tag, E2K_TAG_NON_NUMBER64);
tcg_gen_movi_i64(dst, E2K_MOVA_RESULT_INVALID);
tcg_gen_br(l1);
/* if address is valid */
gen_set_label(l0);
tcg_gen_movi_i32(tag, E2K_TAG_NUMBER64);
tcg_gen_qemu_ld_i64(dst, ptr, 0, memop);
gen_set_label(l1);
gen_aau_result(ctx, instr, dst, tag);
}
static inline void gen_mova_ptr(TCGv ret, Mova *instr)
{
TCGv_i32 t0 = tcg_const_i32(instr->chan);
TCGv_i32 t1 = tcg_const_i32(instr->area);
TCGv_i32 t2 = tcg_const_i32(instr->ind);
gen_helper_mova_ptr(ret, cpu_env, t0, t1, t2);
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
}
static void gen_mova(DisasContext *ctx, Mova *instr)
{
/* branch in gen_checked_ld */
TCGv t5 = tcg_temp_local_new();
ctx->aau_am[instr->chan] = instr->am ? instr->area : -1;
// TODO: check ind has proper alignment
// TODO: check ind is less than mrng
gen_mova_ptr(t5, instr);
switch(instr->opc) {
case 1: /* movab */
case 2: /* movah */
case 3: /* movaw */
case 4: /* movad */
gen_checked_ld(ctx, instr, t5);
break;
case 5: /* movaq */
e2k_todo_illop(ctx, "movaq");
break;
case 7: /* movaqp */
e2k_todo_illop(ctx, "movaqp");
break;
default:
gen_tr_excp_illopc(ctx);
break;
}
tcg_temp_free(t5);
}
static inline void gen_aau_am(DisasContext *ctx, int chan, int area)
{
TCGv_i32 t0 = tcg_const_i32(chan);
TCGv_i32 t1 = tcg_const_i32(area);
gen_helper_aau_am(cpu_env, t0, t1);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
}
void e2k_aau_execute(DisasContext *ctx)
{
const UnpackedBundle *bundle = &ctx->bundle;
unsigned int i;
for (i = 0; i < 4; i++) {
Mova instr = { 0 };
AauResult *res = &ctx->aau_results[i];
instr.chan = i;
instr.aas = bundle->aas[i + 2];
instr.dst = extract16(bundle->aas[i / 2], ((i & 1) ^ 1) * 8, 8);
if (!bundle->aas_present[i + 2] || instr.opc == 0) {
ctx->aau_am[i] = -1;
res->is_set = false;
continue;
}
// TODO: invalid value if addr is unaligned
gen_mova(ctx, &instr);
}
/* bap */
if (ctx->bundle.ss & (1 << 28)) {
gen_load_prefetch_program(ctx);
}
}
void e2k_aau_commit(DisasContext *ctx)
{
unsigned int i;
for (i = 0; i < 4; i++) {
AauResult *res = &ctx->aau_results[i];
if (res->is_set) {
if (IS_REGULAR(res->dst)) {
e2k_gen_reg_index_from_wregi(res->index, GET_REGULAR(res->dst));
}
}
}
for (i = 0; i < 4; i++) {
AauResult *res = &ctx->aau_results[i];
// TODO: aau.tags
if (res->is_set) {
e2k_gen_reg_tag_write_i64(res->tag, res->index);
e2k_gen_reg_lo_write_i64(res->value, res->index);
}
}
for (i = 0; i < 4; i++) {
int area = ctx->aau_am[i];
if (area == -1 || ((i == 1 || i == 3) && ctx->aau_am[i - 1] == area)) {
continue;
}
gen_aau_am(ctx, i, area);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,195 +0,0 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "exec/log.h"
#include "translate.h"
static void gen_get_lp(TCGv_i32 ret, uint16_t clp, int offset, TCGv_i32 lp[7])
{
int p = extract32(clp, offset, 3);
int neg = GET_BIT(clp, offset + 3);
tcg_gen_xori_i32(ret, lp[p], neg);
}
void e2k_gen_cond_i32(DisasContext *ctx, TCGv_i32 ret, uint8_t psrc)
{
if (psrc & 0x80) {
if (psrc == 0xc0) {
// %bgrpred
e2k_todo_illop(ctx, "%%bgrpred");
} else if ((psrc & 0xe0) == 0xc0) {
// %rndpred
e2k_todo_illop(ctx, "%%rndpred");
} else {
gen_tr_excp_illopn(ctx);
}
} else {
int idx = extract8(psrc, 0, 5);
if (psrc == 0) {
// %lcntex
e2k_gen_lcntex(ret);
} else if ((psrc & 0x40) == 0) {
// %spredMASK
e2k_todo_illop(ctx, "%%spred");
} else if ((psrc & 0x60) == 0x60) {
// %predN
e2k_gen_preg_i32(ret, idx);
} else {
// %pcntN
tcg_gen_setcondi_i32(TCG_COND_LEU, ret, e2k_cs.lsr_pcnt, idx);
}
}
}
static inline void scan_needed(const UnpackedBundle *bundle, int need[7])
{
bool once_more = true;
unsigned int i;
for (i = 0; i < 3; i++) {
if (bundle->pls_present[i] && GET_BIT(bundle->pls[i], 5)) {
need[4 + i] = 1;
}
}
while (once_more) {
once_more = false;
for (i = 0; i < 3; i++) {
int p0, p1;
if (need[4 + i] != 1) {
continue;
}
p0 = extract32(bundle->pls[i], 10, 3);
p1 = extract32(bundle->pls[i], 6, 3);
if (p0 < 7 && need[p0] == 0) {
need[p0] = 1;
if (p0 >= 4) {
once_more = true;
}
}
if (p1 < 7 && need[p1] == 0) {
need[p1] = 1;
if (p1 >= 4) {
once_more = true;
}
}
need[4 + i] = 2;
}
}
}
void e2k_plu_execute(DisasContext *ctx)
{
const UnpackedBundle *bundle = &ctx->bundle;
int need[7] = { 0 };
unsigned int i;
TCGv_i32 lp[7];
scan_needed(bundle, need);
for (i = 0; i < 7; i++) {
if (need[i]) {
lp[i] = tcg_temp_new_i32();
}
}
for (i = 0; i < 3; i++) {
ctx->pl_results[i].reg = -1;
if (!bundle->pls_present[i]) {
continue;
}
if (i < 2) {
if (need[i * 2]) {
int elp = extract32(bundle->pls[i], 24, 7);
e2k_gen_cond_i32(ctx, lp[i * 2], elp);
}
if (need[i * 2 + 1]) {
int elp = extract32(bundle->pls[i], 16, 7);
e2k_gen_cond_i32(ctx, lp[i * 2 + 1], elp);
}
}
if (need[4 + i]) {
uint16_t clp = extract32(bundle->pls[i], 0, 16);
int opc = extract32(clp, 14, 2);
TCGv_i32 p0 = tcg_temp_new_i32();
TCGv_i32 p1 = tcg_temp_new_i32();
int vdst = GET_BIT(clp, 5);
int pdst = extract32(clp, 0, 5);
// TODO: check clp arg
// {C/M}LP0 0, 1 => 4
// {C/M}LP1 0, 1, 2, 3, 4 => 5
// {C/M}LP2 0, 1, 2, 3, 4, 5 => 6
// maximal cascading is 2
gen_get_lp(p0, clp, 10, lp);
gen_get_lp(p1, clp, 6, lp);
if (vdst) {
ctx->pl_results[i].reg = pdst;
ctx->pl_results[i].value = e2k_get_temp_i32(ctx);
}
switch (opc) {
case 0: /* andp */
// FIXME: what is the difference between `andp` and `landp`?
case 1: /* landp */
tcg_gen_and_i32(lp[4 + i], p0, p1);
if (vdst) {
tcg_gen_mov_i32(ctx->pl_results[i].value, lp[4 + i]);
}
break;
case 3: { /* movep */
// FIXME: clp cannot read result of movep???
tcg_gen_and_i32(lp[4 + i], p0, p1);
if (vdst) {
TCGv_i32 z = tcg_const_i32(0);
TCGv_i32 t0 = tcg_temp_new_i32();
e2k_gen_preg_i32(t0, pdst);
tcg_gen_movcond_i32(TCG_COND_NE, ctx->pl_results[i].value,
p0, z, p1, t0);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(z);
}
break;
}
default:
abort();
break;
}
}
}
for (i = 0; i < 7; i++) {
if (need[i]) {
tcg_temp_free_i32(lp[i]);
}
}
}
void e2k_plu_commit(DisasContext *ctx)
{
unsigned int i;
for (i = 0; i < 3; i++) {
if (ctx->pl_results[i].reg < 0) {
continue;
}
e2k_gen_store_preg(ctx->pl_results[i].reg, ctx->pl_results[i].value);
}
}

View File

@ -1,275 +0,0 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "exec/log.h"
#include "translate.h"
static inline void gen_ptr_from_index(TCGv_ptr ret, TCGv_ptr ptr, TCGv_i32 idx,
int size)
{
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_ptr t1 = tcg_temp_new_ptr();
tcg_gen_muli_i32(t0, idx, size);
tcg_gen_ext_i32_ptr(t1, t0);
tcg_gen_add_ptr(ret, ptr, t1);
tcg_temp_free_ptr(t1);
tcg_temp_free_i32(t0);
}
static inline void gen_preg_index(TCGv_i32 ret, int idx)
{
TCGv_i32 i = tcg_const_i32(idx);
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 t2 = tcg_temp_new_i32();
TCGv_i32 t3 = tcg_temp_new_i32();
assert(idx < 32);
tcg_gen_addi_i32(t0, e2k_cs.psize, 1);
tcg_gen_addi_i32(t1, e2k_cs.pcur, idx);
tcg_gen_remu_i32(t2, t1, t0);
tcg_gen_movi_i32(t3, idx);
tcg_gen_movcond_i32(TCG_COND_LEU, ret, i, e2k_cs.psize, t2, t3);
tcg_temp_free_i32(t3);
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(i);
}
static void gen_preg_offset(TCGv_i64 ret, int idx)
{
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
gen_preg_index(t0, idx);
tcg_gen_muli_i32(t1, t0, 2);
tcg_gen_extu_i32_i64(ret, t1);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
}
static void gen_preg_clear(TCGv_i64 ret, TCGv_i64 offset)
{
TCGv_i64 t0 = tcg_const_i64(3);
TCGv_i64 t1 = tcg_temp_new_i64();
TCGv_i64 t2 = tcg_temp_new_i64();
tcg_gen_shl_i64(t1, t0, offset);
tcg_gen_not_i64(t2, t1);
tcg_gen_and_i64(ret, t2, e2k_cs.pregs);
tcg_temp_free_i64(t2);
tcg_temp_free_i64(t1);
tcg_temp_free_i64(t0);
}
static inline void gen_preg_i64(TCGv_i64 ret, int reg)
{
TCGv_i64 one = tcg_const_i64(1);
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
TCGv_i64 t2 = tcg_temp_new_i64();
gen_preg_offset(t0, reg);
tcg_gen_shl_i64(t1, one, t0);
tcg_gen_and_i64(t2, e2k_cs.pregs, t1);
tcg_gen_setcondi_i64(TCG_COND_NE, ret, t2, 0);
tcg_temp_free_i64(t2);
tcg_temp_free_i64(t1);
tcg_temp_free_i64(t0);
tcg_temp_free_i64(one);
}
void e2k_gen_preg_i32(TCGv_i32 ret, int reg)
{
TCGv_i64 t0 = tcg_temp_new_i64();
gen_preg_i64(t0, reg);
tcg_gen_extrl_i64_i32(ret, t0);
tcg_temp_free_i64(t0);
}
void e2k_gen_store_preg(int idx, TCGv_i32 val)
{
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
TCGv_i64 t4 = tcg_temp_new_i64();
gen_preg_offset(t0, idx);
gen_preg_clear(t1, t0);
tcg_gen_extu_i32_i64(t2, val);
tcg_gen_andi_i64(t3, t2, 3);
tcg_gen_shl_i64(t4, t2, t0);
tcg_gen_or_i64(e2k_cs.pregs, t1, t4);
tcg_temp_free_i64(t4);
tcg_temp_free_i64(t3);
tcg_temp_free_i64(t2);
tcg_temp_free_i64(t1);
tcg_temp_free_i64(t0);
}
static inline void gen_reg_tag_ptr(TCGv_ptr ret, TCGv_i32 idx)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
TCGv_ptr t1 = tcg_temp_new_ptr();
tcg_gen_ext_i32_ptr(t0, idx);
tcg_gen_addi_ptr(t1, cpu_env, offsetof(CPUE2KState, tags));
tcg_gen_add_ptr(ret, t1, t0);
tcg_temp_free_ptr(t1);
tcg_temp_free_ptr(t0);
}
void e2k_gen_reg_tag_read_i64(TCGv_i32 ret, TCGv_i32 idx)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
gen_reg_tag_ptr(t0, idx);
tcg_gen_ld8u_i32(ret, t0, 0);
tcg_temp_free_ptr(t0);
}
void e2k_gen_reg_tag_read_i32(TCGv_i32 ret, TCGv_i32 idx)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
TCGv_i32 t1 = tcg_temp_new_i32();
gen_reg_tag_ptr(t0, idx);
tcg_gen_ld8u_i32(t1, t0, 0);
tcg_gen_andi_i32(ret, t1, GEN_MASK(0, E2K_TAG_SIZE));
tcg_temp_free_ptr(t0);
}
static inline void gen_tag_check(TCGv_i32 ret, TCGv_i32 tag)
{
// FIXME: what CPU does if tag is greater than 1?
tcg_gen_setcondi_i32(TCG_COND_NE, ret, tag, 0);
}
void e2k_gen_reg_tag_check_i64(TCGv_i32 ret, TCGv_i32 tag)
{
gen_tag_check(ret, tag);
}
void e2k_gen_reg_tag_check_i32(TCGv_i32 ret, TCGv_i32 tag)
{
TCGv_i32 t0 = tcg_temp_new_i32();
e2k_gen_reg_tag_extract_lo(t0, tag);
gen_tag_check(ret, t0);
tcg_temp_free_i32(t0);
}
void e2k_gen_reg_tag_write_i64(TCGv_i32 value, TCGv_i32 idx)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
gen_reg_tag_ptr(t0, idx);
tcg_gen_st8_i32(value, t0, 0);
tcg_temp_free_ptr(t0);
}
void e2k_gen_reg_tag_write_i32(TCGv_i32 value, TCGv_i32 idx)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 t2 = tcg_temp_new_i32();
gen_reg_tag_ptr(t0, idx);
tcg_gen_ld8u_i32(t1, t0, 0);
tcg_gen_deposit_i32(t2, t1, value, 0, E2K_TAG_SIZE);
tcg_gen_st8_i32(t2, t0, 0);
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t1);
tcg_temp_free_ptr(t0);
}
static inline void gen_reg_index_from_wreg(TCGv_i32 ret, TCGv_i32 idx)
{
tcg_gen_mov_i32(ret, idx);
}
void e2k_gen_reg_index_from_wregi(TCGv_i32 ret, int idx)
{
tcg_gen_movi_i32(ret, idx);
}
void e2k_gen_reg_index_from_bregi(TCGv_i32 ret, int idx)
{
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 t2 = tcg_temp_new_i32();
tcg_gen_addi_i32(t0, e2k_cs.bcur, idx);
tcg_gen_remu_i32(t1, t0, e2k_cs.bsize);
tcg_temp_free_i32(t0);
tcg_gen_add_i32(t2, e2k_cs.boff, t1);
tcg_temp_free_i32(t1);
gen_reg_index_from_wreg(ret, t2);
tcg_temp_free_i32(t2);
}
void e2k_gen_reg_index_from_gregi(TCGv_i32 ret, int idx)
{
// TODO: based global registers index
tcg_gen_movi_i32(ret, E2K_NR_COUNT + idx);
}
static inline void gen_reg_lo_ptr(TCGv_ptr ret, TCGv_i32 idx)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
tcg_gen_addi_ptr(t0, cpu_env, offsetof(CPUE2KState, regs));
gen_ptr_from_index(ret, t0, idx, sizeof(E2KReg));
tcg_temp_free_ptr(t0);
}
static inline void gen_reg_hi_ptr(TCGv_ptr ret, TCGv_i32 idx)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
gen_reg_lo_ptr(t0, idx);
tcg_gen_addi_ptr(ret, t0, offsetof(E2KReg, hi));
tcg_temp_free_ptr(t0);
}
#define GEN_REG_READ(name, ty, ptr_func, ld_func) \
void name(ty ret, TCGv_i32 idx) \
{ \
TCGv_ptr t0 = tcg_temp_new_ptr(); \
ptr_func(t0, idx); \
ld_func(ret, t0, 0); \
tcg_temp_free_ptr(t0); \
}
GEN_REG_READ(e2k_gen_reg_lo_read_i64, TCGv_i64, gen_reg_lo_ptr, tcg_gen_ld_i64)
GEN_REG_READ(e2k_gen_reg_lo_read_i32, TCGv_i32, gen_reg_lo_ptr, tcg_gen_ld_i32)
GEN_REG_READ(e2k_gen_reg_hi_read_i64, TCGv_i64, gen_reg_hi_ptr, tcg_gen_ld_i64)
GEN_REG_READ(e2k_gen_reg_hi_read_i32, TCGv_i32, gen_reg_hi_ptr, tcg_gen_ld_i32)
GEN_REG_READ(e2k_gen_reg_hi_read16u_i32, TCGv_i32, gen_reg_hi_ptr, tcg_gen_ld16u_i32)
#define GEN_REG_WRITE(name, ty, ptr_func, st_func) \
void name(ty value, TCGv_i32 idx) \
{ \
TCGv_ptr t0 = tcg_temp_new_ptr(); \
ptr_func(t0, idx); \
st_func(value, t0, 0); \
tcg_temp_free_ptr(t0); \
}
GEN_REG_WRITE(e2k_gen_reg_lo_write_i64, TCGv_i64, gen_reg_lo_ptr, tcg_gen_st_i64)
GEN_REG_WRITE(e2k_gen_reg_lo_write_i32, TCGv_i32, gen_reg_lo_ptr, tcg_gen_st_i32)
GEN_REG_WRITE(e2k_gen_reg_hi_write_i64, TCGv_i64, gen_reg_hi_ptr, tcg_gen_st_i64)
GEN_REG_WRITE(e2k_gen_reg_hi_write_i32, TCGv_i32, gen_reg_hi_ptr, tcg_gen_st_i32)
GEN_REG_WRITE(e2k_gen_reg_hi_write16u_i32, TCGv_i32, gen_reg_hi_ptr, tcg_gen_st16_i32)