mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-06-04 19:28:20 +00:00
m68k comments break patch submission due to being incorrectly formatted
Altering all comments in target/m68k to match Qemu coding styles so that future patches wont fail due to style breaches. Backports commit 808d77bc5f878a666035d478480b8ed229bd49fe from qemu
This commit is contained in:
parent
977e53b921
commit
ac6ee425d3
|
@ -30,7 +30,7 @@
|
||||||
#define M68K_CPU_GET_CLASS(uc, obj) \
|
#define M68K_CPU_GET_CLASS(uc, obj) \
|
||||||
OBJECT_GET_CLASS(uc, M68kCPUClass, (obj), TYPE_M68K_CPU)
|
OBJECT_GET_CLASS(uc, M68kCPUClass, (obj), TYPE_M68K_CPU)
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* M68kCPUClass:
|
* M68kCPUClass:
|
||||||
* @parent_realize: The parent class' realize handler.
|
* @parent_realize: The parent class' realize handler.
|
||||||
* @parent_reset: The parent class' reset handler.
|
* @parent_reset: The parent class' reset handler.
|
||||||
|
|
|
@ -199,8 +199,10 @@ static void any_cpu_initfn(struct uc_struct *uc, Object *obj, void *opaque)
|
||||||
m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
|
m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
|
||||||
m68k_set_feature(env, M68K_FEATURE_BRAL);
|
m68k_set_feature(env, M68K_FEATURE_BRAL);
|
||||||
m68k_set_feature(env, M68K_FEATURE_CF_FPU);
|
m68k_set_feature(env, M68K_FEATURE_CF_FPU);
|
||||||
/* MAC and EMAC are mututally exclusive, so pick EMAC.
|
/*
|
||||||
It's mostly backwards compatible. */
|
* MAC and EMAC are mututally exclusive, so pick EMAC.
|
||||||
|
* It's mostly backwards compatible.
|
||||||
|
*/
|
||||||
m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
|
m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
|
||||||
m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
|
m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
|
||||||
m68k_set_feature(env, M68K_FEATURE_USP);
|
m68k_set_feature(env, M68K_FEATURE_USP);
|
||||||
|
|
|
@ -108,9 +108,11 @@ typedef struct CPUM68KState {
|
||||||
float_status fp_status;
|
float_status fp_status;
|
||||||
|
|
||||||
uint64_t mactmp;
|
uint64_t mactmp;
|
||||||
/* EMAC Hardware deals with 48-bit values composed of one 32-bit and
|
/*
|
||||||
two 8-bit parts. We store a single 64-bit value and
|
* EMAC Hardware deals with 48-bit values composed of one 32-bit and
|
||||||
rearrange/extend this when changing modes. */
|
* two 8-bit parts. We store a single 64-bit value and
|
||||||
|
* rearrange/extend this when changing modes.
|
||||||
|
*/
|
||||||
uint64_t macc[4];
|
uint64_t macc[4];
|
||||||
uint32_t macsr;
|
uint32_t macsr;
|
||||||
uint32_t mac_mask;
|
uint32_t mac_mask;
|
||||||
|
@ -153,7 +155,7 @@ typedef struct CPUM68KState {
|
||||||
struct uc_struct *uc;
|
struct uc_struct *uc;
|
||||||
} CPUM68KState;
|
} CPUM68KState;
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* M68kCPU:
|
* M68kCPU:
|
||||||
* @env: #CPUM68KState
|
* @env: #CPUM68KState
|
||||||
*
|
*
|
||||||
|
@ -177,9 +179,11 @@ int m68k_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||||
int m68k_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
int m68k_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||||
|
|
||||||
void m68k_tcg_init(struct uc_struct *uc);
|
void m68k_tcg_init(struct uc_struct *uc);
|
||||||
/* you can call this signal handler from your SIGBUS and SIGSEGV
|
/*
|
||||||
signal handlers to inform the virtual CPU of exceptions. non zero
|
* you can call this signal handler from your SIGBUS and SIGSEGV
|
||||||
is returned if the signal was handled by the virtual CPU. */
|
* signal handlers to inform the virtual CPU of exceptions. non zero
|
||||||
|
* is returned if the signal was handled by the virtual CPU.
|
||||||
|
*/
|
||||||
int cpu_m68k_signal_handler(int host_signum, void *pinfo,
|
int cpu_m68k_signal_handler(int host_signum, void *pinfo,
|
||||||
void *puc);
|
void *puc);
|
||||||
uint32_t cpu_m68k_get_ccr(CPUM68KState *env);
|
uint32_t cpu_m68k_get_ccr(CPUM68KState *env);
|
||||||
|
@ -444,9 +448,11 @@ void m68k_switch_sp(CPUM68KState *env);
|
||||||
|
|
||||||
void do_m68k_semihosting(CPUM68KState *env, int nr);
|
void do_m68k_semihosting(CPUM68KState *env, int nr);
|
||||||
|
|
||||||
/* There are 4 ColdFire core ISA revisions: A, A+, B and C.
|
/*
|
||||||
Each feature covers the subset of instructions common to the
|
* There are 4 ColdFire core ISA revisions: A, A+, B and C.
|
||||||
ISA revisions mentioned. */
|
* Each feature covers the subset of instructions common to the
|
||||||
|
* ISA revisions mentioned.
|
||||||
|
*/
|
||||||
|
|
||||||
enum m68k_features {
|
enum m68k_features {
|
||||||
M68K_FEATURE_M68000,
|
M68K_FEATURE_M68000,
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
#include "exec/cpu_ldst.h"
|
#include "exec/cpu_ldst.h"
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
|
||||||
/* Undefined offsets may be different on various FPU.
|
/*
|
||||||
|
* Undefined offsets may be different on various FPU.
|
||||||
* On 68040 they return 0.0 (floatx80_zero)
|
* On 68040 they return 0.0 (floatx80_zero)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -622,7 +623,8 @@ void HELPER(fcos)(CPUM68KState *env, FPReg *res, FPReg *val)
|
||||||
void HELPER(fsincos)(CPUM68KState *env, FPReg *res0, FPReg *res1, FPReg *val)
|
void HELPER(fsincos)(CPUM68KState *env, FPReg *res0, FPReg *res1, FPReg *val)
|
||||||
{
|
{
|
||||||
floatx80 a = val->d;
|
floatx80 a = val->d;
|
||||||
/* If res0 and res1 specify the same floating-point data register,
|
/*
|
||||||
|
* If res0 and res1 specify the same floating-point data register,
|
||||||
* the sine result is stored in the register, and the cosine
|
* the sine result is stored in the register, and the cosine
|
||||||
* result is discarded.
|
* result is discarded.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -606,9 +606,11 @@ void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MAC unit. */
|
/* 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
|
* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
|
||||||
in-place. */
|
* take values, others take register numbers and manipulate the contents
|
||||||
|
* in-place.
|
||||||
|
*/
|
||||||
void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
|
void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
|
||||||
{
|
{
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
|
@ -688,9 +690,11 @@ void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
|
||||||
if (env->macsr & MACSR_V) {
|
if (env->macsr & MACSR_V) {
|
||||||
env->macsr |= MACSR_PAV0 << acc;
|
env->macsr |= MACSR_PAV0 << acc;
|
||||||
if (env->macsr & MACSR_OMC) {
|
if (env->macsr & MACSR_OMC) {
|
||||||
/* The result is saturated to 32 bits, despite overflow occurring
|
/*
|
||||||
at 48 bits. Seems weird, but that's what the hardware docs
|
* The result is saturated to 32 bits, despite overflow occurring
|
||||||
say. */
|
* at 48 bits. Seems weird, but that's what the hardware docs
|
||||||
|
* say.
|
||||||
|
*/
|
||||||
result = (result >> 63) ^ 0x7fffffff;
|
result = (result >> 63) ^ 0x7fffffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -501,10 +501,12 @@ bool m68k_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||||
|
|
||||||
if (interrupt_request & CPU_INTERRUPT_HARD
|
if (interrupt_request & CPU_INTERRUPT_HARD
|
||||||
&& ((env->sr & SR_I) >> SR_I_SHIFT) < env->pending_level) {
|
&& ((env->sr & SR_I) >> SR_I_SHIFT) < env->pending_level) {
|
||||||
/* Real hardware gets the interrupt vector via an IACK cycle
|
/*
|
||||||
at this point. Current emulated hardware doesn't rely on
|
* Real hardware gets the interrupt vector via an IACK cycle
|
||||||
this, so we provide/save the vector when the interrupt is
|
* at this point. Current emulated hardware doesn't rely on
|
||||||
first signalled. */
|
* this, so we provide/save the vector when the interrupt is
|
||||||
|
* first signalled.
|
||||||
|
*/
|
||||||
cs->exception_index = env->pending_vector;
|
cs->exception_index = env->pending_vector;
|
||||||
do_interrupt_m68k_hardirq(env);
|
do_interrupt_m68k_hardirq(env);
|
||||||
return true;
|
return true;
|
||||||
|
@ -545,7 +547,8 @@ void HELPER(divuw)(CPUM68KState *env, int destr, uint32_t den)
|
||||||
env->cc_c = 0; /* always cleared, even if overflow */
|
env->cc_c = 0; /* always cleared, even if overflow */
|
||||||
if (quot > 0xffff) {
|
if (quot > 0xffff) {
|
||||||
env->cc_v = -1;
|
env->cc_v = -1;
|
||||||
/* real 68040 keeps N and unset Z on overflow,
|
/*
|
||||||
|
* real 68040 keeps N and unset Z on overflow,
|
||||||
* whereas documentation says "undefined"
|
* whereas documentation says "undefined"
|
||||||
*/
|
*/
|
||||||
env->cc_z = 1;
|
env->cc_z = 1;
|
||||||
|
@ -572,7 +575,8 @@ void HELPER(divsw)(CPUM68KState *env, int destr, int32_t den)
|
||||||
if (quot != (int16_t)quot) {
|
if (quot != (int16_t)quot) {
|
||||||
env->cc_v = -1;
|
env->cc_v = -1;
|
||||||
/* nothing else is modified */
|
/* nothing else is modified */
|
||||||
/* real 68040 keeps N and unset Z on overflow,
|
/*
|
||||||
|
* real 68040 keeps N and unset Z on overflow,
|
||||||
* whereas documentation says "undefined"
|
* whereas documentation says "undefined"
|
||||||
*/
|
*/
|
||||||
env->cc_z = 1;
|
env->cc_z = 1;
|
||||||
|
@ -655,7 +659,8 @@ void HELPER(divull)(CPUM68KState *env, int numr, int regr, uint32_t den)
|
||||||
env->cc_c = 0; /* always cleared, even if overflow */
|
env->cc_c = 0; /* always cleared, even if overflow */
|
||||||
if (quot > 0xffffffffULL) {
|
if (quot > 0xffffffffULL) {
|
||||||
env->cc_v = -1;
|
env->cc_v = -1;
|
||||||
/* real 68040 keeps N and unset Z on overflow,
|
/*
|
||||||
|
* real 68040 keeps N and unset Z on overflow,
|
||||||
* whereas documentation says "undefined"
|
* whereas documentation says "undefined"
|
||||||
*/
|
*/
|
||||||
env->cc_z = 1;
|
env->cc_z = 1;
|
||||||
|
@ -689,7 +694,8 @@ void HELPER(divsll)(CPUM68KState *env, int numr, int regr, int32_t den)
|
||||||
env->cc_c = 0; /* always cleared, even if overflow */
|
env->cc_c = 0; /* always cleared, even if overflow */
|
||||||
if (quot != (int32_t)quot) {
|
if (quot != (int32_t)quot) {
|
||||||
env->cc_v = -1;
|
env->cc_v = -1;
|
||||||
/* real 68040 keeps N and unset Z on overflow,
|
/*
|
||||||
|
* real 68040 keeps N and unset Z on overflow,
|
||||||
* whereas documentation says "undefined"
|
* whereas documentation says "undefined"
|
||||||
*/
|
*/
|
||||||
env->cc_z = 1;
|
env->cc_z = 1;
|
||||||
|
@ -848,14 +854,18 @@ static struct bf_data bf_prep(uint32_t addr, int32_t ofs, uint32_t len)
|
||||||
addr -= 1;
|
addr -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute the number of bytes required (minus one) to
|
/*
|
||||||
satisfy the bitfield. */
|
* Compute the number of bytes required (minus one) to
|
||||||
|
* satisfy the bitfield.
|
||||||
|
*/
|
||||||
blen = (bofs + len - 1) / 8;
|
blen = (bofs + len - 1) / 8;
|
||||||
|
|
||||||
/* Canonicalize the bit offset for data loaded into a 64-bit big-endian
|
/*
|
||||||
word. For the cases where BLEN is not a power of 2, adjust ADDR so
|
* Canonicalize the bit offset for data loaded into a 64-bit big-endian
|
||||||
that we can use the next power of two sized load without crossing a
|
* word. For the cases where BLEN is not a power of 2, adjust ADDR so
|
||||||
page boundary, unless the field itself crosses the boundary. */
|
* that we can use the next power of two sized load without crossing a
|
||||||
|
* page boundary, unless the field itself crosses the boundary.
|
||||||
|
*/
|
||||||
switch (blen) {
|
switch (blen) {
|
||||||
case 0:
|
case 0:
|
||||||
bofs += 56;
|
bofs += 56;
|
||||||
|
@ -946,8 +956,10 @@ uint64_t HELPER(bfextu_mem)(CPUM68KState *env, uint32_t addr,
|
||||||
struct bf_data d = bf_prep(addr, ofs, len);
|
struct bf_data d = bf_prep(addr, ofs, len);
|
||||||
uint64_t data = bf_load(env, d.addr, d.blen, ra);
|
uint64_t data = bf_load(env, d.addr, d.blen, ra);
|
||||||
|
|
||||||
/* Put CC_N at the top of the high word; put the zero-extended value
|
/*
|
||||||
at the bottom of the low word. */
|
* Put CC_N at the top of the high word; put the zero-extended value
|
||||||
|
* at the bottom of the low word.
|
||||||
|
*/
|
||||||
data <<= d.bofs;
|
data <<= d.bofs;
|
||||||
data >>= 64 - d.len;
|
data >>= 64 - d.len;
|
||||||
data |= data << (64 - d.len);
|
data |= data << (64 - d.len);
|
||||||
|
@ -1025,15 +1037,18 @@ uint64_t HELPER(bfffo_mem)(CPUM68KState *env, uint32_t addr,
|
||||||
uint64_t n = (data & mask) << d.bofs;
|
uint64_t n = (data & mask) << d.bofs;
|
||||||
uint32_t ffo = helper_bfffo_reg(n >> 32, ofs, d.len);
|
uint32_t ffo = helper_bfffo_reg(n >> 32, ofs, d.len);
|
||||||
|
|
||||||
/* Return FFO in the low word and N in the high word.
|
/*
|
||||||
Note that because of MASK and the shift, the low word
|
* Return FFO in the low word and N in the high word.
|
||||||
is already zero. */
|
* Note that because of MASK and the shift, the low word
|
||||||
|
* is already zero.
|
||||||
|
*/
|
||||||
return n | ffo;
|
return n | ffo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HELPER(chk)(CPUM68KState *env, int32_t val, int32_t ub)
|
void HELPER(chk)(CPUM68KState *env, int32_t val, int32_t ub)
|
||||||
{
|
{
|
||||||
/* From the specs:
|
/*
|
||||||
|
* From the specs:
|
||||||
* X: Not affected, C,V,Z: Undefined,
|
* X: Not affected, C,V,Z: Undefined,
|
||||||
* N: Set if val < 0; cleared if val > ub, undefined otherwise
|
* N: Set if val < 0; cleared if val > ub, undefined otherwise
|
||||||
* We implement here values found from a real MC68040:
|
* We implement here values found from a real MC68040:
|
||||||
|
@ -1063,7 +1078,8 @@ void HELPER(chk)(CPUM68KState *env, int32_t val, int32_t ub)
|
||||||
|
|
||||||
void HELPER(chk2)(CPUM68KState *env, int32_t val, int32_t lb, int32_t ub)
|
void HELPER(chk2)(CPUM68KState *env, int32_t val, int32_t lb, int32_t ub)
|
||||||
{
|
{
|
||||||
/* From the specs:
|
/*
|
||||||
|
* From the specs:
|
||||||
* X: Not affected, N,V: Undefined,
|
* X: Not affected, N,V: Undefined,
|
||||||
* Z: Set if val is equal to lb or ub
|
* Z: Set if val is equal to lb or ub
|
||||||
* C: Set if val < lb or val > ub, cleared otherwise
|
* C: Set if val < lb or val > ub, cleared otherwise
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
* the Softfloat-2a license unless specifically indicated otherwise.
|
* the Softfloat-2a license unless specifically indicated otherwise.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Portions of this work are licensed under the terms of the GNU GPL,
|
/*
|
||||||
|
* Portions of this work are licensed under the terms of the GNU GPL,
|
||||||
* version 2 or later. See the COPYING file in the top-level directory.
|
* version 2 or later. See the COPYING file in the top-level directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -41,10 +42,10 @@ static floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status)
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Returns the modulo remainder of the extended double-precision floating-point
|
* Returns the modulo remainder of the extended double-precision floating-point
|
||||||
| value `a' with respect to the corresponding value `b'.
|
* value `a' with respect to the corresponding value `b'.
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status)
|
floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -124,10 +125,10 @@ floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status)
|
||||||
80, zSign, bExp + expDiff, aSig0, aSig1, status);
|
80, zSign, bExp + expDiff, aSig0, aSig1, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Returns the mantissa of the extended double-precision floating-point
|
* Returns the mantissa of the extended double-precision floating-point
|
||||||
| value `a'.
|
* value `a'.
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_getman(floatx80 a, float_status *status)
|
floatx80 floatx80_getman(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -158,10 +159,10 @@ floatx80 floatx80_getman(floatx80 a, float_status *status)
|
||||||
0x3FFF, aSig, 0, status);
|
0x3FFF, aSig, 0, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Returns the exponent of the extended double-precision floating-point
|
* Returns the exponent of the extended double-precision floating-point
|
||||||
| value `a' as an extended double-precision value.
|
* value `a' as an extended double-precision value.
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_getexp(floatx80 a, float_status *status)
|
floatx80 floatx80_getexp(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -191,13 +192,13 @@ floatx80 floatx80_getexp(floatx80 a, float_status *status)
|
||||||
return int32_to_floatx80(aExp - 0x3FFF, status);
|
return int32_to_floatx80(aExp - 0x3FFF, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Scales extended double-precision floating-point value in operand `a' by
|
* Scales extended double-precision floating-point value in operand `a' by
|
||||||
| value `b'. The function truncates the value in the second operand 'b' to
|
* value `b'. The function truncates the value in the second operand 'b' to
|
||||||
| an integral value and adds that value to the exponent of the operand 'a'.
|
* an integral value and adds that value to the exponent of the operand 'a'.
|
||||||
| The operation performed according to the IEC/IEEE Standard for Binary
|
* The operation performed according to the IEC/IEEE Standard for Binary
|
||||||
| Floating-Point Arithmetic.
|
* Floating-Point Arithmetic.
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
|
floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -282,26 +283,26 @@ floatx80 floatx80_move(floatx80 a, float_status *status)
|
||||||
aExp, aSig, 0, status);
|
aExp, aSig, 0, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Algorithms for transcendental functions supported by MC68881 and MC68882
|
* Algorithms for transcendental functions supported by MC68881 and MC68882
|
||||||
| mathematical coprocessors. The functions are derived from FPSP library.
|
* mathematical coprocessors. The functions are derived from FPSP library.
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
#define one_exp 0x3FFF
|
#define one_exp 0x3FFF
|
||||||
#define one_sig LIT64(0x8000000000000000)
|
#define one_sig LIT64(0x8000000000000000)
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Function for compactifying extended double-precision floating point values.
|
* Function for compactifying extended double-precision floating point values.
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
static int32_t floatx80_make_compact(int32_t aExp, uint64_t aSig)
|
static int32_t floatx80_make_compact(int32_t aExp, uint64_t aSig)
|
||||||
{
|
{
|
||||||
return (aExp << 16) | (aSig >> 48);
|
return (aExp << 16) | (aSig >> 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Log base e of x plus 1
|
* Log base e of x plus 1
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_lognp1(floatx80 a, float_status *status)
|
floatx80 floatx80_lognp1(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -498,9 +499,9 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Log base e
|
* Log base e
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_logn(floatx80 a, float_status *status)
|
floatx80 floatx80_logn(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -666,9 +667,9 @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Log base 10
|
* Log base 10
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_log10(floatx80 a, float_status *status)
|
floatx80 floatx80_log10(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -723,9 +724,9 @@ floatx80 floatx80_log10(floatx80 a, float_status *status)
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Log base 2
|
* Log base 2
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_log2(floatx80 a, float_status *status)
|
floatx80 floatx80_log2(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -790,9 +791,9 @@ floatx80 floatx80_log2(floatx80 a, float_status *status)
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| e to x
|
* e to x
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_etox(floatx80 a, float_status *status)
|
floatx80 floatx80_etox(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -848,7 +849,8 @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
|
||||||
j = n & 0x3F; /* J = N mod 64 */
|
j = n & 0x3F; /* J = N mod 64 */
|
||||||
m = n / 64; /* NOTE: this is really arithmetic right shift by 6 */
|
m = n / 64; /* NOTE: this is really arithmetic right shift by 6 */
|
||||||
if (n < 0 && j) {
|
if (n < 0 && j) {
|
||||||
/* arithmetic right shift is division and
|
/*
|
||||||
|
* arithmetic right shift is division and
|
||||||
* round towards minus infinity
|
* round towards minus infinity
|
||||||
*/
|
*/
|
||||||
m--;
|
m--;
|
||||||
|
@ -973,9 +975,9 @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| 2 to x
|
* 2 to x
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_twotox(floatx80 a, float_status *status)
|
floatx80 floatx80_twotox(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -1051,14 +1053,16 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
|
||||||
j = n & 0x3F;
|
j = n & 0x3F;
|
||||||
l = n / 64; /* NOTE: this is really arithmetic right shift by 6 */
|
l = n / 64; /* NOTE: this is really arithmetic right shift by 6 */
|
||||||
if (n < 0 && j) {
|
if (n < 0 && j) {
|
||||||
/* arithmetic right shift is division and
|
/*
|
||||||
|
* arithmetic right shift is division and
|
||||||
* round towards minus infinity
|
* round towards minus infinity
|
||||||
*/
|
*/
|
||||||
l--;
|
l--;
|
||||||
}
|
}
|
||||||
m = l / 2; /* NOTE: this is really arithmetic right shift by 1 */
|
m = l / 2; /* NOTE: this is really arithmetic right shift by 1 */
|
||||||
if (l < 0 && (l & 1)) {
|
if (l < 0 && (l & 1)) {
|
||||||
/* arithmetic right shift is division and
|
/*
|
||||||
|
* arithmetic right shift is division and
|
||||||
* round towards minus infinity
|
* round towards minus infinity
|
||||||
*/
|
*/
|
||||||
m--;
|
m--;
|
||||||
|
@ -1121,9 +1125,9 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| 10 to x
|
* 10 to x
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_tentox(floatx80 a, float_status *status)
|
floatx80 floatx80_tentox(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -1200,14 +1204,16 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
|
||||||
j = n & 0x3F;
|
j = n & 0x3F;
|
||||||
l = n / 64; /* NOTE: this is really arithmetic right shift by 6 */
|
l = n / 64; /* NOTE: this is really arithmetic right shift by 6 */
|
||||||
if (n < 0 && j) {
|
if (n < 0 && j) {
|
||||||
/* arithmetic right shift is division and
|
/*
|
||||||
|
* arithmetic right shift is division and
|
||||||
* round towards minus infinity
|
* round towards minus infinity
|
||||||
*/
|
*/
|
||||||
l--;
|
l--;
|
||||||
}
|
}
|
||||||
m = l / 2; /* NOTE: this is really arithmetic right shift by 1 */
|
m = l / 2; /* NOTE: this is really arithmetic right shift by 1 */
|
||||||
if (l < 0 && (l & 1)) {
|
if (l < 0 && (l & 1)) {
|
||||||
/* arithmetic right shift is division and
|
/*
|
||||||
|
* arithmetic right shift is division and
|
||||||
* round towards minus infinity
|
* round towards minus infinity
|
||||||
*/
|
*/
|
||||||
m--;
|
m--;
|
||||||
|
@ -1274,9 +1280,9 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Tangent
|
* Tangent
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_tan(floatx80 a, float_status *status)
|
floatx80 floatx80_tan(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -1484,9 +1490,9 @@ floatx80 floatx80_tan(floatx80 a, float_status *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Sine
|
* Sine
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_sin(floatx80 a, float_status *status)
|
floatx80 floatx80_sin(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -1723,9 +1729,9 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Cosine
|
* Cosine
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_cos(floatx80 a, float_status *status)
|
floatx80 floatx80_cos(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -1960,9 +1966,9 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Arc tangent
|
* Arc tangent
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_atan(floatx80 a, float_status *status)
|
floatx80 floatx80_atan(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -2157,9 +2163,9 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Arc sine
|
* Arc sine
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_asin(floatx80 a, float_status *status)
|
floatx80 floatx80_asin(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -2222,9 +2228,9 @@ floatx80 floatx80_asin(floatx80 a, float_status *status)
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Arc cosine
|
* Arc cosine
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_acos(floatx80 a, float_status *status)
|
floatx80 floatx80_acos(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -2291,9 +2297,9 @@ floatx80 floatx80_acos(floatx80 a, float_status *status)
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Hyperbolic arc tangent
|
* Hyperbolic arc tangent
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_atanh(floatx80 a, float_status *status)
|
floatx80 floatx80_atanh(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -2356,9 +2362,9 @@ floatx80 floatx80_atanh(floatx80 a, float_status *status)
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| e to x minus 1
|
* e to x minus 1
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
|
floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -2410,7 +2416,8 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
|
||||||
j = n & 0x3F; /* J = N mod 64 */
|
j = n & 0x3F; /* J = N mod 64 */
|
||||||
m = n / 64; /* NOTE: this is really arithmetic right shift by 6 */
|
m = n / 64; /* NOTE: this is really arithmetic right shift by 6 */
|
||||||
if (n < 0 && j) {
|
if (n < 0 && j) {
|
||||||
/* arithmetic right shift is division and
|
/*
|
||||||
|
* arithmetic right shift is division and
|
||||||
* round towards minus infinity
|
* round towards minus infinity
|
||||||
*/
|
*/
|
||||||
m--;
|
m--;
|
||||||
|
@ -2607,9 +2614,9 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Hyperbolic tangent
|
* Hyperbolic tangent
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_tanh(floatx80 a, float_status *status)
|
floatx80 floatx80_tanh(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -2722,9 +2729,9 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Hyperbolic sine
|
* Hyperbolic sine
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_sinh(floatx80 a, float_status *status)
|
floatx80 floatx80_sinh(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
@ -2811,9 +2818,9 @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*
|
||||||
| Hyperbolic cosine
|
* Hyperbolic cosine
|
||||||
*----------------------------------------------------------------------------*/
|
*/
|
||||||
|
|
||||||
floatx80 floatx80_cosh(floatx80 a, float_status *status)
|
floatx80 floatx80_cosh(floatx80 a, float_status *status)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
* the Softfloat-2a license unless specifically indicated otherwise.
|
* the Softfloat-2a license unless specifically indicated otherwise.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Portions of this work are licensed under the terms of the GNU GPL,
|
/*
|
||||||
|
* Portions of this work are licensed under the terms of the GNU GPL,
|
||||||
* version 2 or later. See the COPYING file in the top-level directory.
|
* version 2 or later. See the COPYING file in the top-level directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
* the Softfloat-2a license unless specifically indicated otherwise.
|
* the Softfloat-2a license unless specifically indicated otherwise.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Portions of this work are licensed under the terms of the GNU GPL,
|
/*
|
||||||
|
* Portions of this work are licensed under the terms of the GNU GPL,
|
||||||
* version 2 or later. See the COPYING file in the top-level directory.
|
* version 2 or later. See the COPYING file in the top-level directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -241,8 +241,10 @@ static void set_cc_op(DisasContext *s, CCOp op)
|
||||||
s->cc_op = op;
|
s->cc_op = op;
|
||||||
s->cc_op_synced = 0;
|
s->cc_op_synced = 0;
|
||||||
|
|
||||||
/* Discard CC computation that will no longer be used.
|
/*
|
||||||
Note that X and N are never dead. */
|
* Discard CC computation that will no longer be used.
|
||||||
|
* Note that X and N are never dead.
|
||||||
|
*/
|
||||||
dead = cc_op_live[old_op] & ~cc_op_live[op];
|
dead = cc_op_live[old_op] & ~cc_op_live[op];
|
||||||
if (dead & CCF_C) {
|
if (dead & CCF_C) {
|
||||||
tcg_gen_discard_i32(tcg_ctx, tcg_ctx->QREG_CC_C);
|
tcg_gen_discard_i32(tcg_ctx, tcg_ctx->QREG_CC_C);
|
||||||
|
@ -307,8 +309,10 @@ static inline void gen_addr_fault(DisasContext *s)
|
||||||
gen_exception(s, s->base.pc_next, EXCP_ADDRESS);
|
gen_exception(s, s->base.pc_next, EXCP_ADDRESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate a load from the specified address. Narrow values are
|
/*
|
||||||
sign extended to full register width. */
|
* Generate a load from the specified address. Narrow values are
|
||||||
|
* sign extended to full register width.
|
||||||
|
*/
|
||||||
static inline TCGv gen_load(DisasContext *s, int opsize, TCGv addr,
|
static inline TCGv gen_load(DisasContext *s, int opsize, TCGv addr,
|
||||||
int sign, int index)
|
int sign, int index)
|
||||||
{
|
{
|
||||||
|
@ -362,8 +366,10 @@ typedef enum {
|
||||||
EA_LOADS
|
EA_LOADS
|
||||||
} ea_what;
|
} ea_what;
|
||||||
|
|
||||||
/* Generate an unsigned load if VAL is 0 a signed load if val is -1,
|
/*
|
||||||
otherwise generate a store. */
|
* Generate an unsigned load if VAL is 0 a signed load if val is -1,
|
||||||
|
* otherwise generate a store.
|
||||||
|
*/
|
||||||
static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
|
static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
|
||||||
ea_what what, int index)
|
ea_what what, int index)
|
||||||
{
|
{
|
||||||
|
@ -430,8 +436,10 @@ static TCGv gen_addr_index(DisasContext *s, uint16_t ext, TCGv tmp)
|
||||||
return add;
|
return add;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle a base + index + displacement effective addresss.
|
/*
|
||||||
A NULL_QREG base means pc-relative. */
|
* Handle a base + index + displacement effective addresss.
|
||||||
|
* A NULL_QREG base means pc-relative.
|
||||||
|
*/
|
||||||
static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
|
static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
@ -730,8 +738,10 @@ static inline int ext_opsize(int ext, int pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assign value to a register. If the width is less than the register width
|
/*
|
||||||
only the low part of the register is set. */
|
* Assign value to a register. If the width is less than the register width
|
||||||
|
* only the low part of the register is set.
|
||||||
|
*/
|
||||||
static void gen_partset_reg(DisasContext *s, int opsize, TCGv reg, TCGv val)
|
static void gen_partset_reg(DisasContext *s, int opsize, TCGv reg, TCGv val)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
@ -760,8 +770,10 @@ static void gen_partset_reg(DisasContext *s, int opsize, TCGv reg, TCGv val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate code for an "effective address". Does not adjust the base
|
/*
|
||||||
register for autoincrement addressing modes. */
|
* Generate code for an "effective address". Does not adjust the base
|
||||||
|
* register for autoincrement addressing modes.
|
||||||
|
*/
|
||||||
static TCGv gen_lea_mode(CPUM68KState *env, DisasContext *s,
|
static TCGv gen_lea_mode(CPUM68KState *env, DisasContext *s,
|
||||||
int mode, int reg0, int opsize)
|
int mode, int reg0, int opsize)
|
||||||
{
|
{
|
||||||
|
@ -835,9 +847,11 @@ static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
||||||
return gen_lea_mode(env, s, mode, reg0, opsize);
|
return gen_lea_mode(env, s, mode, reg0, opsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate code to load/store a value from/into an EA. If WHAT > 0 this is
|
/*
|
||||||
a write otherwise it is a read (0 == sign extend, -1 == zero extend).
|
* Generate code to load/store a value from/into an EA. If WHAT > 0 this is
|
||||||
ADDRP is non-null for readwrite operands. */
|
* a write otherwise it is a read (0 == sign extend, -1 == zero extend).
|
||||||
|
* ADDRP is non-null for readwrite operands.
|
||||||
|
*/
|
||||||
static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0,
|
static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0,
|
||||||
int opsize, TCGv val, TCGv *addrp, ea_what what,
|
int opsize, TCGv val, TCGv *addrp, ea_what what,
|
||||||
int index)
|
int index)
|
||||||
|
@ -1038,7 +1052,8 @@ static void gen_load_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp,
|
||||||
tcg_gen_st_i64(tcg_ctx, t64, fp, offsetof(FPReg, l.lower));
|
tcg_gen_st_i64(tcg_ctx, t64, fp, offsetof(FPReg, l.lower));
|
||||||
break;
|
break;
|
||||||
case OS_PACKED:
|
case OS_PACKED:
|
||||||
/* unimplemented data type on 68040/ColdFire
|
/*
|
||||||
|
* unimplemented data type on 68040/ColdFire
|
||||||
* FIXME if needed for another FPU
|
* FIXME if needed for another FPU
|
||||||
*/
|
*/
|
||||||
gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
|
gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
|
||||||
|
@ -1093,7 +1108,8 @@ static void gen_store_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp,
|
||||||
tcg_gen_qemu_st64(s->uc, t64, tmp, index);
|
tcg_gen_qemu_st64(s->uc, t64, tmp, index);
|
||||||
break;
|
break;
|
||||||
case OS_PACKED:
|
case OS_PACKED:
|
||||||
/* unimplemented data type on 68040/ColdFire
|
/*
|
||||||
|
* unimplemented data type on 68040/ColdFire
|
||||||
* FIXME if needed for another FPU
|
* FIXME if needed for another FPU
|
||||||
*/
|
*/
|
||||||
gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
|
gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
|
||||||
|
@ -1240,7 +1256,8 @@ static int gen_ea_mode_fp(CPUM68KState *env, DisasContext *s, int mode,
|
||||||
tcg_temp_free_i64(tcg_ctx, t64);
|
tcg_temp_free_i64(tcg_ctx, t64);
|
||||||
break;
|
break;
|
||||||
case OS_PACKED:
|
case OS_PACKED:
|
||||||
/* unimplemented data type on 68040/ColdFire
|
/*
|
||||||
|
* unimplemented data type on 68040/ColdFire
|
||||||
* FIXME if needed for another FPU
|
* FIXME if needed for another FPU
|
||||||
*/
|
*/
|
||||||
gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
|
gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
|
||||||
|
@ -1328,9 +1345,11 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
|
||||||
goto done;
|
goto done;
|
||||||
case 14: /* GT (!(Z || (N ^ V))) */
|
case 14: /* GT (!(Z || (N ^ V))) */
|
||||||
case 15: /* LE (Z || (N ^ V)) */
|
case 15: /* LE (Z || (N ^ V)) */
|
||||||
/* Logic operations clear V, which simplifies LE to (Z || N),
|
/*
|
||||||
and since Z and N are co-located, this becomes a normal
|
* Logic operations clear V, which simplifies LE to (Z || N),
|
||||||
comparison vs N. */
|
* and since Z and N are co-located, this becomes a normal
|
||||||
|
* comparison vs N.
|
||||||
|
*/
|
||||||
if (op == CC_OP_LOGIC) {
|
if (op == CC_OP_LOGIC) {
|
||||||
c->v1 = tcg_ctx->QREG_CC_N;
|
c->v1 = tcg_ctx->QREG_CC_N;
|
||||||
tcond = TCG_COND_LE;
|
tcond = TCG_COND_LE;
|
||||||
|
@ -1587,9 +1606,11 @@ DISAS_INSN(undef_fpu)
|
||||||
|
|
||||||
DISAS_INSN(undef)
|
DISAS_INSN(undef)
|
||||||
{
|
{
|
||||||
/* ??? This is both instructions that are as yet unimplemented
|
/*
|
||||||
for the 680x0 series, as well as those that are implemented
|
* ??? This is both instructions that are as yet unimplemented
|
||||||
but actually illegal for CPU32 or pre-68020. */
|
* for the 680x0 series, as well as those that are implemented
|
||||||
|
* but actually illegal for CPU32 or pre-68020.
|
||||||
|
*/
|
||||||
qemu_log_mask(LOG_UNIMP, "Illegal instruction: %04x @ %08x\n",
|
qemu_log_mask(LOG_UNIMP, "Illegal instruction: %04x @ %08x\n",
|
||||||
insn, s->base.pc_next);
|
insn, s->base.pc_next);
|
||||||
gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
|
gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
|
||||||
|
@ -1697,7 +1718,8 @@ static void bcd_add(DisasContext *s, TCGv dest, TCGv src)
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
TCGv t0, t1;
|
TCGv t0, t1;
|
||||||
|
|
||||||
/* dest10 = dest10 + src10 + X
|
/*
|
||||||
|
* dest10 = dest10 + src10 + X
|
||||||
*
|
*
|
||||||
* t1 = src
|
* t1 = src
|
||||||
* t2 = t1 + 0x066
|
* t2 = t1 + 0x066
|
||||||
|
@ -1709,7 +1731,8 @@ static void bcd_add(DisasContext *s, TCGv dest, TCGv src)
|
||||||
* return t3 - t7
|
* return t3 - t7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* t1 = (src + 0x066) + dest + X
|
/*
|
||||||
|
* t1 = (src + 0x066) + dest + X
|
||||||
* = result with some possible exceding 0x6
|
* = result with some possible exceding 0x6
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1722,20 +1745,23 @@ static void bcd_add(DisasContext *s, TCGv dest, TCGv src)
|
||||||
|
|
||||||
/* we will remove exceding 0x6 where there is no carry */
|
/* we will remove exceding 0x6 where there is no carry */
|
||||||
|
|
||||||
/* t0 = (src + 0x0066) ^ dest
|
/*
|
||||||
|
* t0 = (src + 0x0066) ^ dest
|
||||||
* = t1 without carries
|
* = t1 without carries
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tcg_gen_xor_i32(tcg_ctx, t0, t0, dest);
|
tcg_gen_xor_i32(tcg_ctx, t0, t0, dest);
|
||||||
|
|
||||||
/* extract the carries
|
/*
|
||||||
|
* extract the carries
|
||||||
* t0 = t0 ^ t1
|
* t0 = t0 ^ t1
|
||||||
* = only the carries
|
* = only the carries
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tcg_gen_xor_i32(tcg_ctx, t0, t0, t1);
|
tcg_gen_xor_i32(tcg_ctx, t0, t0, t1);
|
||||||
|
|
||||||
/* generate 0x1 where there is no carry
|
/*
|
||||||
|
* generate 0x1 where there is no carry
|
||||||
* and for each 0x10, generate a 0x6
|
* and for each 0x10, generate a 0x6
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1746,7 +1772,8 @@ static void bcd_add(DisasContext *s, TCGv dest, TCGv src)
|
||||||
tcg_gen_add_i32(tcg_ctx, dest, dest, t0);
|
tcg_gen_add_i32(tcg_ctx, dest, dest, t0);
|
||||||
tcg_temp_free(tcg_ctx, t0);
|
tcg_temp_free(tcg_ctx, t0);
|
||||||
|
|
||||||
/* remove the exceding 0x6
|
/*
|
||||||
|
* remove the exceding 0x6
|
||||||
* for digits that have not generated a carry
|
* for digits that have not generated a carry
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1759,7 +1786,8 @@ static void bcd_sub(DisasContext *s, TCGv dest, TCGv src)
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
TCGv t0, t1, t2;
|
TCGv t0, t1, t2;
|
||||||
|
|
||||||
/* dest10 = dest10 - src10 - X
|
/*
|
||||||
|
* dest10 = dest10 - src10 - X
|
||||||
* = bcd_add(dest + 1 - X, 0x199 - src)
|
* = bcd_add(dest + 1 - X, 0x199 - src)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1784,7 +1812,8 @@ static void bcd_sub(DisasContext *s, TCGv dest, TCGv src)
|
||||||
|
|
||||||
tcg_gen_xor_i32(tcg_ctx, t0, t1, t2);
|
tcg_gen_xor_i32(tcg_ctx, t0, t1, t2);
|
||||||
|
|
||||||
/* t2 = ~t0 & 0x110
|
/*
|
||||||
|
* t2 = ~t0 & 0x110
|
||||||
* t0 = (t2 >> 2) | (t2 >> 3)
|
* t0 = (t2 >> 2) | (t2 >> 3)
|
||||||
*
|
*
|
||||||
* to fit on 8bit operands, changed in:
|
* to fit on 8bit operands, changed in:
|
||||||
|
@ -2090,8 +2119,10 @@ DISAS_INSN(movem)
|
||||||
/* pre-decrement is not allowed */
|
/* pre-decrement is not allowed */
|
||||||
goto do_addr_fault;
|
goto do_addr_fault;
|
||||||
}
|
}
|
||||||
/* We want a bare copy of the address reg, without any pre-decrement
|
/*
|
||||||
adjustment, as gen_lea would provide. */
|
* We want a bare copy of the address reg, without any pre-decrement
|
||||||
|
* adjustment, as gen_lea would provide.
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -2133,7 +2164,8 @@ DISAS_INSN(movem)
|
||||||
tcg_gen_sub_i32(tcg_ctx, addr, addr, incr);
|
tcg_gen_sub_i32(tcg_ctx, addr, addr, incr);
|
||||||
if (reg0 + 8 == i &&
|
if (reg0 + 8 == i &&
|
||||||
m68k_feature(s->env, M68K_FEATURE_EXT_FULL)) {
|
m68k_feature(s->env, M68K_FEATURE_EXT_FULL)) {
|
||||||
/* M68020+: if the addressing register is the
|
/*
|
||||||
|
* M68020+: if the addressing register is the
|
||||||
* register moved to memory, the value written
|
* register moved to memory, the value written
|
||||||
* is the initial value decremented by the size of
|
* is the initial value decremented by the size of
|
||||||
* the operation, regardless of how many actual
|
* the operation, regardless of how many actual
|
||||||
|
@ -2485,7 +2517,8 @@ DISAS_INSN(cas)
|
||||||
|
|
||||||
cmp = gen_extend(s, DREG(ext, 0), opsize, 1);
|
cmp = gen_extend(s, DREG(ext, 0), opsize, 1);
|
||||||
|
|
||||||
/* if <EA> == Dc then
|
/*
|
||||||
|
* if <EA> == Dc then
|
||||||
* <EA> = Du
|
* <EA> = Du
|
||||||
* Dc = <EA> (because <EA> == Dc)
|
* Dc = <EA> (because <EA> == Dc)
|
||||||
* else
|
* else
|
||||||
|
@ -2539,7 +2572,8 @@ DISAS_INSN(cas2w)
|
||||||
addr2 = DREG(ext2, 12);
|
addr2 = DREG(ext2, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if (R1) == Dc1 && (R2) == Dc2 then
|
/*
|
||||||
|
* if (R1) == Dc1 && (R2) == Dc2 then
|
||||||
* (R1) = Du1
|
* (R1) = Du1
|
||||||
* (R2) = Du2
|
* (R2) = Du2
|
||||||
* else
|
* else
|
||||||
|
@ -2590,7 +2624,8 @@ DISAS_INSN(cas2l)
|
||||||
addr2 = DREG(ext2, 12);
|
addr2 = DREG(ext2, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if (R1) == Dc1 && (R2) == Dc2 then
|
/*
|
||||||
|
* if (R1) == Dc1 && (R2) == Dc2 then
|
||||||
* (R1) = Du1
|
* (R1) = Du1
|
||||||
* (R2) = Du2
|
* (R2) = Du2
|
||||||
* else
|
* else
|
||||||
|
@ -2680,7 +2715,8 @@ DISAS_INSN(negx)
|
||||||
|
|
||||||
gen_flush_flags(s); /* compute old Z */
|
gen_flush_flags(s); /* compute old Z */
|
||||||
|
|
||||||
/* Perform substract with borrow.
|
/*
|
||||||
|
* Perform substract with borrow.
|
||||||
* (X, N) = -(src + X);
|
* (X, N) = -(src + X);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -2692,7 +2728,8 @@ DISAS_INSN(negx)
|
||||||
|
|
||||||
tcg_gen_andi_i32(tcg_ctx, QREG_CC_X, QREG_CC_X, 1);
|
tcg_gen_andi_i32(tcg_ctx, QREG_CC_X, QREG_CC_X, 1);
|
||||||
|
|
||||||
/* Compute signed-overflow for negation. The normal formula for
|
/*
|
||||||
|
* Compute signed-overflow for negation. The normal formula for
|
||||||
* subtraction is (res ^ src) & (src ^ dest), but with dest==0
|
* subtraction is (res ^ src) & (src ^ dest), but with dest==0
|
||||||
* this simplies to res & src.
|
* this simplies to res & src.
|
||||||
*/
|
*/
|
||||||
|
@ -2942,8 +2979,10 @@ DISAS_INSN(mull)
|
||||||
|
|
||||||
set_cc_op(s, CC_OP_FLAGS);
|
set_cc_op(s, CC_OP_FLAGS);
|
||||||
} else {
|
} else {
|
||||||
/* The upper 32 bits of the product are discarded, so
|
/*
|
||||||
muls.l and mulu.l are functionally equivalent. */
|
* The upper 32 bits of the product are discarded, so
|
||||||
|
* muls.l and mulu.l are functionally equivalent.
|
||||||
|
*/
|
||||||
tcg_gen_mul_i32(tcg_ctx, DREG(ext, 12), src1, DREG(ext, 12));
|
tcg_gen_mul_i32(tcg_ctx, DREG(ext, 12), src1, DREG(ext, 12));
|
||||||
gen_logic_cc(s, DREG(ext, 12), OS_LONG);
|
gen_logic_cc(s, DREG(ext, 12), OS_LONG);
|
||||||
}
|
}
|
||||||
|
@ -3043,8 +3082,10 @@ DISAS_INSN(jump)
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
TCGv tmp;
|
TCGv tmp;
|
||||||
|
|
||||||
/* Load the target address first to ensure correct exception
|
/*
|
||||||
behavior. */
|
* Load the target address first to ensure correct exception
|
||||||
|
* behavior.
|
||||||
|
*/
|
||||||
tmp = gen_lea(env, s, insn, OS_LONG);
|
tmp = gen_lea(env, s, insn, OS_LONG);
|
||||||
if (IS_NULL_QREG(tmp)) {
|
if (IS_NULL_QREG(tmp)) {
|
||||||
gen_addr_fault(s);
|
gen_addr_fault(s);
|
||||||
|
@ -3082,8 +3123,10 @@ DISAS_INSN(addsubq)
|
||||||
dest = tcg_temp_new(tcg_ctx);
|
dest = tcg_temp_new(tcg_ctx);
|
||||||
tcg_gen_mov_i32(tcg_ctx, dest, src);
|
tcg_gen_mov_i32(tcg_ctx, dest, src);
|
||||||
if ((insn & 0x38) == 0x08) {
|
if ((insn & 0x38) == 0x08) {
|
||||||
/* Don't update condition codes if the destination is an
|
/*
|
||||||
address register. */
|
* Don't update condition codes if the destination is an
|
||||||
|
* address register.
|
||||||
|
*/
|
||||||
if (insn & 0x0100) {
|
if (insn & 0x0100) {
|
||||||
tcg_gen_sub_i32(tcg_ctx, dest, dest, val);
|
tcg_gen_sub_i32(tcg_ctx, dest, dest, val);
|
||||||
} else {
|
} else {
|
||||||
|
@ -3228,7 +3271,8 @@ static inline void gen_subx(DisasContext *s, TCGv src, TCGv dest, int opsize)
|
||||||
|
|
||||||
gen_flush_flags(s); /* compute old Z */
|
gen_flush_flags(s); /* compute old Z */
|
||||||
|
|
||||||
/* Perform substract with borrow.
|
/*
|
||||||
|
* Perform substract with borrow.
|
||||||
* (X, N) = dest - (src + X);
|
* (X, N) = dest - (src + X);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -3459,7 +3503,8 @@ static inline void gen_addx(DisasContext *s, TCGv src, TCGv dest, int opsize)
|
||||||
|
|
||||||
gen_flush_flags(s); /* compute old Z */
|
gen_flush_flags(s); /* compute old Z */
|
||||||
|
|
||||||
/* Perform addition with carry.
|
/*
|
||||||
|
* Perform addition with carry.
|
||||||
* (X, N) = src + dest + X;
|
* (X, N) = src + dest + X;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -3552,9 +3597,11 @@ static inline void shift_im(DisasContext *s, uint16_t insn, int opsize)
|
||||||
tcg_gen_shri_i32(tcg_ctx, QREG_CC_C, reg, bits - count);
|
tcg_gen_shri_i32(tcg_ctx, QREG_CC_C, reg, bits - count);
|
||||||
tcg_gen_shli_i32(tcg_ctx, QREG_CC_N, reg, count);
|
tcg_gen_shli_i32(tcg_ctx, QREG_CC_N, reg, count);
|
||||||
|
|
||||||
/* Note that ColdFire always clears V (done above),
|
/*
|
||||||
while M68000 sets if the most significant bit is changed at
|
* Note that ColdFire always clears V (done above),
|
||||||
any time during the shift operation */
|
* while M68000 sets if the most significant bit is changed at
|
||||||
|
* any time during the shift operation.
|
||||||
|
*/
|
||||||
if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
|
if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
|
||||||
/* if shift count >= bits, V is (reg != 0) */
|
/* if shift count >= bits, V is (reg != 0) */
|
||||||
if (count >= bits) {
|
if (count >= bits) {
|
||||||
|
@ -3606,9 +3653,11 @@ static inline void shift_reg(DisasContext *s, uint16_t insn, int opsize)
|
||||||
s64 = tcg_temp_new_i64(tcg_ctx);
|
s64 = tcg_temp_new_i64(tcg_ctx);
|
||||||
s32 = tcg_temp_new(tcg_ctx);
|
s32 = tcg_temp_new(tcg_ctx);
|
||||||
|
|
||||||
/* Note that m68k truncates the shift count modulo 64, not 32.
|
/*
|
||||||
In addition, a 64-bit shift makes it easy to find "the last
|
* Note that m68k truncates the shift count modulo 64, not 32.
|
||||||
bit shifted out", for the carry flag. */
|
* In addition, a 64-bit shift makes it easy to find "the last
|
||||||
|
* bit shifted out", for the carry flag.
|
||||||
|
*/
|
||||||
tcg_gen_andi_i32(tcg_ctx, s32, DREG(insn, 9), 63);
|
tcg_gen_andi_i32(tcg_ctx, s32, DREG(insn, 9), 63);
|
||||||
tcg_gen_extu_i32_i64(tcg_ctx, s64, s32);
|
tcg_gen_extu_i32_i64(tcg_ctx, s64, s32);
|
||||||
tcg_gen_extu_i32_i64(tcg_ctx, t64, reg);
|
tcg_gen_extu_i32_i64(tcg_ctx, t64, reg);
|
||||||
|
@ -3635,7 +3684,8 @@ static inline void shift_reg(DisasContext *s, uint16_t insn, int opsize)
|
||||||
tcg_gen_movcond_i32(tcg_ctx, TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V,
|
tcg_gen_movcond_i32(tcg_ctx, TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V,
|
||||||
QREG_CC_C, QREG_CC_X);
|
QREG_CC_C, QREG_CC_X);
|
||||||
|
|
||||||
/* M68000 sets V if the most significant bit is changed at
|
/*
|
||||||
|
* M68000 sets V if the most significant bit is changed at
|
||||||
* any time during the shift operation. Do this via creating
|
* any time during the shift operation. Do this via creating
|
||||||
* an extension of the sign bit, comparing, and discarding
|
* an extension of the sign bit, comparing, and discarding
|
||||||
* the bits below the sign bit. I.e.
|
* the bits below the sign bit. I.e.
|
||||||
|
@ -3738,9 +3788,11 @@ DISAS_INSN(shift_mem)
|
||||||
tcg_gen_shri_i32(tcg_ctx, QREG_CC_C, src, 15);
|
tcg_gen_shri_i32(tcg_ctx, QREG_CC_C, src, 15);
|
||||||
tcg_gen_shli_i32(tcg_ctx, QREG_CC_N, src, 1);
|
tcg_gen_shli_i32(tcg_ctx, QREG_CC_N, src, 1);
|
||||||
|
|
||||||
/* Note that ColdFire always clears V,
|
/*
|
||||||
while M68000 sets if the most significant bit is changed at
|
* Note that ColdFire always clears V,
|
||||||
any time during the shift operation */
|
* while M68000 sets if the most significant bit is changed at
|
||||||
|
* any time during the shift operation
|
||||||
|
*/
|
||||||
if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
|
if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
|
||||||
src = gen_extend(s, src, OS_WORD, 1);
|
src = gen_extend(s, src, OS_WORD, 1);
|
||||||
tcg_gen_xor_i32(tcg_ctx, QREG_CC_V, QREG_CC_N, src);
|
tcg_gen_xor_i32(tcg_ctx, QREG_CC_V, QREG_CC_N, src);
|
||||||
|
@ -4172,9 +4224,11 @@ DISAS_INSN(bfext_reg)
|
||||||
TCGv tmp = tcg_temp_new(tcg_ctx);
|
TCGv tmp = tcg_temp_new(tcg_ctx);
|
||||||
TCGv shift;
|
TCGv shift;
|
||||||
|
|
||||||
/* In general, we're going to rotate the field so that it's at the
|
/*
|
||||||
top of the word and then right-shift by the complement of the
|
* In general, we're going to rotate the field so that it's at the
|
||||||
width to extend the field. */
|
* top of the word and then right-shift by the complement of the
|
||||||
|
* width to extend the field.
|
||||||
|
*/
|
||||||
if (ext & 0x20) {
|
if (ext & 0x20) {
|
||||||
/* Variable width. */
|
/* Variable width. */
|
||||||
if (ext & 0x800) {
|
if (ext & 0x800) {
|
||||||
|
@ -4204,8 +4258,10 @@ DISAS_INSN(bfext_reg)
|
||||||
src = tmp;
|
src = tmp;
|
||||||
pos = 32 - len;
|
pos = 32 - len;
|
||||||
} else {
|
} else {
|
||||||
/* Immediate offset. If the field doesn't wrap around the
|
/*
|
||||||
end of the word, rely on (s)extract completely. */
|
* Immediate offset. If the field doesn't wrap around the
|
||||||
|
* end of the word, rely on (s)extract completely.
|
||||||
|
*/
|
||||||
if (pos < 0) {
|
if (pos < 0) {
|
||||||
tcg_gen_rotli_i32(tcg_ctx, tmp, src, ofs);
|
tcg_gen_rotli_i32(tcg_ctx, tmp, src, ofs);
|
||||||
src = tmp;
|
src = tmp;
|
||||||
|
@ -5095,7 +5151,8 @@ static void gen_op_fmove_fcr(CPUM68KState *env, DisasContext *s,
|
||||||
addr = tcg_temp_new(tcg_ctx);
|
addr = tcg_temp_new(tcg_ctx);
|
||||||
tcg_gen_mov_i32(tcg_ctx, addr, tmp);
|
tcg_gen_mov_i32(tcg_ctx, addr, tmp);
|
||||||
|
|
||||||
/* mask:
|
/*
|
||||||
|
* mask:
|
||||||
*
|
*
|
||||||
* 0b100 Floating-Point Control Register
|
* 0b100 Floating-Point Control Register
|
||||||
* 0b010 Floating-Point Status Register
|
* 0b010 Floating-Point Status Register
|
||||||
|
@ -5164,7 +5221,8 @@ static void gen_op_fmovem(CPUM68KState *env, DisasContext *s,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_load && (mode & 2) == 0) {
|
if (!is_load && (mode & 2) == 0) {
|
||||||
/* predecrement addressing mode
|
/*
|
||||||
|
* predecrement addressing mode
|
||||||
* only available to store register to memory
|
* only available to store register to memory
|
||||||
*/
|
*/
|
||||||
if (opsize == OS_EXTENDED) {
|
if (opsize == OS_EXTENDED) {
|
||||||
|
@ -5194,8 +5252,10 @@ static void gen_op_fmovem(CPUM68KState *env, DisasContext *s,
|
||||||
tcg_temp_free(tcg_ctx, tmp);
|
tcg_temp_free(tcg_ctx, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ??? FP exceptions are not implemented. Most exceptions are deferred until
|
/*
|
||||||
immediately before the next FP instruction is executed. */
|
* ??? FP exceptions are not implemented. Most exceptions are deferred until
|
||||||
|
* immediately before the next FP instruction is executed.
|
||||||
|
*/
|
||||||
DISAS_INSN(fpu)
|
DISAS_INSN(fpu)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
@ -5731,8 +5791,10 @@ DISAS_INSN(mac)
|
||||||
tmp = gen_lea(env, s, insn, OS_LONG);
|
tmp = gen_lea(env, s, insn, OS_LONG);
|
||||||
addr = tcg_temp_new(tcg_ctx);
|
addr = tcg_temp_new(tcg_ctx);
|
||||||
tcg_gen_and_i32(tcg_ctx, addr, tmp, tcg_ctx->QREG_MAC_MASK);
|
tcg_gen_and_i32(tcg_ctx, addr, tmp, tcg_ctx->QREG_MAC_MASK);
|
||||||
/* Load the value now to ensure correct exception behavior.
|
/*
|
||||||
Perform writeback after reading the MAC inputs. */
|
* Load the value now to ensure correct exception behavior.
|
||||||
|
* Perform writeback after reading the MAC inputs.
|
||||||
|
*/
|
||||||
loadval = gen_load(s, OS_LONG, addr, 0, IS_USER(s));
|
loadval = gen_load(s, OS_LONG, addr, 0, IS_USER(s));
|
||||||
|
|
||||||
acc ^= 1;
|
acc ^= 1;
|
||||||
|
@ -5853,8 +5915,10 @@ DISAS_INSN(mac)
|
||||||
TCGv rw;
|
TCGv rw;
|
||||||
rw = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
|
rw = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
|
||||||
tcg_gen_mov_i32(tcg_ctx, rw, loadval);
|
tcg_gen_mov_i32(tcg_ctx, rw, loadval);
|
||||||
/* FIXME: Should address writeback happen with the masked or
|
/*
|
||||||
unmasked value? */
|
* FIXME: Should address writeback happen with the masked or
|
||||||
|
* unmasked value?
|
||||||
|
*/
|
||||||
switch ((insn >> 3) & 7) {
|
switch ((insn >> 3) & 7) {
|
||||||
case 3: /* Post-increment. */
|
case 3: /* Post-increment. */
|
||||||
tcg_gen_addi_i32(tcg_ctx, AREG(insn, 0), addr, 4);
|
tcg_gen_addi_i32(tcg_ctx, AREG(insn, 0), addr, 4);
|
||||||
|
@ -6012,8 +6076,10 @@ register_opcode(TCGContext *tcg_ctx, disas_proc proc, uint16_t opcode, uint16_t
|
||||||
opcode, mask);
|
opcode, mask);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
/* This could probably be cleverer. For now just optimize the case where
|
/*
|
||||||
the top bits are known. */
|
* This could probably be cleverer. For now just optimize the case where
|
||||||
|
* the top bits are known.
|
||||||
|
*/
|
||||||
/* Find the first zero bit in the mask. */
|
/* Find the first zero bit in the mask. */
|
||||||
i = 0x8000;
|
i = 0x8000;
|
||||||
while ((i & mask) != 0)
|
while ((i & mask) != 0)
|
||||||
|
@ -6032,19 +6098,24 @@ register_opcode(TCGContext *tcg_ctx, disas_proc proc, uint16_t opcode, uint16_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register m68k opcode handlers. Order is important.
|
/*
|
||||||
Later insn override earlier ones. */
|
* Register m68k opcode handlers. Order is important.
|
||||||
|
* Later insn override earlier ones.
|
||||||
|
*/
|
||||||
void register_m68k_insns (CPUM68KState *env)
|
void register_m68k_insns (CPUM68KState *env)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
||||||
|
|
||||||
/* Build the opcode table only once to avoid
|
/*
|
||||||
multithreading issues. */
|
* Build the opcode table only once to avoid
|
||||||
|
* multithreading issues.
|
||||||
|
*/
|
||||||
if (tcg_ctx->opcode_table[0] != NULL) {
|
if (tcg_ctx->opcode_table[0] != NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* use BASE() for instruction available
|
/*
|
||||||
|
* use BASE() for instruction available
|
||||||
* for CF_ISA_A and M68000.
|
* for CF_ISA_A and M68000.
|
||||||
*/
|
*/
|
||||||
#define BASE(name, opcode, mask) \
|
#define BASE(name, opcode, mask) \
|
||||||
|
@ -6325,10 +6396,12 @@ static bool m68k_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
|
||||||
DisasContext *dc = container_of(dcbase, DisasContext, base);
|
DisasContext *dc = container_of(dcbase, DisasContext, base);
|
||||||
|
|
||||||
gen_exception(dc, dc->base.pc_next, EXCP_DEBUG);
|
gen_exception(dc, dc->base.pc_next, EXCP_DEBUG);
|
||||||
/* The address covered by the breakpoint must be included in
|
/*
|
||||||
[tb->pc, tb->pc + tb->size) in order to for it to be
|
* The address covered by the breakpoint must be included in
|
||||||
properly cleared -- thus we increment the PC here so that
|
* [tb->pc, tb->pc + tb->size) in order to for it to be
|
||||||
the logic setting tb->size below does the right thing. */
|
* properly cleared -- thus we increment the PC here so that
|
||||||
|
* the logic setting tb->size below does the right thing.
|
||||||
|
*/
|
||||||
dc->base.pc_next += 2;
|
dc->base.pc_next += 2;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -6361,7 +6434,8 @@ static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dc->base.is_jmp == DISAS_NEXT) {
|
if (dc->base.is_jmp == DISAS_NEXT) {
|
||||||
/* Stop translation when the next insn might touch a new page.
|
/*
|
||||||
|
* Stop translation when the next insn might touch a new page.
|
||||||
* This ensures that prefetch aborts at the right place.
|
* This ensures that prefetch aborts at the right place.
|
||||||
*
|
*
|
||||||
* We cannot determine the size of the next insn without
|
* We cannot determine the size of the next insn without
|
||||||
|
@ -6405,8 +6479,10 @@ static void m68k_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
tcg_gen_lookup_and_goto_ptr(tcg_ctx);
|
tcg_gen_lookup_and_goto_ptr(tcg_ctx);
|
||||||
break;
|
break;
|
||||||
case DISAS_EXIT:
|
case DISAS_EXIT:
|
||||||
/* We updated CC_OP and PC in gen_exit_tb, but also modified
|
/*
|
||||||
other state that may require returning to the main loop. */
|
* We updated CC_OP and PC in gen_exit_tb, but also modified
|
||||||
|
* other state that may require returning to the main loop.
|
||||||
|
*/
|
||||||
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
|
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in a new issue