260 lines
9.2 KiB
C
260 lines
9.2 KiB
C
/*
|
|
* m68k.h - machine dependent bits
|
|
*
|
|
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
|
*
|
|
* Inspired by Christian Bauer's Basilisk II
|
|
*
|
|
* This file is part of the ARAnyM project which builds a new and powerful
|
|
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
|
*
|
|
* ARAnyM 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.
|
|
*
|
|
* ARAnyM 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 ARAnyM; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
/*
|
|
* UAE - The Un*x Amiga Emulator
|
|
*
|
|
* MC68000 emulation - machine dependent bits
|
|
*
|
|
* Copyright 1996 Bernd Schmidt
|
|
* Copyright 2004-2005 Richard Drummond
|
|
*/
|
|
|
|
#if (defined(CPU_i386) && defined(X86_ASSEMBLY)) || (defined(CPU_x86_64) && defined(X86_64_ASSEMBLY))
|
|
|
|
#ifndef REGS_DEFINED
|
|
|
|
/*
|
|
* Machine dependent structure for holding the 68k CCR flags
|
|
*/
|
|
struct flag_struct {
|
|
unsigned int cznv;
|
|
unsigned int x;
|
|
};
|
|
|
|
|
|
/*
|
|
* The bits in the cznv field in the above structure are assigned to
|
|
* allow the easy mirroring of the x86 condition flags. (For example,
|
|
* from the AX register - the x86 overflow flag can be copied to AL
|
|
* with a setto %AL instr and the other flags copied to AH with an
|
|
* lahf instr).
|
|
*
|
|
* The 68k CZNV flags are thus assinged in cznv as:
|
|
*
|
|
* <--AL--> <--AH-->
|
|
* 76543210 FEDCBA98 --------- ---------
|
|
* xxxxxxxV NZxxxxxC xxxxxxxxx xxxxxxxxx
|
|
*/
|
|
|
|
#define FLAGBIT_N 15
|
|
#define FLAGBIT_Z 14
|
|
#define FLAGBIT_C 8
|
|
#define FLAGBIT_V 0
|
|
#define FLAGBIT_X 8
|
|
|
|
#define FLAGVAL_N (1 << FLAGBIT_N)
|
|
#define FLAGVAL_Z (1 << FLAGBIT_Z)
|
|
#define FLAGVAL_C (1 << FLAGBIT_C)
|
|
#define FLAGVAL_V (1 << FLAGBIT_V)
|
|
#define FLAGVAL_X (1 << FLAGBIT_X)
|
|
|
|
#else /* REGS_DEFINED */
|
|
|
|
#define SET_ZFLG(y) (regs.ccrflags.cznv = (regs.ccrflags.cznv & ~FLAGVAL_Z) | (((y) ? 1 : 0) << FLAGBIT_Z))
|
|
#define SET_CFLG(y) (regs.ccrflags.cznv = (regs.ccrflags.cznv & ~FLAGVAL_C) | (((y) ? 1 : 0) << FLAGBIT_C))
|
|
#define SET_VFLG(y) (regs.ccrflags.cznv = (regs.ccrflags.cznv & ~FLAGVAL_V) | (((y) ? 1 : 0) << FLAGBIT_V))
|
|
#define SET_NFLG(y) (regs.ccrflags.cznv = (regs.ccrflags.cznv & ~FLAGVAL_N) | (((y) ? 1 : 0) << FLAGBIT_N))
|
|
#define SET_XFLG(y) (regs.ccrflags.x = ((y) ? 1 : 0) << FLAGBIT_X)
|
|
|
|
#define GET_ZFLG() ((regs.ccrflags.cznv >> FLAGBIT_Z) & 1)
|
|
#define GET_CFLG() ((regs.ccrflags.cznv >> FLAGBIT_C) & 1)
|
|
#define GET_VFLG() ((regs.ccrflags.cznv >> FLAGBIT_V) & 1)
|
|
#define GET_NFLG() ((regs.ccrflags.cznv >> FLAGBIT_N) & 1)
|
|
#define GET_XFLG() ((regs.ccrflags.x >> FLAGBIT_X) & 1)
|
|
|
|
#define CLEAR_CZNV() (regs.ccrflags.cznv = 0)
|
|
#define GET_CZNV() (regs.ccrflags.cznv)
|
|
#define IOR_CZNV(X) (regs.ccrflags.cznv |= (X))
|
|
#define SET_CZNV(X) (regs.ccrflags.cznv = (X))
|
|
|
|
#define COPY_CARRY() (regs.ccrflags.x = regs.ccrflags.cznv)
|
|
|
|
|
|
/*
|
|
* Test CCR condition
|
|
*/
|
|
STATIC_INLINE int cctrue (int cc)
|
|
{
|
|
uae_u32 cznv = regs.ccrflags.cznv;
|
|
|
|
switch (cc) {
|
|
case 0: return 1; /* T */
|
|
case 1: return 0; /* F */
|
|
case 2: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) == 0; /* !CFLG && !ZFLG HI */
|
|
case 3: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) != 0; /* CFLG || ZFLG LS */
|
|
case 4: return (cznv & FLAGVAL_C) == 0; /* !CFLG CC */
|
|
case 5: return (cznv & FLAGVAL_C) != 0; /* CFLG CS */
|
|
case 6: return (cznv & FLAGVAL_Z) == 0; /* !ZFLG NE */
|
|
case 7: return (cznv & FLAGVAL_Z) != 0; /* ZFLG EQ */
|
|
case 8: return (cznv & FLAGVAL_V) == 0; /* !VFLG VC */
|
|
case 9: return (cznv & FLAGVAL_V) != 0; /* VFLG VS */
|
|
case 10: return (cznv & FLAGVAL_N) == 0; /* !NFLG PL */
|
|
case 11: return (cznv & FLAGVAL_N) != 0; /* NFLG MI */
|
|
case 12: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) == 0; /* NFLG == VFLG GE */
|
|
case 13: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) != 0; /* NFLG != VFLG LT */
|
|
case 14: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG && (NFLG == VFLG) GT */
|
|
return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) == 0;
|
|
case 15: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG && (NFLG != VFLG) LE */
|
|
return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) != 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#endif /* REGS_DEFINED */
|
|
|
|
#elif defined(CPU_arm) && defined(ARMV6_ASSEMBLY)
|
|
|
|
#ifndef REGS_DEFINED
|
|
|
|
struct flag_struct {
|
|
uae_u32 nzcv;
|
|
uae_u32 x;
|
|
};
|
|
|
|
#define FLAGVAL_Q 0x08000000
|
|
#define FLAGVAL_V 0x10000000
|
|
#define FLAGVAL_C 0x20000000
|
|
#define FLAGVAL_Z 0x40000000
|
|
#define FLAGVAL_N 0x80000000
|
|
|
|
#else /* REGS_DEFINED */
|
|
|
|
#define SET_NFLG(y) (regs.ccrflags.nzcv = (regs.ccrflags.nzcv & ~0x80000000) | (((y) ? 1 : 0) << 31))
|
|
#define SET_ZFLG(y) (regs.ccrflags.nzcv = (regs.ccrflags.nzcv & ~0x40000000) | (((y) ? 1 : 0) << 30))
|
|
#define SET_CFLG(y) (regs.ccrflags.nzcv = (regs.ccrflags.nzcv & ~0x20000000) | (((y) ? 1 : 0) << 29))
|
|
#define SET_VFLG(y) (regs.ccrflags.nzcv = (regs.ccrflags.nzcv & ~0x10000000) | (((y) ? 1 : 0) << 28))
|
|
|
|
#define SET_XFLG(y) (regs.ccrflags.x = ((y) ? 1 : 0))
|
|
|
|
#define GET_NFLG() ((regs.ccrflags.nzcv >> 31) & 1)
|
|
#define GET_ZFLG() ((regs.ccrflags.nzcv >> 30) & 1)
|
|
#define GET_CFLG() ((regs.ccrflags.nzcv >> 29) & 1)
|
|
#define GET_VFLG() ((regs.ccrflags.nzcv >> 28) & 1)
|
|
#define GET_XFLG() (regs.ccrflags.x & 1)
|
|
|
|
#define CLEAR_CZNV() (regs.ccrflags.nzcv = 0)
|
|
#define GET_CZNV() (regs.ccrflags.nzcv)
|
|
#define IOR_CZNV(X) (regs.ccrflags.nzcv |= (X))
|
|
#define SET_CZNV(X) (regs.ccrflags.nzcv = (X))
|
|
|
|
#define COPY_CARRY() (regs.ccrflags.x = ((regs.ccrflags.nzcv >> 29) & 1))
|
|
|
|
STATIC_INLINE int cctrue(int cc)
|
|
{
|
|
unsigned int nzcv = regs.ccrflags.nzcv;
|
|
switch(cc){
|
|
case 0: return 1; /* T */
|
|
case 1: return 0; /* F */
|
|
case 2: return (nzcv & 0x60000000) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
|
|
case 3: return (nzcv & 0x60000000) != 0; /* GET_CFLG || GET_ZFLG; LS */
|
|
case 4: return (nzcv & 0x20000000) == 0; /* !GET_CFLG; CC */
|
|
case 5: return (nzcv & 0x20000000) != 0; /* GET_CFLG; CS */
|
|
case 6: return (nzcv & 0x40000000) == 0; /* !GET_ZFLG; NE */
|
|
case 7: return (nzcv & 0x40000000) != 0; /* GET_ZFLG; EQ */
|
|
case 8: return (nzcv & 0x10000000) == 0; /* !GET_VFLG; VC */
|
|
case 9: return (nzcv & 0x10000000) != 0; /* GET_VFLG; VS */
|
|
case 10:return (nzcv & 0x80000000) == 0; /* !GET_NFLG; PL */
|
|
case 11:return (nzcv & 0x80000000) != 0; /* GET_NFLG; MI */
|
|
case 12:return (((nzcv << 3) ^ nzcv) & 0x80000000) == 0; /* GET_NFLG == GET_VFLG; GE */
|
|
case 13:return (((nzcv << 3) ^ nzcv) & 0x80000000) != 0; /* GET_NFLG != GET_VFLG; LT */
|
|
case 14:
|
|
nzcv &= 0xd0000000;
|
|
return (((nzcv << 3) ^ nzcv) & 0xc0000000) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
|
|
case 15:
|
|
nzcv &= 0xd0000000;
|
|
return (((nzcv << 3) ^ nzcv) & 0xc0000000) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#endif /* REGS_DEFINED */
|
|
|
|
#else
|
|
|
|
#ifndef REGS_DEFINED
|
|
|
|
struct flag_struct {
|
|
unsigned int c;
|
|
unsigned int z;
|
|
unsigned int n;
|
|
unsigned int v;
|
|
unsigned int x;
|
|
};
|
|
|
|
#else /* REGS_DEFINED */
|
|
|
|
#define ZFLG (regs.ccrflags.z)
|
|
#define NFLG (regs.ccrflags.n)
|
|
#define CFLG (regs.ccrflags.c)
|
|
#define VFLG (regs.ccrflags.v)
|
|
#define XFLG (regs.ccrflags.x)
|
|
|
|
#define SET_CFLG(x) (CFLG = (x))
|
|
#define SET_NFLG(x) (NFLG = (x))
|
|
#define SET_VFLG(x) (VFLG = (x))
|
|
#define SET_ZFLG(x) (ZFLG = (x))
|
|
#define SET_XFLG(x) (XFLG = (x))
|
|
|
|
#define GET_CFLG() CFLG
|
|
#define GET_NFLG() NFLG
|
|
#define GET_VFLG() VFLG
|
|
#define GET_ZFLG() ZFLG
|
|
#define GET_XFLG() XFLG
|
|
|
|
#define CLEAR_CZNV() do { \
|
|
SET_CFLG (0); \
|
|
SET_ZFLG (0); \
|
|
SET_NFLG (0); \
|
|
SET_VFLG (0); \
|
|
} while (0)
|
|
|
|
#define COPY_CARRY() (regs.ccrflags.x = regs.ccrflags.c)
|
|
|
|
STATIC_INLINE int cctrue(const int cc)
|
|
{
|
|
switch(cc){
|
|
case 0: return 1; /* T */
|
|
case 1: return 0; /* F */
|
|
case 2: return !CFLG && !ZFLG; /* HI */
|
|
case 3: return CFLG || ZFLG; /* LS */
|
|
case 4: return !CFLG; /* CC */
|
|
case 5: return CFLG; /* CS */
|
|
case 6: return !ZFLG; /* NE */
|
|
case 7: return ZFLG; /* EQ */
|
|
case 8: return !VFLG; /* VC */
|
|
case 9: return VFLG; /* VS */
|
|
case 10:return !NFLG; /* PL */
|
|
case 11:return NFLG; /* MI */
|
|
case 12:return NFLG == VFLG; /* GE */
|
|
case 13:return NFLG != VFLG; /* LT */
|
|
case 14:return !ZFLG && (NFLG == VFLG); /* GT */
|
|
case 15:return ZFLG || (NFLG != VFLG); /* LE */
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#endif /* REGS_DEFINED */
|
|
|
|
#endif
|