Merge branch 'e2k-fpu' into e2k

This commit is contained in:
Denis Drakhnia 2020-12-16 22:33:50 +02:00
commit 2c45fb6f0b
11 changed files with 1511 additions and 172 deletions

View File

@ -138,7 +138,7 @@ static FloatParts parts_default_nan(float_status *status)
/* !snan_bit_is_one, set all bits */
frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
|| defined(TARGET_MICROBLAZE)
|| defined(TARGET_MICROBLAZE) || defined(TARGET_E2K)
/* !snan_bit_is_one, set sign and msb */
frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
sign = 1;

View File

@ -42,8 +42,6 @@ static void e2k_cpu_reset(DeviceState *dev)
memset(env, 0, offsetof(CPUE2KState, end_reset_fields));
env->rptr = &env->regs[0];
env->tptr = &env->tags[0];
env->cr1.wpsz = 4;
env->cr1.wbs = 4;
env->wd.base = 0;
@ -53,6 +51,7 @@ static void e2k_cpu_reset(DeviceState *dev)
env->bn.size = 8;
env->bn.cur = 0;
env->aau.incrs[0] = 1; /* always one */
env->fpcr._one = 1;
// FIXME: testing
env->idr = 0x3a207; // mimic 8c
@ -74,8 +73,12 @@ void e2k_cpu_do_interrupt(CPUState *cs)
cs->exception_index = -1;
}
static void cpu_e2k_disas_set_info(CPUState *cpu, disassemble_info *info)
static void cpu_e2k_disas_set_info(CPUState *cs, disassemble_info *info)
{
E2KCPU *cpu = E2K_CPU(cs);
CPUE2KState *env = &cpu->env;
info->mach = env->version * 3;
info->print_insn = print_insn_e2k;
}

View File

