Convert m68k target to TCG.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4565 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
pbrook 2008-05-24 22:29:16 +00:00
parent 3979144c49
commit e1f3808e03
11 changed files with 1574 additions and 2352 deletions

2
configure vendored
View File

@ -1237,10 +1237,8 @@ case "$target_cpu" in
;; ;;
m68k) m68k)
echo "TARGET_ARCH=m68k" >> $config_mak echo "TARGET_ARCH=m68k" >> $config_mak
echo "CONFIG_DYNGEN_OP=yes" >> $config_mak
echo "#define TARGET_ARCH \"m68k\"" >> $config_h echo "#define TARGET_ARCH \"m68k\"" >> $config_h
echo "#define TARGET_M68K 1" >> $config_h echo "#define TARGET_M68K 1" >> $config_h
echo "#define CONFIG_DYNGEN_OP 1" >> $config_h
bflt="yes" bflt="yes"
;; ;;
mips|mipsel) mips|mipsel)

View File

@ -108,7 +108,7 @@ typedef struct CPUM68KState {
int exception_index; int exception_index;
int interrupt_request; int interrupt_request;
int user_mode_only; int user_mode_only;
int halted; uint32_t halted;
int pending_vector; int pending_vector;
int pending_level; int pending_level;
@ -120,6 +120,7 @@ typedef struct CPUM68KState {
uint32_t features; uint32_t features;
} CPUM68KState; } CPUM68KState;
void m68k_tcg_init(void);
CPUM68KState *cpu_m68k_init(const char *cpu_model); CPUM68KState *cpu_m68k_init(const char *cpu_model);
int cpu_m68k_exec(CPUM68KState *s); int cpu_m68k_exec(CPUM68KState *s);
void cpu_m68k_close(CPUM68KState *s); void cpu_m68k_close(CPUM68KState *s);
@ -141,9 +142,7 @@ enum {
CC_OP_CMPW, /* CC_DEST = result, CC_SRC = source */ CC_OP_CMPW, /* CC_DEST = result, CC_SRC = source */
CC_OP_ADDX, /* CC_DEST = result, CC_SRC = source */ CC_OP_ADDX, /* CC_DEST = result, CC_SRC = source */
CC_OP_SUBX, /* CC_DEST = result, CC_SRC = source */ CC_OP_SUBX, /* CC_DEST = result, CC_SRC = source */
CC_OP_SHL, /* CC_DEST = source, CC_SRC = shift */ CC_OP_SHIFT, /* CC_DEST = result, CC_SRC = carry */
CC_OP_SHR, /* CC_DEST = source, CC_SRC = shift */
CC_OP_SAR, /* CC_DEST = source, CC_SRC = shift */
}; };
#define CCF_C 0x01 #define CCF_C 0x01

View File

@ -45,8 +45,6 @@ int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
#endif #endif
void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op); void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op);
float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1);
void helper_movec(CPUM68KState *env, int reg, uint32_t val);
void cpu_loop_exit(void); void cpu_loop_exit(void);

View File

@ -27,6 +27,10 @@
#include "exec-all.h" #include "exec-all.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "helpers.h"
#define SIGNBIT (1u << 31)
enum m68k_cpuid { enum m68k_cpuid {
M68K_CPUID_M5206, M68K_CPUID_M5206,
M68K_CPUID_M5208, M68K_CPUID_M5208,
@ -121,11 +125,16 @@ void cpu_reset(CPUM68KState *env)
CPUM68KState *cpu_m68k_init(const char *cpu_model) CPUM68KState *cpu_m68k_init(const char *cpu_model)
{ {
CPUM68KState *env; CPUM68KState *env;
static int inited;
env = malloc(sizeof(CPUM68KState)); env = malloc(sizeof(CPUM68KState));
if (!env) if (!env)
return NULL; return NULL;
cpu_exec_init(env); cpu_exec_init(env);
if (!inited) {
inited = 1;
m68k_tcg_init();
}
env->cpu_model_str = cpu_model; env->cpu_model_str = cpu_model;
@ -211,34 +220,9 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
if (HIGHBIT & (tmp ^ dest) & (tmp ^ src)) if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
flags |= CCF_V; flags |= CCF_V;
break; break;
case CC_OP_SHL: case CC_OP_SHIFT:
if (src >= 32) { SET_NZ(dest);
SET_NZ(0); if (src)
} else {
tmp = dest << src;
SET_NZ(tmp);
}
if (src && src <= 32 && (dest & (1 << (32 - src))))
flags |= CCF_C;
break;
case CC_OP_SHR:
if (src >= 32) {
SET_NZ(0);
} else {
tmp = dest >> src;
SET_NZ(tmp);
}
if (src && src <= 32 && ((dest >> (src - 1)) & 1))
flags |= CCF_C;
break;
case CC_OP_SAR:
if (src >= 32) {
SET_NZ(-1);
} else {
tmp = (int32_t)dest >> src;
SET_NZ(tmp);
}
if (src && src <= 32 && (((int32_t)dest >> (src - 1)) & 1))
flags |= CCF_C; flags |= CCF_C;
break; break;
default: default:
@ -248,25 +232,7 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
env->cc_dest = flags; env->cc_dest = flags;
} }
float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1) void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
{
/* ??? This may incorrectly raise exceptions. */
/* ??? Should flush denormals to zero. */
float64 res;
res = float64_sub(src0, src1, &env->fp_status);
if (float64_is_nan(res)) {
/* +/-inf compares equal against itself, but sub returns nan. */
if (!float64_is_nan(src0)
&& !float64_is_nan(src1)) {
res = float64_zero;
if (float64_lt_quiet(src0, res, &env->fp_status))
res = float64_chs(res);
}
}
return res;
}
void helper_movec(CPUM68KState *env, int reg, uint32_t val)
{ {
switch (reg) { switch (reg) {
case 0x02: /* CACR */ case 0x02: /* CACR */
@ -286,7 +252,7 @@ void helper_movec(CPUM68KState *env, int reg, uint32_t val)
} }
} }
void m68k_set_macsr(CPUM68KState *env, uint32_t val) void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
{ {
uint32_t acc; uint32_t acc;
int8_t exthigh; int8_t exthigh;
@ -376,3 +342,541 @@ void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
} }
#endif #endif
uint32_t HELPER(bitrev)(uint32_t x)
{
x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
return bswap32(x);
}
uint32_t HELPER(ff1)(uint32_t x)
{
int n;
for (n = 32; x; n--)
x >>= 1;
return n;
}
uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
{
/* The result has the opposite sign to the original value. */
if (ccr & CCF_V)
val = (((int32_t)val) >> 31) ^ SIGNBIT;
return val;
}
uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
{
uint32_t res;
uint32_t old_flags;
old_flags = env->cc_dest;
if (env->cc_x) {
env->cc_x = (op1 <= op2);
env->cc_op = CC_OP_SUBX;
res = op1 - (op2 + 1);
} else {
env->cc_x = (op1 < op2);
env->cc_op = CC_OP_SUB;
res = op1 - op2;
}
env->cc_dest = res;
env->cc_src = op2;
cpu_m68k_flush_flags(env, env->cc_op);
/* !Z is sticky. */
env->cc_dest &= (old_flags | ~CCF_Z);
return res;
}
uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
{
uint32_t res;
uint32_t old_flags;
old_flags = env->cc_dest;
if (env->cc_x) {
res = op1 + op2 + 1;
env->cc_x = (res <= op2);
env->cc_op = CC_OP_ADDX;
} else {
res = op1 + op2;
env->cc_x = (res < op2);
env->cc_op = CC_OP_ADD;
}
env->cc_dest = res;
env->cc_src = op2;
cpu_m68k_flush_flags(env, env->cc_op);
/* !Z is sticky. */
env->cc_dest &= (old_flags | ~CCF_Z);
return res;
}
uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
{
return a < b;
}
uint32_t HELPER(btest)(uint32_t x)
{
return x != 0;
}
void HELPER(set_sr)(CPUState *env, uint32_t val)
{
env->sr = val & 0xffff;
m68k_switch_sp(env);
}
uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
{
uint32_t result;
uint32_t cf;
shift &= 63;
if (shift == 0) {
result = val;
cf = env->cc_src & CCF_C;
} else if (shift < 32) {
result = val << shift;
cf = (val >> (32 - shift)) & 1;
} else if (shift == 32) {
result = 0;
cf = val & 1;
} else /* shift > 32 */ {
result = 0;
cf = 0;
}
env->cc_src = cf;
env->cc_x = (cf != 0);
env->cc_dest = result;
return result;
}
uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
{
uint32_t result;
uint32_t cf;
shift &= 63;
if (shift == 0) {
result = val;
cf = env->cc_src & CCF_C;
} else if (shift < 32) {
result = val >> shift;
cf = (val >> (shift - 1)) & 1;
} else if (shift == 32) {
result = 0;
cf = val >> 31;
} else /* shift > 32 */ {
result = 0;
cf = 0;
}
env->cc_src = cf;
env->cc_x = (cf != 0);
env->cc_dest = result;
return result;
}
uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
{
uint32_t result;
uint32_t cf;
shift &= 63;
if (shift == 0) {
result = val;
cf = (env->cc_src & CCF_C) != 0;
} else if (shift < 32) {
result = (int32_t)val >> shift;
cf = (val >> (shift - 1)) & 1;
} else /* shift >= 32 */ {
result = (int32_t)val >> 31;
cf = val >> 31;
}
env->cc_src = cf;
env->cc_x = cf;
env->cc_dest = result;
return result;
}
/* FPU helpers. */
uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
{
return float64_to_int32(val, &env->fp_status);
}
float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
{
return float64_to_float32(val, &env->fp_status);
}
float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
{
return int32_to_float64(val, &env->fp_status);
}
float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
{
return float32_to_float64(val, &env->fp_status);
}
float64 HELPER(iround_f64)(CPUState *env, float64 val)
{
return float64_round_to_int(val, &env->fp_status);
}
float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
{
return float64_trunc_to_int(val, &env->fp_status);
}
float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
{
return float64_sqrt(val, &env->fp_status);
}
float64 HELPER(abs_f64)(float64 val)
{
return float64_abs(val);
}
float64 HELPER(chs_f64)(float64 val)
{
return float64_chs(val);
}
float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
{
return float64_add(a, b, &env->fp_status);
}
float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
{
return float64_sub(a, b, &env->fp_status);
}
float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
{
return float64_mul(a, b, &env->fp_status);
}
float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
{
return float64_div(a, b, &env->fp_status);
}
float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
{
/* ??? This may incorrectly raise exceptions. */
/* ??? Should flush denormals to zero. */
float64 res;
res = float64_sub(a, b, &env->fp_status);
if (float64_is_nan(res)) {
/* +/-inf compares equal against itself, but sub returns nan. */
if (!float64_is_nan(a)
&& !float64_is_nan(b)) {
res = float64_zero;
if (float64_lt_quiet(a, res, &env->fp_status))
res = float64_chs(res);
}
}
return res;
}
uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
{
return float64_compare_quiet(val, float64_zero, &env->fp_status);
}
/* MAC unit. */
/* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
take values, others take register numbers and manipulate the contents
in-place. */
void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
{
uint32_t mask;
env->macc[dest] = env->macc[src];
mask = MACSR_PAV0 << dest;
if (env->macsr & (MACSR_PAV0 << src))
env->macsr |= mask;
else
env->macsr &= ~mask;
}
uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
{
int64_t product;
int64_t res;
product = (uint64_t)op1 * op2;
res = (product << 24) >> 24;
if (res != product) {
env->macsr |= MACSR_V;
if (env->macsr & MACSR_OMC) {
/* Make sure the accumulate operation overflows. */
if (product < 0)
res = ~(1ll << 50);
else
res = 1ll << 50;
}
}
return res;
}
uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
{
uint64_t product;
product = (uint64_t)op1 * op2;
if (product & (0xffffffull << 40)) {
env->macsr |= MACSR_V;
if (env->macsr & MACSR_OMC) {
/* Make sure the accumulate operation overflows. */
product = 1ll << 50;
} else {
product &= ((1ull << 40) - 1);
}
}
return product;
}
uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
{
uint64_t product;
uint32_t remainder;
product = (uint64_t)op1 * op2;
if (env->macsr & MACSR_RT) {
remainder = product & 0xffffff;
product >>= 24;
if (remainder > 0x800000)
product++;
else if (remainder == 0x800000)
product += (product & 1);
} else {
product >>= 24;
}
return product;
}
void HELPER(macsats)(CPUState *env, uint32_t acc)
{
int64_t tmp;
int64_t result;
tmp = env->macc[acc];
result = ((tmp << 16) >> 16);
if (result != tmp) {
env->macsr |= MACSR_V;
}
if (env->macsr & MACSR_V) {
env->macsr |= MACSR_PAV0 << acc;
if (env->macsr & MACSR_OMC) {
/* The result is saturated to 32 bits, despite overflow occuring
at 48 bits. Seems weird, but that's what the hardware docs
say. */
result = (result >> 63) ^ 0x7fffffff;
}
}
env->macc[acc] = result;
}
void HELPER(macsatu)(CPUState *env, uint32_t acc)
{
uint64_t val;
val = env->macc[acc];
if (val & (0xffffull << 48)) {
env->macsr |= MACSR_V;
}
if (env->macsr & MACSR_V) {
env->macsr |= MACSR_PAV0 << acc;
if (env->macsr & MACSR_OMC) {
if (val > (1ull << 53))
val = 0;
else
val = (1ull << 48) - 1;
} else {
val &= ((1ull << 48) - 1);
}
}
env->macc[acc] = val;
}
void HELPER(macsatf)(CPUState *env, uint32_t acc)
{
int64_t sum;
int64_t result;
sum = env->macc[acc];
result = (sum << 16) >> 16;
if (result != sum) {
env->macsr |= MACSR_V;
}
if (env->macsr & MACSR_V) {
env->macsr |= MACSR_PAV0 << acc;
if (env->macsr & MACSR_OMC) {
result = (result >> 63) ^ 0x7fffffffffffll;
}
}
env->macc[acc] = result;
}
void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
{
uint64_t val;
val = env->macc[acc];
if (val == 0)
env->macsr |= MACSR_Z;
else if (val & (1ull << 47));
env->macsr |= MACSR_N;
if (env->macsr & (MACSR_PAV0 << acc)) {
env->macsr |= MACSR_V;
}
if (env->macsr & MACSR_FI) {
val = ((int64_t)val) >> 40;
if (val != 0 && val != -1)
env->macsr |= MACSR_EV;
} else if (env->macsr & MACSR_SU) {
val = ((int64_t)val) >> 32;
if (val != 0 && val != -1)
env->macsr |= MACSR_EV;
} else {
if ((val >> 32) != 0)
env->macsr |= MACSR_EV;
}
}
void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
{
cpu_m68k_flush_flags(env, cc_op);
}
uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
{
int rem;
uint32_t result;
if (env->macsr & MACSR_SU) {
/* 16-bit rounding. */
rem = val & 0xffffff;
val = (val >> 24) & 0xffffu;
if (rem > 0x800000)
val++;
else if (rem == 0x800000)
val += (val & 1);
} else if (env->macsr & MACSR_RT) {
/* 32-bit rounding. */
rem = val & 0xff;
val >>= 8;
if (rem > 0x80)
val++;
else if (rem == 0x80)
val += (val & 1);
} else {
/* No rounding. */
val >>= 8;
}
if (env->macsr & MACSR_OMC) {
/* Saturate. */
if (env->macsr & MACSR_SU) {
if (val != (uint16_t) val) {
result = ((val >> 63) ^ 0x7fff) & 0xffff;
} else {
result = val & 0xffff;
}
} else {
if (val != (uint32_t)val) {
result = ((uint32_t)(val >> 63) & 0x7fffffff);
} else {
result = (uint32_t)val;
}
}
} else {
/* No saturation. */
if (env->macsr & MACSR_SU) {
result = val & 0xffff;
} else {
result = (uint32_t)val;
}
}
return result;
}
uint32_t HELPER(get_macs)(uint64_t val)
{
if (val == (int32_t)val) {
return (int32_t)val;
} else {
return (val >> 61) ^ ~SIGNBIT;
}
}
uint32_t HELPER(get_macu)(uint64_t val)
{
if ((val >> 32) == 0) {
return (uint32_t)val;
} else {
return 0xffffffffu;
}
}
uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
{
uint32_t val;
val = env->macc[acc] & 0x00ff;
val = (env->macc[acc] >> 32) & 0xff00;
val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
val |= (env->macc[acc + 1] >> 16) & 0xff000000;
return val;
}
uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
{
uint32_t val;
val = (env->macc[acc] >> 32) & 0xffff;
val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
return val;
}
void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
{
int64_t res;
int32_t tmp;
res = env->macc[acc] & 0xffffffff00ull;
tmp = (int16_t)(val & 0xff00);
res |= ((int64_t)tmp) << 32;
res |= val & 0xff;
env->macc[acc] = res;
res = env->macc[acc + 1] & 0xffffffff00ull;
tmp = (val & 0xff000000);
res |= ((int64_t)tmp) << 16;
res |= (val >> 16) & 0xff;
env->macc[acc + 1] = res;
}
void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
{
int64_t res;
int32_t tmp;
res = (uint32_t)env->macc[acc];
tmp = (int16_t)val;
res |= ((int64_t)tmp) << 32;
env->macc[acc] = res;
res = (uint32_t)env->macc[acc + 1];
tmp = val & 0xffff0000;
res |= (int64_t)tmp << 16;
env->macc[acc + 1] = res;
}
void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
{
uint64_t res;
res = (uint32_t)env->macc[acc];
res |= ((uint64_t)(val & 0xffff)) << 32;
env->macc[acc] = res;
res = (uint32_t)env->macc[acc + 1];
res |= (uint64_t)(val & 0xffff0000) << 16;
env->macc[acc + 1] = res;
}

138
target-m68k/helpers.h Normal file
View File

@ -0,0 +1,138 @@
#ifndef DEF_HELPER
#define DEF_HELPER(name, ret, args) ret glue(helper_,name) args;
#endif
#ifdef GEN_HELPER
#define DEF_HELPER_0_0(name, ret, args) \
DEF_HELPER(name, ret, args) \
static inline void gen_helper_##name(void) \
{ \
tcg_gen_helper_0_0(helper_##name); \
}
#define DEF_HELPER_0_1(name, ret, args) \
DEF_HELPER(name, ret, args) \
static inline void gen_helper_##name(TCGv arg1) \
{ \
tcg_gen_helper_0_1(helper_##name, arg1); \
}
#define DEF_HELPER_0_2(name, ret, args) \
DEF_HELPER(name, ret, args) \
static inline void gen_helper_##name(TCGv arg1, TCGv arg2) \
{ \
tcg_gen_helper_0_2(helper_##name, arg1, arg2); \
}
#define DEF_HELPER_0_3(name, ret, args) \
DEF_HELPER(name, ret, args) \
static inline void gen_helper_##name( \
TCGv arg1, TCGv arg2, TCGv arg3) \
{ \
tcg_gen_helper_0_3(helper_##name, arg1, arg2, arg3); \
}
#define DEF_HELPER_1_0(name, ret, args) \
DEF_HELPER(name, ret, args) \
static inline void gen_helper_##name(TCGv ret) \
{ \
tcg_gen_helper_1_0(helper_##name, ret); \
}
#define DEF_HELPER_1_1(name, ret, args) \
DEF_HELPER(name, ret, args) \
static inline void gen_helper_##name(TCGv ret, TCGv arg1) \
{ \
tcg_gen_helper_1_1(helper_##name, ret, arg1); \
}
#define DEF_HELPER_1_2(name, ret, args) \
DEF_HELPER(name, ret, args) \
static inline void gen_helper_##name(TCGv ret, TCGv arg1, TCGv arg2) \
{ \
tcg_gen_helper_1_2(helper_##name, ret, arg1, arg2); \
}
#define DEF_HELPER_1_3(name, ret, args) \
DEF_HELPER(name, ret, args) \
static inline void gen_helper_##name(TCGv ret, \
TCGv arg1, TCGv arg2, TCGv arg3) \
{ \
tcg_gen_helper_1_3(helper_##name, ret, arg1, arg2, arg3); \
}
#define DEF_HELPER_1_4(name, ret, args) \
DEF_HELPER(name, ret, args) \
static inline void gen_helper_##name(TCGv ret, \
TCGv arg1, TCGv arg2, TCGv arg3, TCGv arg4) \
{ \
tcg_gen_helper_1_4(helper_##name, ret, arg1, arg2, arg3, arg4); \
}
#else /* !GEN_HELPER */
#define DEF_HELPER_0_0 DEF_HELPER
#define DEF_HELPER_0_1 DEF_HELPER
#define DEF_HELPER_0_2 DEF_HELPER
#define DEF_HELPER_0_3 DEF_HELPER
#define DEF_HELPER_1_0 DEF_HELPER
#define DEF_HELPER_1_1 DEF_HELPER
#define DEF_HELPER_1_2 DEF_HELPER
#define DEF_HELPER_1_3 DEF_HELPER
#define DEF_HELPER_1_4 DEF_HELPER
#define HELPER(x) glue(helper_,x)
#endif
DEF_HELPER_1_1(bitrev, uint32_t, (uint32_t))
DEF_HELPER_1_1(ff1, uint32_t, (uint32_t))
DEF_HELPER_1_2(sats, uint32_t, (uint32_t, uint32_t))
DEF_HELPER_0_2(divu, void, (CPUState *, uint32_t))
DEF_HELPER_0_2(divs, void, (CPUState *, uint32_t))
DEF_HELPER_1_3(addx_cc, uint32_t, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_1_3(subx_cc, uint32_t, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_1_3(shl_cc, uint32_t, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_1_3(shr_cc, uint32_t, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_1_3(sar_cc, uint32_t, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_1_2(xflag_lt, uint32_t, (uint32_t, uint32_t))
DEF_HELPER_0_2(set_sr, void, (CPUState *, uint32_t))
DEF_HELPER_0_3(movec, void, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_1_2(f64_to_i32, float32, (CPUState *, float64))
DEF_HELPER_1_2(f64_to_f32, float32, (CPUState *, float64))
DEF_HELPER_1_2(i32_to_f64, float64, (CPUState *, uint32_t))
DEF_HELPER_1_2(f32_to_f64, float64, (CPUState *, float32))
DEF_HELPER_1_2(iround_f64, float64, (CPUState *, float64))
DEF_HELPER_1_2(itrunc_f64, float64, (CPUState *, float64))
DEF_HELPER_1_2(sqrt_f64, float64, (CPUState *, float64))
DEF_HELPER_1_1(abs_f64, float64, (float64))
DEF_HELPER_1_1(chs_f64, float64, (float64))
DEF_HELPER_1_3(add_f64, float64, (CPUState *, float64, float64))
DEF_HELPER_1_3(sub_f64, float64, (CPUState *, float64, float64))
DEF_HELPER_1_3(mul_f64, float64, (CPUState *, float64, float64))
DEF_HELPER_1_3(div_f64, float64, (CPUState *, float64, float64))
DEF_HELPER_1_3(sub_cmp_f64, float64, (CPUState *, float64, float64))
DEF_HELPER_1_2(compare_f64, uint32_t, (CPUState *, float64))
DEF_HELPER_0_3(mac_move, void, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_1_3(macmulf, uint64_t, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_1_3(macmuls, uint64_t, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_1_3(macmulu, uint64_t, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_0_2(macsats, void, (CPUState *, uint32_t))
DEF_HELPER_0_2(macsatu, void, (CPUState *, uint32_t))
DEF_HELPER_0_2(macsatf, void, (CPUState *, uint32_t))
DEF_HELPER_0_2(mac_set_flags, void, (CPUState *, uint32_t))
DEF_HELPER_0_2(set_macsr, void, (CPUState *, uint32_t))
DEF_HELPER_1_2(get_macf, uint32_t, (CPUState *, uint64_t))
DEF_HELPER_1_1(get_macs, uint32_t, (uint64_t))
DEF_HELPER_1_1(get_macu, uint32_t, (uint64_t))
DEF_HELPER_1_2(get_mac_extf, uint32_t, (CPUState *, uint32_t))
DEF_HELPER_1_2(get_mac_exti, uint32_t, (CPUState *, uint32_t))
DEF_HELPER_0_3(set_mac_extf, void, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_0_3(set_mac_exts, void, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_0_3(set_mac_extu, void, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_0_2(flush_flags, void, (CPUState *, uint32_t))
DEF_HELPER_0_1(raise_exception, void, (uint32_t))
#undef DEF_HELPER
#undef DEF_HELPER_0_0
#undef DEF_HELPER_0_1
#undef DEF_HELPER_0_2
#undef DEF_HELPER_0_3
#undef DEF_HELPER_1_0
#undef DEF_HELPER_1_1
#undef DEF_HELPER_1_2
#undef DEF_HELPER_1_3
#undef DEF_HELPER_1_4
#undef GEN_HELPER
#undef DEF_HELPER

View File

@ -1,130 +0,0 @@
/* Various hacks to make code written for a dynamic code generator work
with regular QEMU. */
static int free_qreg;
#define QMODE_I32 1
#define QMODE_F32 1
#define QMODE_F64 2
static inline int gen_new_qreg(int mode)
{
int qreg;
qreg = free_qreg;
free_qreg += mode;
if (free_qreg > MAX_QREGS) {
fprintf(stderr, "qreg overflow\n");
abort();
}
return qreg + TARGET_NUM_QREGS;
}
static inline int gen_im32(uint32_t i)
{
int qreg = gen_new_qreg(QMODE_I32);
gen_op_mov32_im(qreg, i);
return qreg;
}
static inline void gen_op_ldf32_raw(int dest, int addr)
{
gen_op_ld32_raw(dest, addr);
}
static inline void gen_op_stf32_raw(int addr, int dest)
{
gen_op_st32_raw(addr, dest);
}
#if !defined(CONFIG_USER_ONLY)
static inline void gen_op_ldf32_user(int dest, int addr)
{
gen_op_ld32_user(dest, addr);
}
static inline void gen_op_stf32_user(int addr, int dest)
{
gen_op_st32_user(addr, dest);
}
static inline void gen_op_ldf32_kernel(int dest, int addr)
{
gen_op_ld32_kernel(dest, addr);
}
static inline void gen_op_stf32_kernel(int addr, int dest)
{
gen_op_st32_kernel(addr, dest);
}
#endif
static inline void gen_op_pack_32_f32(int dest, int src)
{
gen_op_mov32(dest, src);
}
static inline void gen_op_pack_f32_32(int dest, int src)
{
gen_op_mov32(dest, src);
}
static inline void gen_op_flags_set(void)
{
/* Dummy op. */
}
static inline void gen_op_shl_im_cc(int val, int shift)
{
gen_op_shl_cc(val, gen_im32(shift));
}
static inline void gen_op_shr_im_cc(int val, int shift)
{
gen_op_shr_cc(val, gen_im32(shift));
}
static inline void gen_op_sar_im_cc(int val, int shift)
{
gen_op_sar_cc(val, gen_im32(shift));
}
#ifdef USE_DIRECT_JUMP
#define TBPARAM(x)
#else
#define TBPARAM(x) (long)(x)
#endif
static inline void gen_op_goto_tb(int dummy, int n, long tb)
{
if (n == 0) {
gen_op_goto_tb0(TBPARAM(tb));
} else {
gen_op_goto_tb1(TBPARAM(tb));
}
}
static inline void gen_op_jmp_z32(int val, int label)
{
gen_op_set_T0_z32(val);
gen_op_jmp_T0(label);
}
static inline void gen_op_jmp_nz32(int val, int label)
{
gen_op_set_T0_nz32(val);
gen_op_jmp_T0(label);
}
static inline void gen_op_jmp_s32(int val, int label)
{
gen_op_set_T0_s32(val);
gen_op_jmp_T0(label);
}
static inline void gen_op_jmp_ns32(int val, int label)
{
gen_op_set_T0_ns32(val);
gen_op_jmp_T0(label);
}

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "exec.h" #include "exec.h"
#include "helpers.h"
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
@ -161,3 +162,71 @@ void do_interrupt(int is_hw)
} }
#endif #endif
static void raise_exception(int tt)
{
env->exception_index = tt;
cpu_loop_exit();
}
void HELPER(raise_exception)(uint32_t tt)
{
raise_exception(tt);
}
void HELPER(divu)(CPUState *env, uint32_t word)
{
uint32_t num;
uint32_t den;
uint32_t quot;
uint32_t rem;
uint32_t flags;
num = env->div1;
den = env->div2;
/* ??? This needs to make sure the throwing location is accurate. */
if (den == 0)
raise_exception(EXCP_DIV0);
quot = num / den;
rem = num % den;
flags = 0;
/* Avoid using a PARAM1 of zero. This breaks dyngen because it uses
the address of a symbol, and gcc knows symbols can't have address
zero. */
if (word && quot > 0xffff)
flags |= CCF_V;
if (quot == 0)
flags |= CCF_Z;
else if ((int32_t)quot < 0)
flags |= CCF_N;
env->div1 = quot;
env->div2 = rem;
env->cc_dest = flags;
}
void HELPER(divs)(CPUState *env, uint32_t word)
{
int32_t num;
int32_t den;
int32_t quot;
int32_t rem;
int32_t flags;
num = env->div1;
den = env->div2;
if (den == 0)
raise_exception(EXCP_DIV0);
quot = num / den;
rem = num % den;
flags = 0;
if (word && quot != (int16_t)quot)
flags |= CCF_V;
if (quot == 0)
flags |= CCF_Z;
else if (quot < 0)
flags |= CCF_N;
env->div1 = quot;
env->div2 = rem;
env->cc_dest = flags;
}

View File

@ -1,46 +0,0 @@
/* Load/store ops. */
#define MEM_LD_OP(name,suffix) \
OP(glue(glue(ld,name),MEMSUFFIX)) \
{ \
uint32_t addr = get_op(PARAM2); \
set_op(PARAM1, glue(glue(ld,suffix),MEMSUFFIX)(addr)); \
FORCE_RET(); \
}
MEM_LD_OP(8u32,ub)
MEM_LD_OP(8s32,sb)
MEM_LD_OP(16u32,uw)
MEM_LD_OP(16s32,sw)
MEM_LD_OP(32,l)
#undef MEM_LD_OP
#define MEM_ST_OP(name,suffix) \
OP(glue(glue(st,name),MEMSUFFIX)) \
{ \
uint32_t addr = get_op(PARAM1); \
glue(glue(st,suffix),MEMSUFFIX)(addr, get_op(PARAM2)); \
FORCE_RET(); \
}
MEM_ST_OP(8,b)
MEM_ST_OP(16,w)
MEM_ST_OP(32,l)
#undef MEM_ST_OP
OP(glue(ldf64,MEMSUFFIX))
{
uint32_t addr = get_op(PARAM2);
set_opf64(PARAM1, glue(ldfq,MEMSUFFIX)(addr));
FORCE_RET();
}
OP(glue(stf64,MEMSUFFIX))
{
uint32_t addr = get_op(PARAM1);
glue(stfq,MEMSUFFIX)(addr, get_opf64(PARAM2));
FORCE_RET();
}
#undef MEMSUFFIX

View File

@ -1,37 +1,13 @@
DEFO32(D0, dregs[0])
DEFO32(D1, dregs[1])
DEFO32(D2, dregs[2])
DEFO32(D3, dregs[3])
DEFO32(D4, dregs[4])
DEFO32(D5, dregs[5])
DEFO32(D6, dregs[6])
DEFO32(D7, dregs[7])
DEFO32(A0, aregs[0])
DEFO32(A1, aregs[1])
DEFO32(A2, aregs[2])
DEFO32(A3, aregs[3])
DEFO32(A4, aregs[4])
DEFO32(A5, aregs[5])
DEFO32(A6, aregs[6])
DEFO32(SP, aregs[7]) /* A7 */
DEFF64(F0, fregs[0])
DEFF64(F1, fregs[1])
DEFF64(F2, fregs[2])
DEFF64(F3, fregs[3])
DEFF64(F4, fregs[4])
DEFF64(F5, fregs[5])
DEFF64(F6, fregs[6])
DEFF64(F7, fregs[7])
DEFF64(FP_RESULT, fp_result) DEFF64(FP_RESULT, fp_result)
DEFO32(PC, pc) DEFO32(PC, pc)
DEFO32(SR, sr) DEFO32(SR, sr)
DEFO32(CC_OP, cc_op) DEFO32(CC_OP, cc_op)
DEFR(T0, AREG1, QMODE_I32)
DEFO32(CC_DEST, cc_dest) DEFO32(CC_DEST, cc_dest)
DEFO32(CC_SRC, cc_src) DEFO32(CC_SRC, cc_src)
DEFO32(CC_X, cc_x) DEFO32(CC_X, cc_x)
DEFO32(DIV1, div1) DEFO32(DIV1, div1)
DEFO32(DIV2, div2) DEFO32(DIV2, div2)
DEFO32(EXCEPTION, exception_index) DEFO32(EXCEPTION, exception_index)
DEFO32(HALTED, halted)
DEFO32(MACSR, macsr) DEFO32(MACSR, macsr)
DEFO32(MAC_MASK, mac_mask) DEFO32(MAC_MASK, mac_mask)

File diff suppressed because it is too large Load Diff