target: e2k: Add basic FX instrs.
This commit is contained in:
parent
7f949defe5
commit
a0e898c7da
@ -1,3 +1,10 @@
|
||||
#define dh_alias_Reg ptr
|
||||
#define dh_alias_f80 ptr
|
||||
#define dh_ctype_Reg E2KReg *
|
||||
#define dh_ctype_f80 floatx80 *
|
||||
#define dh_is_signed_Reg 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_no_spill, noreturn, env, int)
|
||||
DEF_HELPER_1(debug, void, env)
|
||||
@ -51,10 +58,12 @@ DEF_HELPER_3_32_64(fcmpod)
|
||||
DEF_HELPER_2(fstois, i32, env, i32)
|
||||
DEF_HELPER_2(istofs, i32, env, i32)
|
||||
DEF_HELPER_2(fstoistr, i32, env, i32)
|
||||
DEF_HELPER_3(fstofx, void, f80, env, i32)
|
||||
|
||||
DEF_HELPER_2(fdtoid, i64, env, i64)
|
||||
DEF_HELPER_2(idtofd, i64, env, i64)
|
||||
DEF_HELPER_2(fdtoidtr, i64, env, i64)
|
||||
DEF_HELPER_3(fdtofx, void, f80, env, i64)
|
||||
|
||||
DEF_HELPER_2(fstofd, i64, env, i32)
|
||||
DEF_HELPER_2(fstoid, i64, env, i32)
|
||||
@ -65,3 +74,12 @@ DEF_HELPER_2(fdtofs, i32, env, i64)
|
||||
DEF_HELPER_2(fdtois, i32, env, i64)
|
||||
DEF_HELPER_2(idtofs, i32, env, i64)
|
||||
DEF_HELPER_2(fdtoistr, i32, env, i64)
|
||||
|
||||
DEF_HELPER_2(fxtofs, i32, env, f80)
|
||||
DEF_HELPER_2(fxtofd, i64, env, f80)
|
||||
|
||||
DEF_HELPER_3(fxaddxx, void, env, f80, f80)
|
||||
DEF_HELPER_3(fxsubxx, void, env, f80, f80)
|
||||
DEF_HELPER_3(fxrsubxx, void, env, f80, f80)
|
||||
DEF_HELPER_3(fxmulxx, void, env, f80, f80)
|
||||
DEF_HELPER_3(fxdivxx, void, env, f80, f80)
|
||||
|
@ -5,6 +5,9 @@
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
#define glue3(x, y, z) glue(glue(x, y), z)
|
||||
#define deref(x) *(x)
|
||||
|
||||
static inline void fpu_set_exception(CPUE2KState *env, int mask)
|
||||
{
|
||||
env->fpsr.ef |= mask;
|
||||
@ -93,21 +96,21 @@ void e2k_update_fp_status(CPUE2KState *env)
|
||||
#define no_cvt(x) (x) // when function already returns in correct type
|
||||
|
||||
#define GENERATE_CVT_FLOAT1_OP(name, from_t, to_t, size_from, size_to, func_from, func_to) \
|
||||
uint##size_to##_t HELPER(name)(CPUE2KState *env, uint##size_from##_t x) \
|
||||
size_to HELPER(name)(CPUE2KState *env, size_from x) \
|
||||
{\
|
||||
uint8_t old_flags = save_exception_flags(env); \
|
||||
uint##size_to##_t z = func_to( from_t##_to_##to_t (func_from(x), &env->fp_status) );\
|
||||
size_to z = func_to( glue3(from_t, _to_, to_t) (func_from(x), &env->fp_status) );\
|
||||
merge_exception_flags(env, old_flags); \
|
||||
return z; \
|
||||
}
|
||||
|
||||
#define GENERATE_SIMPLE_FLOAT2_OPS_32_64(name, function) \
|
||||
GENERATE_SIMPLE_FLOAT2_OP(name##s, function, 32) \
|
||||
GENERATE_SIMPLE_FLOAT2_OP(name##d, function, 64)
|
||||
GENERATE_SIMPLE_FLOAT2_OP(glue(name, s), function, 32) \
|
||||
GENERATE_SIMPLE_FLOAT2_OP(glue(name, d), function, 64)
|
||||
|
||||
#define GENERATE_CMP_FLOAT2_OPS_32_64(name, function, expr) \
|
||||
GENERATE_CMP_FLOAT2_OP(name##s, function, expr, 32) \
|
||||
GENERATE_CMP_FLOAT2_OP(name##d, function, expr, 64)
|
||||
GENERATE_CMP_FLOAT2_OP(glue(name, s), function, expr, 32) \
|
||||
GENERATE_CMP_FLOAT2_OP(glue(name, d), function, expr, 64)
|
||||
|
||||
GENERATE_SIMPLE_FLOAT2_OPS_32_64(fadd, add)
|
||||
GENERATE_SIMPLE_FLOAT2_OPS_32_64(fsub, sub)
|
||||
@ -124,20 +127,57 @@ GENERATE_CMP_FLOAT2_OPS_32_64(fcmpnlt, lt, !)
|
||||
GENERATE_CMP_FLOAT2_OPS_32_64(fcmpuod, unordered, )
|
||||
GENERATE_CMP_FLOAT2_OPS_32_64(fcmpod, unordered, !)
|
||||
|
||||
GENERATE_CVT_FLOAT1_OP(fstois, float32, int32, 32, 32, make_float32, no_cvt)
|
||||
GENERATE_CVT_FLOAT1_OP(istofs, int32, float32, 32, 32, no_cvt, float32_val)
|
||||
GENERATE_CVT_FLOAT1_OP(fstoistr, float32, int32_round_to_zero, 32, 32, make_float32, no_cvt)
|
||||
GENERATE_CVT_FLOAT1_OP(fstois, float32, int32, uint32_t, uint32_t, make_float32, no_cvt)
|
||||
GENERATE_CVT_FLOAT1_OP(istofs, int32, float32, uint32_t, uint32_t, no_cvt, float32_val)
|
||||
GENERATE_CVT_FLOAT1_OP(fstoistr, float32, int32_round_to_zero, uint32_t, uint32_t, make_float32, no_cvt)
|
||||
|
||||
GENERATE_CVT_FLOAT1_OP(fdtoid, float64, int64, 64, 64, make_float64, no_cvt)
|
||||
GENERATE_CVT_FLOAT1_OP(idtofd, int64, float64, 64, 64, no_cvt, float64_val)
|
||||
GENERATE_CVT_FLOAT1_OP(fdtoidtr, float64, int64_round_to_zero, 64, 64, make_float64, no_cvt)
|
||||
GENERATE_CVT_FLOAT1_OP(fdtoid, float64, int64, uint64_t, uint64_t, make_float64, no_cvt)
|
||||
GENERATE_CVT_FLOAT1_OP(idtofd, int64, float64, uint64_t, uint64_t, no_cvt, float64_val)
|
||||
GENERATE_CVT_FLOAT1_OP(fdtoidtr, float64, int64_round_to_zero, uint64_t, uint64_t, make_float64, no_cvt)
|
||||
|
||||
GENERATE_CVT_FLOAT1_OP(fstofd, float32, float64, 32, 64, make_float32, float64_val)
|
||||
GENERATE_CVT_FLOAT1_OP(fstoid, float32, int64, 32, 64, make_float32, no_cvt)
|
||||
GENERATE_CVT_FLOAT1_OP(istofd, int32, float64, 32, 64, no_cvt, float64_val)
|
||||
GENERATE_CVT_FLOAT1_OP(fstoidtr, float32, int64_round_to_zero, 32, 64, make_float32, no_cvt)
|
||||
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, no_cvt)
|
||||
GENERATE_CVT_FLOAT1_OP(istofd, int32, float64, uint32_t, uint64_t, no_cvt, float64_val)
|
||||
GENERATE_CVT_FLOAT1_OP(fstoidtr, float32, int64_round_to_zero, uint32_t, uint64_t, make_float32, no_cvt)
|
||||
|
||||
GENERATE_CVT_FLOAT1_OP(fdtofs, float64, float32, 64, 32, make_float64, float32_val)
|
||||
GENERATE_CVT_FLOAT1_OP(fdtois, float64, int32, 64, 32, make_float64, no_cvt)
|
||||
GENERATE_CVT_FLOAT1_OP(idtofs, int64, float32, 64, 32, no_cvt, float32_val)
|
||||
GENERATE_CVT_FLOAT1_OP(fdtoistr, float64, int32_round_to_zero, 64, 32, make_float64, no_cvt)
|
||||
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, no_cvt)
|
||||
GENERATE_CVT_FLOAT1_OP(idtofs, int64, float32, uint64_t, uint32_t, no_cvt, float32_val)
|
||||
GENERATE_CVT_FLOAT1_OP(fdtoistr, float64, int32_round_to_zero, uint64_t, uint32_t, make_float64, no_cvt)
|
||||
|
||||
GENERATE_CVT_FLOAT1_OP(fxtofs, floatx80, float32, floatx80*, uint32_t, deref, float32_val)
|
||||
GENERATE_CVT_FLOAT1_OP(fxtofd, floatx80, float64, floatx80*, uint64_t, deref, float64_val)
|
||||
|
||||
void HELPER(fstofx)(floatx80 *ret, CPUE2KState *env, uint32_t x)
|
||||
{
|
||||
uint8_t old_flags = save_exception_flags(env);
|
||||
*ret = float32_to_floatx80(make_float32(x), &env->fp_status);
|
||||
merge_exception_flags(env, old_flags);
|
||||
}
|
||||
|
||||
void HELPER(fdtofx)(floatx80 *ret, CPUE2KState *env, uint64_t x)
|
||||
{
|
||||
uint8_t old_flags = save_exception_flags(env);
|
||||
*ret = float64_to_floatx80(make_float64(x), &env->fp_status);
|
||||
merge_exception_flags(env, old_flags);
|
||||
}
|
||||
|
||||
#define GEN_OP2_XX(name, op) \
|
||||
void HELPER(name)(CPUE2KState *env, floatx80 *x, floatx80 *y) \
|
||||
{ \
|
||||
uint8_t old_flags = save_exception_flags(env); \
|
||||
*x = glue(floatx80_, op)(*x, *y, &env->fp_status); \
|
||||
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)
|
||||
{
|
||||
uint8_t old_flags = save_exception_flags(env);
|
||||
*x = floatx80_sub(*y, *x, &env->fp_status);
|
||||
merge_exception_flags(env, old_flags);
|
||||
}
|
||||
|
@ -372,11 +372,11 @@ static inline void do_branch(DisasContext *ctx, target_ulong pc_next)
|
||||
|
||||
static void e2k_tr_init_disas_context(DisasContextBase *db, CPUState *cs)
|
||||
{
|
||||
DisasContext *dc = container_of(db, DisasContext, base);
|
||||
DisasContext *ctx = container_of(db, DisasContext, base);
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
dc->version = env->version;
|
||||
ctx->version = env->version;
|
||||
}
|
||||
|
||||
static bool e2k_tr_breakpoint_check(DisasContextBase *db, CPUState *cs,
|
||||
|
@ -19,6 +19,35 @@ typedef struct {
|
||||
TCGv_i32 value;
|
||||
} Src32;
|
||||
|
||||
static inline Src80 temp_new_src80(void)
|
||||
{
|
||||
Src80 t = { 0 };
|
||||
|
||||
t.tag = tcg_temp_new_i32();
|
||||
t.lo = tcg_temp_new_i64();
|
||||
t.hi = tcg_temp_new_i32();
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static inline void temp_free_src80(Src80 *t)
|
||||
{
|
||||
tcg_temp_free_i32(t->tag);
|
||||
tcg_temp_free_i64(t->lo);
|
||||
tcg_temp_free_i32(t->hi);
|
||||
}
|
||||
|
||||
static inline Src80 get_temp_src80(DisasContext *ctx)
|
||||
{
|
||||
Src80 t = { 0 };
|
||||
|
||||
t.tag = e2k_get_temp_i32(ctx);
|
||||
t.lo = e2k_get_temp_i64(ctx);
|
||||
t.hi = e2k_get_temp_i32(ctx);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int chan;
|
||||
union {
|
||||
@ -131,6 +160,20 @@ static inline void gen_reg_i32(DisasContext *ctx, Src32 *ret, uint8_t arg)
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
||||
static inline void gen_temp_reg_write_i64_i32(TCGv_i64 lo, TCGv_i32 hi,
|
||||
TCGv_ptr ptr)
|
||||
{
|
||||
tcg_gen_st_i64(lo, ptr, offsetof(E2KReg, f80.low));
|
||||
tcg_gen_st16_i32(hi, ptr, offsetof(E2KReg, f80.high));
|
||||
}
|
||||
|
||||
static inline void gen_temp_reg_read_i64_i32(TCGv_ptr ptr, TCGv_i64 ret_lo,
|
||||
TCGv_i32 ret_hi)
|
||||
{
|
||||
tcg_gen_ld_i64(ret_lo, ptr, offsetof(E2KReg, f80.low));
|
||||
tcg_gen_ld16u_i32(ret_hi, ptr, offsetof(E2KReg, f80.high));
|
||||
}
|
||||
|
||||
static inline void gen_literal_i64(DisasContext *ctx, Src64 *ret, uint8_t arg)
|
||||
{
|
||||
int i = GET_LIT(arg);
|
||||
@ -1650,6 +1693,46 @@ static inline void gen_movif(DisasContext *ctx, Instr *instr)
|
||||
gen_al_result_i80(ctx, instr, src1.value, src2.value, tag);
|
||||
}
|
||||
|
||||
static inline void gen_fstofx(Src80 *ret, TCGv_i32 src2)
|
||||
{
|
||||
TCGv_ptr t0 = tcg_temp_new_ptr();
|
||||
|
||||
tcg_gen_addi_ptr(t0, cpu_env, offsetof(CPUE2KState, t0.f80));
|
||||
gen_helper_fstofx(t0, cpu_env, src2);
|
||||
gen_temp_reg_read_i64_i32(t0, ret->lo, ret->hi);
|
||||
tcg_temp_free_ptr(t0);
|
||||
}
|
||||
|
||||
static inline void gen_fdtofx(Src80 *ret, TCGv_i64 src2)
|
||||
{
|
||||
TCGv_ptr t0 = tcg_temp_new_ptr();
|
||||
|
||||
tcg_gen_addi_ptr(t0, cpu_env, offsetof(CPUE2KState, t0));
|
||||
gen_helper_fdtofx(t0, cpu_env, src2);
|
||||
gen_temp_reg_read_i64_i32(t0, ret->lo, ret->hi);
|
||||
tcg_temp_free_ptr(t0);
|
||||
}
|
||||
|
||||
static inline void gen_fxtofs(TCGv_i32 ret, Src80 src2)
|
||||
{
|
||||
TCGv_ptr t0 = tcg_temp_new_ptr();
|
||||
|
||||
tcg_gen_addi_ptr(t0, cpu_env, offsetof(CPUE2KState, t0));
|
||||
gen_temp_reg_write_i64_i32(src2.lo, src2.hi, t0);
|
||||
gen_helper_fxtofs(ret, cpu_env, t0);
|
||||
tcg_temp_free_ptr(t0);
|
||||
}
|
||||
|
||||
static inline void gen_fxtofd(TCGv_i64 ret, Src80 src2)
|
||||
{
|
||||
TCGv_ptr t0 = tcg_temp_new_ptr();
|
||||
|
||||
tcg_gen_addi_ptr(t0, cpu_env, offsetof(CPUE2KState, t0));
|
||||
gen_temp_reg_write_i64_i32(src2.lo, src2.hi, t0);
|
||||
gen_helper_fxtofd(ret, cpu_env, t0);
|
||||
tcg_temp_free_ptr(t0);
|
||||
}
|
||||
|
||||
static void gen_aad_tag(TCGv_i64 ret, TCGv_i32 tag)
|
||||
{
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
@ -2186,6 +2269,191 @@ static void gen_alopf2_i32_i64_env(DisasContext *ctx, int chan, void (*op)(TCGv_
|
||||
gen_al_result_i64(ctx, chan, dst, tag);
|
||||
}
|
||||
|
||||
static inline void gen_alopf1_f80(Src80 *ret, Src80 src1, Src80 src2,
|
||||
void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr))
|
||||
{
|
||||
TCGv_ptr t0 = tcg_temp_new_ptr();
|
||||
TCGv_ptr t1 = tcg_temp_new_ptr();
|
||||
|
||||
gen_tag2_i64(ret->tag, src1.tag, src2.tag);
|
||||
|
||||
tcg_gen_addi_ptr(t0, cpu_env, offsetof(CPUE2KState, t0.f80));
|
||||
tcg_gen_addi_ptr(t1, cpu_env, offsetof(CPUE2KState, t1.f80));
|
||||
|
||||
gen_temp_reg_write_i64_i32(src1.lo, src1.hi, t0);
|
||||
gen_temp_reg_write_i64_i32(src2.lo, src2.hi, t1);
|
||||
|
||||
(*op)(cpu_env, t0, t1);
|
||||
|
||||
gen_temp_reg_read_i64_i32(t0, ret->lo, ret->hi);
|
||||
|
||||
tcg_temp_free_ptr(t1);
|
||||
tcg_temp_free_ptr(t0);
|
||||
}
|
||||
|
||||
static inline void gen_alopf1_xxx(DisasContext *ctx, Instr *instr,
|
||||
void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr))
|
||||
{
|
||||
Src80 src1 = get_src1_i80(ctx, instr->src1);
|
||||
Src80 src2 = get_src2_i80(ctx, instr->src2);
|
||||
Src80 res = get_temp_src80(ctx);
|
||||
gen_alopf1_f80(&res, src1, src2, op);
|
||||
gen_al_result_i80(ctx, instr, res.lo, res.hi, res.tag);
|
||||
}
|
||||
|
||||
static inline void gen_alopf1_xxs(DisasContext *ctx, Instr *instr,
|
||||
void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr))
|
||||
{
|
||||
Src80 src1 = get_src1_i80(ctx, instr->src1);
|
||||
Src80 src2 = get_src2_i80(ctx, instr->chan);
|
||||
TCGv_i32 tag = e2k_get_temp_i32(ctx);
|
||||
TCGv_i32 dst = e2k_get_temp_i32(ctx);
|
||||
Src80 t0 = temp_new_src80();
|
||||
|
||||
gen_tag2_i32(tag, src1.tag, src2.tag);
|
||||
gen_alopf1_f80(&t0, src1, src2, op);
|
||||
gen_fxtofs(dst, t0);
|
||||
gen_al_result_i32(ctx, instr->chan, dst, tag);
|
||||
|
||||
temp_free_src80(&t0);
|
||||
}
|
||||
|
||||
static inline void gen_alopf1_xxd(DisasContext *ctx, Instr *instr,
|
||||
void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr))
|
||||
{
|
||||
Src80 src1 = get_src1_i80(ctx, instr->src1);
|
||||
Src80 src2 = get_src2_i80(ctx, instr->chan);
|
||||
TCGv_i32 tag = e2k_get_temp_i32(ctx);
|
||||
TCGv_i64 dst = e2k_get_temp_i64(ctx);
|
||||
Src80 t0 = temp_new_src80();
|
||||
|
||||
gen_tag2_i64(tag, src1.tag, src2.tag);
|
||||
gen_alopf1_f80(&t0, src1, src2, op);
|
||||
gen_fxtofd(dst, t0);
|
||||
gen_al_result_i64(ctx, instr->chan, dst, tag);
|
||||
|
||||
temp_free_src80(&t0);
|
||||
}
|
||||
|
||||
static inline void gen_alopf1_xss(DisasContext *ctx, Instr *instr,
|
||||
void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr))
|
||||
{
|
||||
Src80 src1 = get_src1_i80(ctx, instr->src1);
|
||||
Src32 src2 = get_src2_i32(ctx, instr->chan);
|
||||
TCGv_i32 tag = e2k_get_temp_i32(ctx);
|
||||
TCGv_i32 dst = e2k_get_temp_i32(ctx);
|
||||
Src80 t0 = temp_new_src80();
|
||||
Src80 t1 = temp_new_src80();
|
||||
|
||||
gen_tag2_i32(tag, src1.tag, src2.tag);
|
||||
gen_fstofx(&t0, src2.value);
|
||||
gen_alopf1_f80(&t1, src1, t0, op);
|
||||
gen_fxtofs(dst, t1);
|
||||
gen_al_result_i32(ctx, instr->chan, dst, tag);
|
||||
|
||||
temp_free_src80(&t1);
|
||||
temp_free_src80(&t0);
|
||||
}
|
||||
|
||||
static inline void gen_alopf1_xdd(DisasContext *ctx, Instr *instr,
|
||||
void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr))
|
||||
{
|
||||
Src80 src1 = get_src1_i80(ctx, instr->src1);
|
||||
Src64 src2 = get_src2_i64(ctx, instr->chan);
|
||||
TCGv_i32 tag = e2k_get_temp_i32(ctx);
|
||||
TCGv_i64 dst = e2k_get_temp_i64(ctx);
|
||||
Src80 t0 = temp_new_src80();
|
||||
Src80 t1 = temp_new_src80();
|
||||
|
||||
gen_tag2_i64(tag, src1.tag, src2.tag);
|
||||
gen_fdtofx(&t0, src2.value);
|
||||
gen_alopf1_f80(&t1, src1, t0, op);
|
||||
gen_fxtofd(dst, t1);
|
||||
gen_al_result_i64(ctx, instr->chan, dst, tag);
|
||||
|
||||
temp_free_src80(&t1);
|
||||
temp_free_src80(&t0);
|
||||
}
|
||||
|
||||
static inline void gen_alopf1_xsx(DisasContext *ctx, Instr *instr,
|
||||
void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr))
|
||||
{
|
||||
Src80 src1 = get_src1_i80(ctx, instr->src1);
|
||||
Src32 src2 = get_src2_i32(ctx, instr->chan);
|
||||
TCGv_i32 tag = e2k_get_temp_i32(ctx);
|
||||
Src80 t0 = temp_new_src80();
|
||||
Src80 t1 = get_temp_src80(ctx);
|
||||
|
||||
gen_tag2_i64(tag, src1.tag, src2.tag);
|
||||
gen_fstofx(&t0, src2.value);
|
||||
gen_alopf1_f80(&t1, src1, t0, op);
|
||||
gen_al_result_i80(ctx, instr, t1.lo, t1.hi, tag);
|
||||
|
||||
temp_free_src80(&t0);
|
||||
}
|
||||
|
||||
static inline void gen_alopf1_xdx(DisasContext *ctx, Instr *instr,
|
||||
void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr))
|
||||
{
|
||||
Src80 src1 = get_src1_i80(ctx, instr->src1);
|
||||
Src64 src2 = get_src2_i64(ctx, instr->chan);
|
||||
TCGv_i32 tag = e2k_get_temp_i32(ctx);
|
||||
Src80 t0 = temp_new_src80();
|
||||
Src80 t1 = get_temp_src80(ctx);
|
||||
|
||||
gen_tag2_i64(tag, src1.tag, src2.tag);
|
||||
gen_fdtofx(&t0, src2.value);
|
||||
gen_alopf1_f80(&t1, src1, t0, op);
|
||||
gen_al_result_i80(ctx, instr, t1.lo, t1.hi, tag);
|
||||
|
||||
temp_free_src80(&t0);
|
||||
}
|
||||
|
||||
static inline void gen_alopf2_xs(DisasContext *ctx, Instr *instr,
|
||||
void (*op)(TCGv_i32 ret, Src80 src2))
|
||||
{
|
||||
Src80 src2 = get_src2_i80(ctx, instr->chan);
|
||||
TCGv_i32 tag = e2k_get_temp_i32(ctx);
|
||||
TCGv_i32 dst = e2k_get_temp_i32(ctx);
|
||||
|
||||
gen_tag1_i32(tag, src2.tag);
|
||||
(*op)(dst, src2);
|
||||
gen_al_result_i32(ctx, instr->chan, dst, tag);
|
||||
}
|
||||
|
||||
static inline void gen_alopf2_xd(DisasContext *ctx, Instr *instr,
|
||||
void (*op)(TCGv_i64 ret, Src80 src2))
|
||||
{
|
||||
Src80 src2 = get_src2_i80(ctx, instr->chan);
|
||||
TCGv_i32 tag = e2k_get_temp_i32(ctx);
|
||||
TCGv_i64 dst = e2k_get_temp_i64(ctx);
|
||||
|
||||
gen_tag1_i32(tag, src2.tag);
|
||||
(*op)(dst, src2);
|
||||
gen_al_result_i64(ctx, instr->chan, dst, tag);
|
||||
}
|
||||
|
||||
static inline void gen_alopf2_sx(DisasContext *ctx, Instr *instr,
|
||||
void (*op)(Src80 *ret, TCGv_i32 src2))
|
||||
{
|
||||
Src32 src2 = get_src2_i32(ctx, instr->chan);
|
||||
Src80 res = get_temp_src80(ctx);
|
||||
|
||||
gen_tag1_i64(res.tag, src2.tag);
|
||||
(*op)(&res, src2.value);
|
||||
gen_al_result_i80(ctx, instr, res.lo, res.hi, res.tag);
|
||||
}
|
||||
|
||||
static inline void gen_alopf2_dx(DisasContext *ctx, Instr *instr,
|
||||
void (*op)(Src80 *ret, TCGv_i64 src2))
|
||||
{
|
||||
Src64 src2 = get_src2_i64(ctx, instr->chan);
|
||||
Src80 res = get_temp_src80(ctx);
|
||||
|
||||
gen_tag1_i64(res.tag, src2.tag);
|
||||
(*op)(&res, src2.value);
|
||||
gen_al_result_i80(ctx, instr, res.lo, res.hi, res.tag);
|
||||
}
|
||||
|
||||
static void execute_ext_00(DisasContext *ctx, Instr *instr)
|
||||
{
|
||||
@ -2401,6 +2669,8 @@ static void execute_ext_00(DisasContext *ctx, Instr *instr)
|
||||
case 0xc0: func = gen_helper_fdtoid; break;
|
||||
case 0xc2: func = ctx->version >= 2 ? gen_helper_fdtoidtr : 0; break;
|
||||
case 0xc4: func = gen_helper_idtofd; break;
|
||||
case 0xc6: gen_alopf2_xd(ctx, instr, gen_fxtofd); return;
|
||||
case 0xc7: gen_alopf2_dx(ctx, instr, gen_fdtofx); return;
|
||||
}
|
||||
|
||||
if (func) {
|
||||
@ -2418,6 +2688,7 @@ static void execute_ext_00(DisasContext *ctx, Instr *instr)
|
||||
case 0xc2: func = ctx->version >= 2 ? gen_helper_fstoidtr : 0; break;
|
||||
case 0xc4: func = gen_helper_istofd; break;
|
||||
case 0xc6: func = gen_helper_fstofd; break;
|
||||
case 0xc7: gen_alopf2_sx(ctx, instr, gen_fstofx); return;
|
||||
}
|
||||
|
||||
if (func) {
|
||||
@ -2435,6 +2706,7 @@ static void execute_ext_00(DisasContext *ctx, Instr *instr)
|
||||
case 0xc2: func = gen_helper_fdtoistr; break;
|
||||
case 0xc4: func = gen_helper_idtofs; break;
|
||||
case 0xc6: func = gen_helper_fdtofs; break;
|
||||
case 0xc7: gen_alopf2_xs(ctx, instr, gen_fxtofs); return;
|
||||
}
|
||||
|
||||
if (func) {
|
||||
@ -2444,7 +2716,11 @@ static void execute_ext_00(DisasContext *ctx, Instr *instr)
|
||||
}
|
||||
break;
|
||||
case 0x40:
|
||||
if (chan == 5) {
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxaddss */
|
||||
gen_alopf1_xss(ctx, instr, gen_helper_fxaddxx);
|
||||
return;
|
||||
} else if (chan == 5) {
|
||||
// FIXME: temp hack
|
||||
if (instr->src2 == 0xc0) {
|
||||
e2k_tr_gen_exception_no_spill(ctx, 0);
|
||||
@ -2457,26 +2733,213 @@ static void execute_ext_00(DisasContext *ctx, Instr *instr)
|
||||
}
|
||||
break;
|
||||
case 0x41:
|
||||
if (chan == 5) {
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxadddd */
|
||||
gen_alopf1_xdd(ctx, instr, gen_helper_fxaddxx);
|
||||
return;
|
||||
} else if (chan == 5) {
|
||||
/* udivd */
|
||||
gen_alopf1_tag_i64(ctx, chan, gen_udivd);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x42:
|
||||
if (chan == 5) {
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxaddsx */
|
||||
gen_alopf1_xsx(ctx, instr, gen_helper_fxaddxx);
|
||||
return;
|
||||
} else if (chan == 5) {
|
||||
/* sdivs */
|
||||
gen_alopf1_tag_i32(ctx, chan, gen_sdivs);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x43:
|
||||
if (chan == 5) {
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxadddx */
|
||||
gen_alopf1_xdx(ctx, instr, gen_helper_fxaddxx);
|
||||
return;
|
||||
} else if (chan == 5) {
|
||||
/* sdivd */
|
||||
gen_alopf1_tag_i64(ctx, chan, gen_sdivd);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x44:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxaddxs */
|
||||
gen_alopf1_xxs(ctx, instr, gen_helper_fxaddxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x45:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxaddxd */
|
||||
gen_alopf1_xxd(ctx, instr, gen_helper_fxaddxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x47:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxaddxx */
|
||||
gen_alopf1_xxx(ctx, instr, gen_helper_fxaddxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x48:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxsubss */
|
||||
gen_alopf1_xss(ctx, instr, gen_helper_fxsubxx);
|
||||
return;
|
||||
} else if (chan == 5) {
|
||||
/* fxdivss */
|
||||
gen_alopf1_xss(ctx, instr, gen_helper_fxdivxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x49:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxsubdd */
|
||||
gen_alopf1_xdd(ctx, instr, gen_helper_fxsubxx);
|
||||
return;
|
||||
} else if (chan == 5) {
|
||||
/* fxdivdd */
|
||||
gen_alopf1_xdd(ctx, instr, gen_helper_fxdivxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x4a:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxsubsx */
|
||||
gen_alopf1_xsx(ctx, instr, gen_helper_fxsubxx);
|
||||
return;
|
||||
} else if (chan == 5) {
|
||||
/* fxdivsx */
|
||||
gen_alopf1_xsx(ctx, instr, gen_helper_fxdivxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x4b:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxsubdx */
|
||||
gen_alopf1_xdx(ctx, instr, gen_helper_fxsubxx);
|
||||
return;
|
||||
} else if (chan == 5) {
|
||||
/* fxdivdx */
|
||||
gen_alopf1_xdx(ctx, instr, gen_helper_fxdivxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x4c:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxsubxs */
|
||||
gen_alopf1_xxs(ctx, instr, gen_helper_fxsubxx);
|
||||
return;
|
||||
} else if (chan == 5) {
|
||||
/* fxdivxs */
|
||||
gen_alopf1_xxs(ctx, instr, gen_helper_fxdivxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x4d:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxsubxd */
|
||||
gen_alopf1_xxd(ctx, instr, gen_helper_fxsubxx);
|
||||
return;
|
||||
} else if (chan == 5) {
|
||||
/* fxdivxd */
|
||||
gen_alopf1_xxd(ctx, instr, gen_helper_fxdivxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x4f:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxsubxx */
|
||||
gen_alopf1_xxx(ctx, instr, gen_helper_fxsubxx);
|
||||
return;
|
||||
} else if (chan == 5) {
|
||||
/* fxdivxx */
|
||||
gen_alopf1_xxx(ctx, instr, gen_helper_fxdivxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x50:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxmulss */
|
||||
gen_alopf1_xss(ctx, instr, gen_helper_fxmulxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x51:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxmuldd */
|
||||
gen_alopf1_xdd(ctx, instr, gen_helper_fxmulxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x52:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxmulsx */
|
||||
gen_alopf1_xsx(ctx, instr, gen_helper_fxmulxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x53:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxmuldx */
|
||||
gen_alopf1_xdx(ctx, instr, gen_helper_fxmulxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x54:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxmulxs */
|
||||
gen_alopf1_xxs(ctx, instr, gen_helper_fxmulxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x55:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxmulxd */
|
||||
gen_alopf1_xxd(ctx, instr, gen_helper_fxmulxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x57:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxmulxx */
|
||||
gen_alopf1_xxx(ctx, instr, gen_helper_fxmulxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x58:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxrsubss */
|
||||
gen_alopf1_xss(ctx, instr, gen_helper_fxrsubxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x59:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxrsubdd */
|
||||
gen_alopf1_xdd(ctx, instr, gen_helper_fxrsubxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x5a:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxrsubsx */
|
||||
gen_alopf1_xsx(ctx, instr, gen_helper_fxrsubxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x5b:
|
||||
if (is_chan_0134(chan)) {
|
||||
/* fxrsubdx */
|
||||
gen_alopf1_xdx(ctx, instr, gen_helper_fxrsubxx);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x5c:
|
||||
if (is_chan_14(chan) || (ctx->version >= 2 && is_chan_03(chan))) {
|
||||
/* movfi */
|
||||
|
Loading…
Reference in New Issue
Block a user