@ -4,6 +4,7 @@
#include "qemu/bswap.h"
#include "cpu-qom.h"
#include "exec/cpu-defs.h"
#include "fpu/softfloat.h"
void e2k_tcg_initialize(void);
@ -480,6 +481,54 @@ typedef union {
uint64_t raw;
} E2KCtpr;
/* E2K FPU regs are compatible with x87 regs */
#define FPSR_IE (1U << 0) /* invalid operation */
#define FPSR_DE (1U << 1) /* denormalized operand */
#define FPSR_ZE (1U << 2) /* zero divide */
#define FPSR_OE (1U << 3) /* overflow */
#define FPSR_UE (1U << 4) /* underflow */
#define FPSR_PE (1U << 5) /* precision */
typedef union {
struct {
uint32_t ef : 6; /* exception flags */
uint32_t sf : 1; /* stack fault, unused */
uint32_t es : 1; /* error summary status */
uint32_t _c0 : 1; /* condition code 0, unused */
uint32_t c1 : 1; /* condition code 1 */
uint32_t _c2 : 1; /* condition code 2, unused */
uint32_t top: 3; /* stack top, unused */
uint32_t _c3 : 1; /* condition code 3, unused */
uint32_t b : 1; /* fpu busy */
};
uint32_t raw;
} E2KFpsrState;
#define FPCR_EM (FPSR_IE|FPSR_DE|FPSR_ZE|FPSR_OE|FPSR_UE|FPSR_PE)
#define FPCR_PC_SP 0 /* single precision (32 bits) */
#define FPCR_PC_RESERVED 1 /* reserved */
#define FPCR_PC_DP 2 /* double precision (64 bits) */
#define FPCR_PC_XP 3 /* extended precision (80 bits) */
#define FPCR_RC_NEAR 0 /* round to nearest */
#define FPCR_RC_DOWN 1 /* round down */
#define FPCR_RC_UP 2 /* round up */
#define FPCR_RC_CHOP 3 /* round toward zero (truncate) */
typedef union {
struct {
uint32_t em : 6; /* masks flags */
uint32_t _one : 1; /* reserved, always 1 (?) */
uint32_t _zero0 : 1; /* reserved, always 0 */
uint32_t pc : 2; /* precision control */
uint32_t rc : 2; /* rounding control */
uint32_t ic : 1; /* infinity control */
uint32_t _zero1 : 3; /* reserved */
};
uint32_t raw;
} E2KFpcrState;
typedef struct {
union {
uint64_t lo;
@ -501,16 +550,31 @@ typedef struct {
};
} E2KUserStackDesc;
typedef union {
uint32_t u32;
uint64_t u64;
floatx80 f80;
uint8_t u8v[16];
uint16_t u16v[8];
uint32_t u32v[4];
uint64_t u64v[2];
int8_t i8v[16];
int16_t i16v[8];
int32_t i32v[4];
int64_t i64v[2];
} E2KReg;
typedef struct {
/* register file */
uint64_t regs[E2K_REG_COUNT]; /* registers */
uint16_t xregs[E2K_REG_COUNT]; /* x part of registers */
uint8_t tags[E2K_REG_COUNT]; /* registers tags */
uint64_t *rptr; /* pointer to regs */
uint8_t *tptr; /* pointer to tags */
uint64_t regs[E2K_REG_COUNT]; /* low parts of registers */
uint64_t xregs[E2K_REG_COUNT]; /* high parts of registers */
uint64_t pregs; /* predicate file */
target_ulong ip; /* instruction address */
/* temporaries for FX/SIMD ops */
E2KReg t0, t1, t2, t3;
/* procedure chain info */
uint64_t cr0_lo;
uint64_t cr0_hi;
@ -543,9 +607,11 @@ typedef struct {
uint64_t idr;
uint32_t pfpfr; // Packed Floating Point Flag Register (PFPFR)
uint32_t fpcr; // Floating point control register (FPCR)
uint32_t fpsr; // Floating point state register (FPSR)
E2KFpsrState fpsr; // Floating point state register (FPSR)
E2KFpcrState fpcr; // Floating point control register (FPCR)
float_status fp_status;
E2KAauState aau;
int interrupt_index;
@ -596,6 +662,7 @@ void e2k_break_save_state(CPUE2KState *env);
bool e2k_cpu_tlb_fill(CPUState *cpu, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
void e2k_update_fp_status(CPUE2KState *env);
#define cpu_signal_handler e2k_cpu_signal_handler
#define cpu_list e2k_cpu_list

View File

@ -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)
@ -27,3 +34,52 @@ DEF_HELPER_2(pmovmskb, i64, i64, i64)
DEF_HELPER_1(aau_load_program, void, env)
DEF_HELPER_3(mova_ptr, tl, env, int, int)
DEF_HELPER_3(aau_am, void, env, int, int)
#define DEF_HELPER_3_32_64(name) \
DEF_HELPER_3(name##s, i32, env, i32, i32) \
DEF_HELPER_3(name##d, i64, env, i64, i64)
DEF_HELPER_3_32_64(fadd)
DEF_HELPER_3_32_64(fsub)
DEF_HELPER_3_32_64(fmin)
DEF_HELPER_3_32_64(fmax)
DEF_HELPER_3_32_64(fmul)
DEF_HELPER_3_32_64(fdiv)
DEF_HELPER_3_32_64(fcmpeq)
DEF_HELPER_3_32_64(fcmpneq)
DEF_HELPER_3_32_64(fcmple)
DEF_HELPER_3_32_64(fcmpnle)
DEF_HELPER_3_32_64(fcmplt)
DEF_HELPER_3_32_64(fcmpnlt)
DEF_HELPER_3_32_64(fcmpuod)
DEF_HELPER_3_32_64(fcmpod)
#undef DEF_HELPER_3_32_64
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)
DEF_HELPER_2(istofd, i64, env, i32)
DEF_HELPER_2(fstoidtr, i64, env, i32)
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)

183
target/e2k/helper_fpu.c Normal file
View File

@ -0,0 +1,183 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "cpu.h"
#include "exec/exec-all.h"
#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;
if (env->fpsr.ef & (~env->fpcr.em & FPCR_EM)) {
env->fpsr.es = 1;
env->fpsr.b = 1;
}
}
static inline uint8_t save_exception_flags(CPUE2KState *env)
{
uint8_t old_flags = get_float_exception_flags(&env->fp_status);
set_float_exception_flags(0, &env->fp_status);
return old_flags;
}
static inline void merge_exception_flags(CPUE2KState *env, uint8_t old_flags)
{
uint8_t new_flags = get_float_exception_flags(&env->fp_status);
float_raise(old_flags, &env->fp_status);
fpu_set_exception(env,
((new_flags & float_flag_invalid ? FPSR_IE : 0) |
(new_flags & float_flag_divbyzero ? FPSR_ZE : 0) |
(new_flags & float_flag_overflow ? FPSR_OE : 0) |
(new_flags & float_flag_underflow ? FPSR_UE : 0) |
(new_flags & float_flag_inexact ? FPSR_PE : 0) |
(new_flags & float_flag_input_denormal ? FPSR_DE : 0)));
}
void e2k_update_fp_status(CPUE2KState *env)
{
int x;
switch(env->fpcr.rc) {
case FPCR_RC_UP:
x = float_round_up;
break;
case FPCR_RC_DOWN:
x = float_round_down;
break;
case FPCR_RC_CHOP:
x = float_round_to_zero;
break;
case FPCR_RC_NEAR:
x = float_round_nearest_even;
break;
default:
abort();
break;
}
set_float_rounding_mode(x, &env->fp_status);
switch(env->fpcr.pc) {
case FPCR_PC_XP: x = 80; break;
case FPCR_PC_DP: x = 64; break;
case FPCR_PC_SP: x = 32; break;
case FPCR_PC_RESERVED:
default:
abort();
break;
}
set_floatx80_rounding_precision(x, &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) \
{ \
uint8_t old_flags = save_exception_flags(env); \
float##size z = float##size##_##function (make_float##size (x), make_float##size (y), &env->fp_status); \
merge_exception_flags(env, old_flags); \
return float##size##_val(z); \
}
#define GENERATE_CMP_FLOAT2_OP(name, function, expr, size) \
uint##size##_t HELPER(name)(CPUE2KState *env, uint##size##_t x, uint##size##_t y) \
{ \
uint8_t old_flags = save_exception_flags(env); \
uint##size##_t z = expr float##size##_##function (make_float##size (x), make_float##size (y), &env->fp_status); \
merge_exception_flags(env, old_flags); \
return z; \
}
#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) \
size_to HELPER(name)(CPUE2KState *env, size_from x) \
{\
uint8_t old_flags = save_exception_flags(env); \
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(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(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)
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(fcmpeq, eq, )
GENERATE_CMP_FLOAT2_OPS_32_64(fcmpneq, eq, !)
GENERATE_CMP_FLOAT2_OPS_32_64(fcmple, le, )
GENERATE_CMP_FLOAT2_OPS_32_64(fcmpnle, le, !)
GENERATE_CMP_FLOAT2_OPS_32_64(fcmplt, lt, )
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, 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, 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, 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, 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);
}

View File

@ -52,6 +52,8 @@ uint64_t helper_state_reg_read_i64(CPUE2KState *env, int idx)
case 0x55: return env->cr1.hi; /* %cr1.hi */
case 0x57: return env->cr1.lo; /* %cr1.lo */
case 0x81: return env->ip; /* %ip */
case 0x85: return env->fpcr.raw; /* %fpcr */
case 0x86: return env->fpsr.raw; /* %fpsr */
case 0x8a: return env->idr; /* %idr */
case 0x90: return cpu_get_host_ticks(); /* %clkr */
default: {
@ -74,25 +76,45 @@ uint32_t helper_state_reg_read_i32(CPUE2KState *env, int idx)
void helper_state_reg_write_i64(CPUE2KState *env, int idx, uint64_t val)
{
uint64_t *p = state_reg_ptr(env, idx);
switch(idx) {
case 0x85: /* %fpcr */
env->fpcr.raw = val;
e2k_update_fp_status(env);
break;
case 0x86: env->fpsr.raw = val; break; /* %fpsr */
default: {
uint64_t *p = state_reg_ptr(env, idx);
if (p != NULL) {
*p = val;
} else {
qemu_log_mask(LOG_UNIMP, "unknown state register 0x%x\n", idx);
abort();
if (p != NULL) {
*p = val;
} else {
qemu_log_mask(LOG_UNIMP, "unknown state register 0x%x\n", idx);
abort();
}
break;
}
}
}
void helper_state_reg_write_i32(CPUE2KState *env, int idx, uint32_t val)
{
uint32_t *p = (uint32_t*) state_reg_ptr(env, idx);
if (p != NULL) {
*p = val;
} else {
qemu_log_mask(LOG_UNIMP, "unknown state register 0x%x\n", idx);
abort();
switch (idx) {
case 0x85: /* %fpcr */
env->fpcr.raw = val;
e2k_update_fp_status(env);
break;
case 0x86: env->fpsr.raw = val; break; /* %fpsr */
default: {
uint32_t *p = (uint32_t*) state_reg_ptr(env, idx);
if (p != NULL) {
*p = val;
} else {
qemu_log_mask(LOG_UNIMP, "unknown state register 0x%x\n", idx);
abort();
}
break;
}
}
}

View File

@ -4,6 +4,7 @@ e2k_ss.add(files(
'gdbstub.c',
'helper.c',
'helper_aau.c',
'helper_fpu.c',
'helper_int.c',
'helper_sm.c',
'helper_vec.c',

View File

@ -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,
@ -527,11 +527,6 @@ void e2k_tcg_initialize(void) {
*rtl[i].ptr = tcg_global_mem_new(cpu_env, rtl[i].off, rtl[i].name);
}
e2k_cs.rptr = tcg_global_mem_new_ptr(cpu_env,
offsetof(CPUE2KState, rptr), "regs_ptr");
e2k_cs.tptr = tcg_global_mem_new_ptr(cpu_env,
offsetof(CPUE2KState, tptr), "tags_ptr");
for (i = 0; i < 3; i++) {
snprintf(buf, ARRAY_SIZE(buf), "%%ctpr%d", i + 1);
e2k_cs.ctprs[i] = tcg_global_mem_new_i64(cpu_env,

View File

@ -41,8 +41,6 @@ typedef struct CPUE2KStateTCG {
TCGv_i32 is_bp; /* breakpoint flag */
TCGv_i32 wdbl;
TCGv_i64 lsr;
TCGv_ptr rptr; /* pointer to wregs */
TCGv_ptr tptr; /* pointer to wtags */
TCGv_i32 wd_base; /* holds wbs * 2 */
TCGv_i32 wd_size; /* holds wsz * 2 */
TCGv_i32 boff; /* holds rbs * 2 */
@ -89,14 +87,30 @@ typedef struct UnpackedBundle {
} UnpackedBundle;
typedef enum {
AL_RESULT_NONE,
AL_RESULT_REG32,
AL_RESULT_REG64,
AL_RESULT_PREG,
AL_RESULT_CTPR32,
AL_RESULT_CTPR64,
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 */
@ -107,20 +121,23 @@ typedef struct {
struct {
uint8_t dst; /* %rN, 1st phase */
TCGv_i32 index;
TCGv_i32 tag;
union {
TCGv_i32 v32;
TCGv_i64 v64;
};
TCGv_i32 tag;
union {
TCGv_i32 x32; /* FX ops */
TCGv_i64 x64; /* SIMD ops v5+ */
};
} reg;
struct {
int index;
TCGv_i64 value;
} preg, ctpr64;
struct {
int index;
TCGv_i32 value;
} ctpr32;
union {
TCGv_i32 v32;
TCGv_i64 v64;
};
} preg, ctpr;
};
} AlResult;
@ -477,6 +494,13 @@ void e2k_gen_reg_read_i32(TCGv_i32 ret, TCGv_i32 idx);
void e2k_gen_reg_write_i64(TCGv_i64 value, TCGv_i32 idx);
void e2k_gen_reg_write_i32(TCGv_i32 value, TCGv_i32 idx);
void e2k_gen_xreg_read_i64(TCGv_i64 ret, TCGv_i32 idx);
void e2k_gen_xreg_read_i32(TCGv_i32 ret, TCGv_i32 idx);
void e2k_gen_xreg_read16u_i32(TCGv_i32 ret, TCGv_i32 idx);
void e2k_gen_xreg_write_i64(TCGv_i64 value, TCGv_i32 idx);
void e2k_gen_xreg_write_i32(TCGv_i32 value, TCGv_i32 idx);
void e2k_gen_xreg_write16u_i32(TCGv_i32 value, TCGv_i32 idx);
void e2k_gen_preg_i64(TCGv_i64 ret, int reg);
void e2k_gen_preg_i32(TCGv_i32 ret, int reg);
TCGv_i64 e2k_get_preg(DisasContext *dc, int reg);

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,20 @@
#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);
@ -110,9 +124,13 @@ void e2k_gen_store_preg(int idx, TCGv_i64 val)
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_add_ptr(ret, e2k_cs.tptr, t0);
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);
}
@ -235,59 +253,50 @@ void e2k_gen_reg_index_from_gregi(TCGv_i32 ret, int idx)
tcg_gen_movi_i32(ret, E2K_NR_COUNT + idx);
}
static inline void gen_reg_ptr_from_index(TCGv_ptr ret, TCGv_i32 idx)
{
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_ptr t1 = tcg_temp_new_ptr();
tcg_gen_muli_i32(t0, idx, 8);
tcg_gen_ext_i32_ptr(t1, t0);
tcg_gen_add_ptr(ret, e2k_cs.rptr, t1);
tcg_temp_free_ptr(t1);
tcg_temp_free_i32(t0);
}
void e2k_gen_reg_read_i64(TCGv_i64 ret, TCGv_i32 idx)
static inline void gen_reg_ptr(TCGv_ptr ret, TCGv_i32 idx)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
gen_reg_ptr_from_index(t0, idx);
tcg_gen_ld_i64(ret, t0, 0);
tcg_gen_addi_ptr(t0, cpu_env, offsetof(CPUE2KState, regs));
gen_ptr_from_index(ret, t0, idx, 8);
tcg_temp_free_ptr(t0);
}
void e2k_gen_reg_read_i32(TCGv_i32 ret, TCGv_i32 idx)
static inline void gen_xreg_ptr(TCGv_ptr ret, TCGv_i32 idx)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
gen_reg_ptr_from_index(t0, idx);
tcg_gen_ld_i32(ret, t0, 0);
tcg_gen_addi_ptr(t0, cpu_env, offsetof(CPUE2KState, xregs));
gen_ptr_from_index(ret, t0, idx, 8);
tcg_temp_free_ptr(t0);
}
void e2k_gen_reg_write_i64(TCGv_i64 value, TCGv_i32 idx)
{
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_ptr t1 = tcg_temp_new_ptr();
#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); \
}
tcg_gen_mov_i64(t0, value);
gen_reg_ptr_from_index(t1, idx);
tcg_gen_st_i64(t0, t1, 0);
#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); \
}
tcg_temp_free_ptr(t1);
tcg_temp_free_i64(t0);
}
GEN_REG_READ(e2k_gen_reg_read_i64, TCGv_i64, gen_reg_ptr, tcg_gen_ld_i64)
GEN_REG_READ(e2k_gen_reg_read_i32, TCGv_i32, gen_reg_ptr, tcg_gen_ld_i32)
GEN_REG_WRITE(e2k_gen_reg_write_i64, TCGv_i64, gen_reg_ptr, tcg_gen_st_i64)
GEN_REG_WRITE(e2k_gen_reg_write_i32, TCGv_i32, gen_reg_ptr, tcg_gen_st_i32)
void e2k_gen_reg_write_i32(TCGv_i32 value, TCGv_i32 idx)
{
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_ptr t1 = tcg_temp_new_ptr();
tcg_gen_mov_i32(t0, value);
gen_reg_ptr_from_index(t1, idx);
tcg_gen_st_i32(t0, t1, 0);
tcg_temp_free_ptr(t1);
tcg_temp_free_i32(t0);
}
GEN_REG_READ(e2k_gen_xreg_read_i64, TCGv_i64, gen_xreg_ptr, tcg_gen_ld_i64)
GEN_REG_READ(e2k_gen_xreg_read_i32, TCGv_i32, gen_xreg_ptr, tcg_gen_ld_i32)
GEN_REG_READ(e2k_gen_xreg_read16u_i32, TCGv_i32, gen_xreg_ptr, tcg_gen_ld16u_i32)
GEN_REG_WRITE(e2k_gen_xreg_write_i64, TCGv_i64, gen_xreg_ptr, tcg_gen_st_i64)
GEN_REG_WRITE(e2k_gen_xreg_write_i32, TCGv_i32, gen_xreg_ptr, tcg_gen_st_i32)
GEN_REG_WRITE(e2k_gen_xreg_write16u_i32, TCGv_i32, gen_xreg_ptr, tcg_gen_st16_i32)