mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/vivier/tags/m68k-next-pull-request' into staging
remove m68k simulator syscall interface Fix comments format Fix gdbstub # gpg: Signature made Wed 26 Jun 2019 17:20:41 BST # gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C # gpg: issuer "laurent@vivier.eu" # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full] # gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full] # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full] # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier/tags/m68k-next-pull-request: linux-user/m68k: remove simulator syscall interface m68k comments break patch submission due to being incorrectly formatted The m68k gdbstub SR reg request doesnt include Condition-Codes Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -8,4 +8,3 @@ obj-$(TARGET_I386) += vm86.o
|
||||
obj-$(TARGET_ARM) += arm/nwfpe/
|
||||
obj-$(TARGET_ARM) += arm/semihost.o
|
||||
obj-$(TARGET_AARCH64) += arm/semihost.o
|
||||
obj-$(TARGET_M68K) += m68k-sim.o
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
* m68k simulator syscall interface
|
||||
*
|
||||
* Copyright (c) 2005 CodeSourcery, LLC. Written by Paul Brook.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "qemu.h"
|
||||
|
||||
#define SYS_EXIT 1
|
||||
#define SYS_READ 3
|
||||
#define SYS_WRITE 4
|
||||
#define SYS_OPEN 5
|
||||
#define SYS_CLOSE 6
|
||||
#define SYS_BRK 17
|
||||
#define SYS_FSTAT 28
|
||||
#define SYS_ISATTY 29
|
||||
#define SYS_LSEEK 199
|
||||
|
||||
struct m68k_sim_stat {
|
||||
uint16_t sim_st_dev;
|
||||
uint16_t sim_st_ino;
|
||||
uint32_t sim_st_mode;
|
||||
uint16_t sim_st_nlink;
|
||||
uint16_t sim_st_uid;
|
||||
uint16_t sim_st_gid;
|
||||
uint16_t sim_st_rdev;
|
||||
uint32_t sim_st_size;
|
||||
uint32_t sim_st_atime;
|
||||
uint32_t sim_st_mtime;
|
||||
uint32_t sim_st_ctime;
|
||||
uint32_t sim_st_blksize;
|
||||
uint32_t sim_st_blocks;
|
||||
};
|
||||
|
||||
static inline uint32_t check_err(CPUM68KState *env, uint32_t code)
|
||||
{
|
||||
env->dregs[0] = code;
|
||||
if (code == (uint32_t)-1) {
|
||||
env->dregs[1] = errno;
|
||||
} else {
|
||||
env->dregs[1] = 0;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
#define SIM_O_APPEND 0x0008
|
||||
#define SIM_O_CREAT 0x0200
|
||||
#define SIM_O_TRUNC 0x0400
|
||||
#define SIM_O_EXCL 0x0800
|
||||
#define SIM_O_NONBLOCK 0x4000
|
||||
#define SIM_O_NOCTTY 0x8000
|
||||
#define SIM_O_SYNC 0x2000
|
||||
|
||||
static int translate_openflags(int flags)
|
||||
{
|
||||
int hf;
|
||||
|
||||
switch (flags & 3) {
|
||||
case 0: hf = O_RDONLY; break;
|
||||
case 1: hf = O_WRONLY; break;
|
||||
case 2: hf = O_RDWR; break;
|
||||
default: hf = O_RDWR; break;
|
||||
}
|
||||
|
||||
if (flags & SIM_O_APPEND) hf |= O_APPEND;
|
||||
if (flags & SIM_O_CREAT) hf |= O_CREAT;
|
||||
if (flags & SIM_O_TRUNC) hf |= O_TRUNC;
|
||||
if (flags & SIM_O_EXCL) hf |= O_EXCL;
|
||||
if (flags & SIM_O_NONBLOCK) hf |= O_NONBLOCK;
|
||||
if (flags & SIM_O_NOCTTY) hf |= O_NOCTTY;
|
||||
if (flags & SIM_O_SYNC) hf |= O_SYNC;
|
||||
|
||||
return hf;
|
||||
}
|
||||
|
||||
#define ARG(x) tswap32(args[x])
|
||||
void do_m68k_simcall(CPUM68KState *env, int nr)
|
||||
{
|
||||
uint32_t *args;
|
||||
|
||||
args = (uint32_t *)(unsigned long)(env->aregs[7] + 4);
|
||||
switch (nr) {
|
||||
case SYS_EXIT:
|
||||
exit(ARG(0));
|
||||
case SYS_READ:
|
||||
check_err(env, read(ARG(0), (void *)(unsigned long)ARG(1), ARG(2)));
|
||||
break;
|
||||
case SYS_WRITE:
|
||||
check_err(env, write(ARG(0), (void *)(unsigned long)ARG(1), ARG(2)));
|
||||
break;
|
||||
case SYS_OPEN:
|
||||
check_err(env, open((char *)(unsigned long)ARG(0),
|
||||
translate_openflags(ARG(1)), ARG(2)));
|
||||
break;
|
||||
case SYS_CLOSE:
|
||||
{
|
||||
/* Ignore attempts to close stdin/out/err. */
|
||||
int fd = ARG(0);
|
||||
if (fd > 2)
|
||||
check_err(env, close(fd));
|
||||
else
|
||||
check_err(env, 0);
|
||||
break;
|
||||
}
|
||||
case SYS_BRK:
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
ret = do_brk((abi_ulong)ARG(0));
|
||||
if (ret == -ENOMEM)
|
||||
ret = -1;
|
||||
check_err(env, ret);
|
||||
}
|
||||
break;
|
||||
case SYS_FSTAT:
|
||||
{
|
||||
struct stat s;
|
||||
int rc;
|
||||
struct m68k_sim_stat *p;
|
||||
rc = check_err(env, fstat(ARG(0), &s));
|
||||
if (rc == 0) {
|
||||
p = (struct m68k_sim_stat *)(unsigned long)ARG(1);
|
||||
p->sim_st_dev = tswap16(s.st_dev);
|
||||
p->sim_st_ino = tswap16(s.st_ino);
|
||||
p->sim_st_mode = tswap32(s.st_mode);
|
||||
p->sim_st_nlink = tswap16(s.st_nlink);
|
||||
p->sim_st_uid = tswap16(s.st_uid);
|
||||
p->sim_st_gid = tswap16(s.st_gid);
|
||||
p->sim_st_rdev = tswap16(s.st_rdev);
|
||||
p->sim_st_size = tswap32(s.st_size);
|
||||
p->sim_st_atime = tswap32(s.st_atime);
|
||||
p->sim_st_mtime = tswap32(s.st_mtime);
|
||||
p->sim_st_ctime = tswap32(s.st_ctime);
|
||||
p->sim_st_blksize = tswap32(s.st_blksize);
|
||||
p->sim_st_blocks = tswap32(s.st_blocks);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SYS_ISATTY:
|
||||
check_err(env, isatty(ARG(0)));
|
||||
break;
|
||||
case SYS_LSEEK:
|
||||
check_err(env, lseek(ARG(0), (int32_t)ARG(1), ARG(2)));
|
||||
break;
|
||||
default:
|
||||
cpu_abort(env_cpu(env), "Unsupported m68k sim syscall %d\n", nr);
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,6 @@ void cpu_loop(CPUM68KState *env)
|
||||
int trapnr;
|
||||
unsigned int n;
|
||||
target_siginfo_t info;
|
||||
TaskState *ts = cs->opaque;
|
||||
|
||||
for(;;) {
|
||||
cpu_exec_start(cs);
|
||||
@@ -37,26 +36,14 @@ void cpu_loop(CPUM68KState *env)
|
||||
process_queued_cpu_work(cs);
|
||||
|
||||
switch(trapnr) {
|
||||
case EXCP_ILLEGAL:
|
||||
{
|
||||
if (ts->sim_syscalls) {
|
||||
uint16_t nr;
|
||||
get_user_u16(nr, env->pc + 2);
|
||||
env->pc += 4;
|
||||
do_m68k_simcall(env, nr);
|
||||
} else {
|
||||
goto do_sigill;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EXCP_HALT_INSN:
|
||||
/* Semihosing syscall. */
|
||||
env->pc += 4;
|
||||
do_m68k_semihosting(env, env->dregs[0]);
|
||||
break;
|
||||
case EXCP_ILLEGAL:
|
||||
case EXCP_LINEA:
|
||||
case EXCP_LINEF:
|
||||
do_sigill:
|
||||
info.si_signo = TARGET_SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_ILL_ILLOPN;
|
||||
@@ -80,7 +67,6 @@ void cpu_loop(CPUM68KState *env)
|
||||
case EXCP_TRAP0:
|
||||
{
|
||||
abi_long ret;
|
||||
ts->sim_syscalls = 0;
|
||||
n = env->dregs[0];
|
||||
env->pc += 2;
|
||||
ret = do_syscall(env,
|
||||
@@ -154,7 +140,6 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
|
||||
env->aregs[7] = regs->usp;
|
||||
env->sr = regs->sr;
|
||||
|
||||
ts->sim_syscalls = 1;
|
||||
ts->stack_base = info->start_stack;
|
||||
ts->heap_base = info->brk;
|
||||
/* This will be filled in on the first SYS_HEAPINFO call. */
|
||||
|
||||
@@ -26,6 +26,4 @@ struct target_pt_regs {
|
||||
|
||||
#define TARGET_WANT_OLD_SYS_SELECT
|
||||
|
||||
void do_m68k_simcall(CPUM68KState *, int);
|
||||
|
||||
#endif /* M68K_TARGET_SYSCALL_H */
|
||||
|
||||
@@ -116,7 +116,6 @@ typedef struct TaskState {
|
||||
#endif
|
||||
abi_ulong child_tidptr;
|
||||
#ifdef TARGET_M68K
|
||||
int sim_syscalls;
|
||||
abi_ulong tp_value;
|
||||
#endif
|
||||
#if defined(TARGET_ARM) || defined(TARGET_M68K)
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#define M68K_CPU_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(M68kCPUClass, (obj), TYPE_M68K_CPU)
|
||||
|
||||
/**
|
||||
/*
|
||||
* M68kCPUClass:
|
||||
* @parent_realize: The parent class' realize handler.
|
||||
* @parent_reset: The parent class' reset handler.
|
||||
|
||||
+4
-2
@@ -203,8 +203,10 @@ static void any_cpu_initfn(Object *obj)
|
||||
m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
|
||||
m68k_set_feature(env, M68K_FEATURE_BRAL);
|
||||
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_B);
|
||||
m68k_set_feature(env, M68K_FEATURE_USP);
|
||||
|
||||
+18
-11
@@ -106,9 +106,11 @@ typedef struct CPUM68KState {
|
||||
float_status fp_status;
|
||||
|
||||
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
|
||||
rearrange/extend this when changing modes. */
|
||||
/*
|
||||
* 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
|
||||
* rearrange/extend this when changing modes.
|
||||
*/
|
||||
uint64_t macc[4];
|
||||
uint32_t macsr;
|
||||
uint32_t mac_mask;
|
||||
@@ -146,7 +148,7 @@ typedef struct CPUM68KState {
|
||||
uint32_t features;
|
||||
} CPUM68KState;
|
||||
|
||||
/**
|
||||
/*
|
||||
* M68kCPU:
|
||||
* @env: #CPUM68KState
|
||||
*
|
||||
@@ -171,9 +173,11 @@ int m68k_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
|
||||
void m68k_tcg_init(void);
|
||||
void m68k_cpu_init_gdb(M68kCPU *cpu);
|
||||
/* you can call this signal handler from your SIGBUS and SIGSEGV
|
||||
signal handlers to inform the virtual CPU of exceptions. non zero
|
||||
is returned if the signal was handled by the virtual CPU. */
|
||||
/*
|
||||
* you can call this signal handler from your SIGBUS and SIGSEGV
|
||||
* 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,
|
||||
void *puc);
|
||||
uint32_t cpu_m68k_get_ccr(CPUM68KState *env);
|
||||
@@ -182,7 +186,8 @@ void cpu_m68k_set_sr(CPUM68KState *env, uint32_t);
|
||||
void cpu_m68k_set_fpcr(CPUM68KState *env, uint32_t val);
|
||||
|
||||
|
||||
/* Instead of computing the condition codes after each m68k instruction,
|
||||
/*
|
||||
* Instead of computing the condition codes after each m68k instruction,
|
||||
* QEMU just stores one operand (called CC_SRC), the result
|
||||
* (called CC_DEST) and the type of operation (called CC_OP). When the
|
||||
* condition codes are needed, the condition codes can be calculated
|
||||
@@ -447,9 +452,11 @@ void m68k_switch_sp(CPUM68KState *env);
|
||||
|
||||
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
|
||||
ISA revisions mentioned. */
|
||||
/*
|
||||
* There are 4 ColdFire core ISA revisions: A, A+, B and C.
|
||||
* Each feature covers the subset of instructions common to the
|
||||
* ISA revisions mentioned.
|
||||
*/
|
||||
|
||||
enum m68k_features {
|
||||
M68K_FEATURE_M68000,
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
#include "exec/cpu_ldst.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)
|
||||
*/
|
||||
|
||||
@@ -611,7 +612,8 @@ void HELPER(fcos)(CPUM68KState *env, FPReg *res, FPReg *val)
|
||||
void HELPER(fsincos)(CPUM68KState *env, FPReg *res0, FPReg *res1, FPReg *val)
|
||||
{
|
||||
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
|
||||
* result is discarded.
|
||||
*/
|
||||
|
||||
@@ -35,13 +35,16 @@ int m68k_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
} else {
|
||||
switch (n) {
|
||||
case 16:
|
||||
return gdb_get_reg32(mem_buf, env->sr);
|
||||
/* SR is made of SR+CCR, CCR is many 1bit flags so uses helper */
|
||||
return gdb_get_reg32(mem_buf, env->sr | cpu_m68k_get_ccr(env));
|
||||
case 17:
|
||||
return gdb_get_reg32(mem_buf, env->pc);
|
||||
}
|
||||
}
|
||||
/* FP registers not included here because they vary between
|
||||
ColdFire and m68k. Use XML bits for these. */
|
||||
/*
|
||||
* FP registers not included here because they vary between
|
||||
* ColdFire and m68k. Use XML bits for these.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+10
-6
@@ -965,9 +965,11 @@ void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
/*
|
||||
* 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)(CPUM68KState *env, uint32_t dest, uint32_t src)
|
||||
{
|
||||
uint32_t mask;
|
||||
@@ -1047,9 +1049,11 @@ void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
|
||||
if (env->macsr & MACSR_V) {
|
||||
env->macsr |= MACSR_PAV0 << acc;
|
||||
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
|
||||
say. */
|
||||
/*
|
||||
* The result is saturated to 32 bits, despite overflow occurring
|
||||
* at 48 bits. Seems weird, but that's what the hardware docs
|
||||
* say.
|
||||
*/
|
||||
result = (result >> 63) ^ 0x7fffffff;
|
||||
}
|
||||
}
|
||||
|
||||
+16
-8
@@ -130,7 +130,8 @@ static void m68k_semi_return_u32(CPUM68KState *env, uint32_t ret, uint32_t err)
|
||||
target_ulong args = env->dregs[1];
|
||||
if (put_user_u32(ret, args) ||
|
||||
put_user_u32(err, args + 4)) {
|
||||
/* The m68k semihosting ABI does not provide any way to report this
|
||||
/*
|
||||
* The m68k semihosting ABI does not provide any way to report this
|
||||
* error to the guest, so the best we can do is log it in qemu.
|
||||
* It is always a guest error not to pass us a valid argument block.
|
||||
*/
|
||||
@@ -159,8 +160,10 @@ static void m68k_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
|
||||
CPUM68KState *env = &cpu->env;
|
||||
|
||||
if (m68k_semi_is_fseek) {
|
||||
/* FIXME: We've already lost the high bits of the fseek
|
||||
return value. */
|
||||
/*
|
||||
* FIXME: We've already lost the high bits of the fseek
|
||||
* return value.
|
||||
*/
|
||||
m68k_semi_return_u64(env, ret, err);
|
||||
m68k_semi_is_fseek = 0;
|
||||
} else {
|
||||
@@ -168,7 +171,8 @@ static void m68k_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the input value from the argument block; fail the semihosting
|
||||
/*
|
||||
* Read the input value from the argument block; fail the semihosting
|
||||
* call if the memory read fails.
|
||||
*/
|
||||
#define GET_ARG(n) do { \
|
||||
@@ -440,14 +444,18 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||
}
|
||||
ts->heap_limit = base + size;
|
||||
}
|
||||
/* This call may happen before we have writable memory, so return
|
||||
values directly in registers. */
|
||||
/*
|
||||
* This call may happen before we have writable memory, so return
|
||||
* values directly in registers.
|
||||
*/
|
||||
env->dregs[1] = ts->heap_limit;
|
||||
env->aregs[7] = ts->stack_base;
|
||||
}
|
||||
#else
|
||||
/* FIXME: This is wrong for boards where RAM does not start at
|
||||
address zero. */
|
||||
/*
|
||||
* FIXME: This is wrong for boards where RAM does not start at
|
||||
* address zero.
|
||||
*/
|
||||
env->dregs[1] = ram_size;
|
||||
env->aregs[7] = ram_size;
|
||||
#endif
|
||||
|
||||
+37
-21
@@ -494,10 +494,12 @@ bool m68k_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
|
||||
if (interrupt_request & CPU_INTERRUPT_HARD
|
||||
&& ((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
|
||||
this, so we provide/save the vector when the interrupt is
|
||||
first signalled. */
|
||||
/*
|
||||
* Real hardware gets the interrupt vector via an IACK cycle
|
||||
* at this point. Current emulated hardware doesn't rely on
|
||||
* this, so we provide/save the vector when the interrupt is
|
||||
* first signalled.
|
||||
*/
|
||||
cs->exception_index = env->pending_vector;
|
||||
do_interrupt_m68k_hardirq(env);
|
||||
return true;
|
||||
@@ -537,7 +539,8 @@ void HELPER(divuw)(CPUM68KState *env, int destr, uint32_t den)
|
||||
env->cc_c = 0; /* always cleared, even if overflow */
|
||||
if (quot > 0xffff) {
|
||||
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"
|
||||
*/
|
||||
env->cc_z = 1;
|
||||
@@ -564,7 +567,8 @@ void HELPER(divsw)(CPUM68KState *env, int destr, int32_t den)
|
||||
if (quot != (int16_t)quot) {
|
||||
env->cc_v = -1;
|
||||
/* 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"
|
||||
*/
|
||||
env->cc_z = 1;
|
||||
@@ -647,7 +651,8 @@ void HELPER(divull)(CPUM68KState *env, int numr, int regr, uint32_t den)
|
||||
env->cc_c = 0; /* always cleared, even if overflow */
|
||||
if (quot > 0xffffffffULL) {
|
||||
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"
|
||||
*/
|
||||
env->cc_z = 1;
|
||||
@@ -681,7 +686,8 @@ void HELPER(divsll)(CPUM68KState *env, int numr, int regr, int32_t den)
|
||||
env->cc_c = 0; /* always cleared, even if overflow */
|
||||
if (quot != (int32_t)quot) {
|
||||
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"
|
||||
*/
|
||||
env->cc_z = 1;
|
||||
@@ -838,14 +844,18 @@ static struct bf_data bf_prep(uint32_t addr, int32_t ofs, uint32_t len)
|
||||
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;
|
||||
|
||||
/* 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
|
||||
that we can use the next power of two sized load without crossing a
|
||||
page boundary, unless the field itself crosses the boundary. */
|
||||
/*
|
||||
* 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
|
||||
* 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) {
|
||||
case 0:
|
||||
bofs += 56;
|
||||
@@ -937,8 +947,10 @@ uint64_t HELPER(bfextu_mem)(CPUM68KState *env, uint32_t addr,
|
||||
struct bf_data d = bf_prep(addr, ofs, len);
|
||||
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 >>= 64 - d.len;
|
||||
data |= data << (64 - d.len);
|
||||
@@ -1016,15 +1028,18 @@ uint64_t HELPER(bfffo_mem)(CPUM68KState *env, uint32_t addr,
|
||||
uint64_t n = (data & mask) << d.bofs;
|
||||
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
|
||||
is already zero. */
|
||||
/*
|
||||
* Return FFO in the low word and N in the high word.
|
||||
* Note that because of MASK and the shift, the low word
|
||||
* is already zero.
|
||||
*/
|
||||
return n | ffo;
|
||||
}
|
||||
|
||||
void HELPER(chk)(CPUM68KState *env, int32_t val, int32_t ub)
|
||||
{
|
||||
/* From the specs:
|
||||
/*
|
||||
* From the specs:
|
||||
* X: Not affected, C,V,Z: Undefined,
|
||||
* N: Set if val < 0; cleared if val > ub, undefined otherwise
|
||||
* We implement here values found from a real MC68040:
|
||||
@@ -1054,7 +1069,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)
|
||||
{
|
||||
/* From the specs:
|
||||
/*
|
||||
* From the specs:
|
||||
* X: Not affected, N,V: Undefined,
|
||||
* Z: Set if val is equal to lb or ub
|
||||
* C: Set if val < lb or val > ub, cleared otherwise
|
||||
|
||||
+94
-87
@@ -14,7 +14,8 @@
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -41,10 +42,10 @@ static floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status)
|
||||
return a;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the modulo remainder of the extended double-precision floating-point
|
||||
| value `a' with respect to the corresponding value `b'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Returns the modulo remainder of the extended double-precision floating-point
|
||||
* value `a' with respect to the corresponding value `b'.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the mantissa of the extended double-precision floating-point
|
||||
| value `a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Returns the mantissa of the extended double-precision floating-point
|
||||
* value `a'.
|
||||
*/
|
||||
|
||||
floatx80 floatx80_getman(floatx80 a, float_status *status)
|
||||
{
|
||||
@@ -158,10 +159,10 @@ floatx80 floatx80_getman(floatx80 a, float_status *status)
|
||||
0x3FFF, aSig, 0, status);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the exponent of the extended double-precision floating-point
|
||||
| value `a' as an extended double-precision value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Returns the exponent of the extended double-precision floating-point
|
||||
* value `a' as an extended double-precision value.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Scales extended double-precision floating-point value in operand `a' by
|
||||
| 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'.
|
||||
| The operation performed according to the IEC/IEEE Standard for Binary
|
||||
| Floating-Point Arithmetic.
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Scales extended double-precision floating-point value in operand `a' by
|
||||
* 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'.
|
||||
* The operation performed according to the IEC/IEEE Standard for Binary
|
||||
* Floating-Point Arithmetic.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Algorithms for transcendental functions supported by MC68881 and MC68882
|
||||
| mathematical coprocessors. The functions are derived from FPSP library.
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Algorithms for transcendental functions supported by MC68881 and MC68882
|
||||
* mathematical coprocessors. The functions are derived from FPSP library.
|
||||
*/
|
||||
|
||||
#define one_exp 0x3FFF
|
||||
#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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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)
|
||||
{
|
||||
@@ -723,9 +724,9 @@ floatx80 floatx80_log10(floatx80 a, float_status *status)
|
||||
return a;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Log base 2
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Log base 2
|
||||
*/
|
||||
|
||||
floatx80 floatx80_log2(floatx80 a, float_status *status)
|
||||
{
|
||||
@@ -790,9 +791,9 @@ floatx80 floatx80_log2(floatx80 a, float_status *status)
|
||||
return a;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| e to x
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* e to x
|
||||
*/
|
||||
|
||||
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 */
|
||||
m = n / 64; /* NOTE: this is really arithmetic right shift by 6 */
|
||||
if (n < 0 && j) {
|
||||
/* arithmetic right shift is division and
|
||||
/*
|
||||
* arithmetic right shift is division and
|
||||
* round towards minus infinity
|
||||
*/
|
||||
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)
|
||||
{
|
||||
@@ -1051,14 +1053,16 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
|
||||
j = n & 0x3F;
|
||||
l = n / 64; /* NOTE: this is really arithmetic right shift by 6 */
|
||||
if (n < 0 && j) {
|
||||
/* arithmetic right shift is division and
|
||||
/*
|
||||
* arithmetic right shift is division and
|
||||
* round towards minus infinity
|
||||
*/
|
||||
l--;
|
||||
}
|
||||
m = l / 2; /* NOTE: this is really arithmetic right shift by 1 */
|
||||
if (l < 0 && (l & 1)) {
|
||||
/* arithmetic right shift is division and
|
||||
/*
|
||||
* arithmetic right shift is division and
|
||||
* round towards minus infinity
|
||||
*/
|
||||
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)
|
||||
{
|
||||
@@ -1200,14 +1204,16 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
|
||||
j = n & 0x3F;
|
||||
l = n / 64; /* NOTE: this is really arithmetic right shift by 6 */
|
||||
if (n < 0 && j) {
|
||||
/* arithmetic right shift is division and
|
||||
/*
|
||||
* arithmetic right shift is division and
|
||||
* round towards minus infinity
|
||||
*/
|
||||
l--;
|
||||
}
|
||||
m = l / 2; /* NOTE: this is really arithmetic right shift by 1 */
|
||||
if (l < 0 && (l & 1)) {
|
||||
/* arithmetic right shift is division and
|
||||
/*
|
||||
* arithmetic right shift is division and
|
||||
* round towards minus infinity
|
||||
*/
|
||||
m--;
|
||||
@@ -1274,9 +1280,9 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Tangent
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Tangent
|
||||
*/
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -1723,9 +1729,9 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Cosine
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Cosine
|
||||
*/
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -2157,9 +2163,9 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Arc sine
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Arc sine
|
||||
*/
|
||||
|
||||
floatx80 floatx80_asin(floatx80 a, float_status *status)
|
||||
{
|
||||
@@ -2222,9 +2228,9 @@ floatx80 floatx80_asin(floatx80 a, float_status *status)
|
||||
return a;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Arc cosine
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Arc cosine
|
||||
*/
|
||||
|
||||
floatx80 floatx80_acos(floatx80 a, float_status *status)
|
||||
{
|
||||
@@ -2291,9 +2297,9 @@ floatx80 floatx80_acos(floatx80 a, float_status *status)
|
||||
return a;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Hyperbolic arc tangent
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Hyperbolic arc tangent
|
||||
*/
|
||||
|
||||
floatx80 floatx80_atanh(floatx80 a, float_status *status)
|
||||
{
|
||||
@@ -2356,9 +2362,9 @@ floatx80 floatx80_atanh(floatx80 a, float_status *status)
|
||||
return a;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| e to x minus 1
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* e to x minus 1
|
||||
*/
|
||||
|
||||
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 */
|
||||
m = n / 64; /* NOTE: this is really arithmetic right shift by 6 */
|
||||
if (n < 0 && j) {
|
||||
/* arithmetic right shift is division and
|
||||
/*
|
||||
* arithmetic right shift is division and
|
||||
* round towards minus infinity
|
||||
*/
|
||||
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)
|
||||
{
|
||||
@@ -2722,9 +2729,9 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status)
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Hyperbolic sine
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Hyperbolic sine
|
||||
*/
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
+161
-85
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user