Merge branch 'e2k-fpu' into e2k
This commit is contained in:
commit
2c45fb6f0b
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue