mirror of
https://github.com/qemu/qemu.git
synced 2024-12-12 21:23:36 +08:00
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:
parent
3979144c49
commit
e1f3808e03
2
configure
vendored
2
configure
vendored
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
138
target-m68k/helpers.h
Normal 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
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
1059
target-m68k/op.c
1059
target-m68k/op.c
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue
Block a user