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:
parent
17be44b21b
commit
6fb98e718e
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 } },
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
@ -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
|
|
|
@ -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
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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)
|
|
Loading…
Reference in New Issue