mirror of
https://github.com/libretro/PUAE.git
synced 2024-11-27 01:50:51 +00:00
add a new generic x86 machdep directory
this merges i386 and x86_64 into a single dir. the few differences use #ifdef __x86_64__.
This commit is contained in:
parent
ba2582df1e
commit
ce51f99dc8
10
src/md-x86-gcc/Makefile.am
Normal file
10
src/md-x86-gcc/Makefile.am
Normal file
@ -0,0 +1,10 @@
|
||||
AM_CPPFLAGS = @UAE_CPPFLAGS@
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/include -I$(top_builddir)/src -I$(top_srcdir)/src
|
||||
AM_CFLAGS = @UAE_CFLAGS@
|
||||
AM_CXXFLAGS = @UAE_CXXFLAGS@
|
||||
|
||||
noinst_LIBRARIES = libmachdep.a
|
||||
|
||||
libmachdep_a_SOURCES = support.c
|
||||
|
||||
noinst_HEADERS = machdep.h m68k.h m68kops.h maccess.h rpt.h
|
97
src/md-x86-gcc/m68k.h
Normal file
97
src/md-x86-gcc/m68k.h
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* MC68000 emulation - machine dependent bits
|
||||
*
|
||||
* Copyright 1996 Bernd Schmidt
|
||||
* Copyright 2004-2007 Richard Drummond
|
||||
*/
|
||||
|
||||
/*
|
||||
* Machine dependent structure for holding the 68k CCR flags
|
||||
*/
|
||||
struct flag_struct {
|
||||
unsigned int cznv;
|
||||
unsigned int x;
|
||||
};
|
||||
|
||||
extern struct flag_struct regflags;
|
||||
|
||||
/*
|
||||
* 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 assigned 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)
|
||||
|
||||
#define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~FLAGVAL_Z) | (((y) ? 1 : 0) << FLAGBIT_Z))
|
||||
#define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~FLAGVAL_C) | (((y) ? 1 : 0) << FLAGBIT_C))
|
||||
#define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~FLAGVAL_V) | (((y) ? 1 : 0) << FLAGBIT_V))
|
||||
#define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~FLAGVAL_N) | (((y) ? 1 : 0) << FLAGBIT_N))
|
||||
#define SET_XFLG(y) (regflags.x = ((y) ? 1 : 0) << FLAGBIT_X)
|
||||
|
||||
#define GET_ZFLG() ((regflags.cznv >> FLAGBIT_Z) & 1)
|
||||
#define GET_CFLG() ((regflags.cznv >> FLAGBIT_C) & 1)
|
||||
#define GET_VFLG() ((regflags.cznv >> FLAGBIT_V) & 1)
|
||||
#define GET_NFLG() ((regflags.cznv >> FLAGBIT_N) & 1)
|
||||
#define GET_XFLG() ((regflags.x >> FLAGBIT_X) & 1)
|
||||
|
||||
#define CLEAR_CZNV() (regflags.cznv = 0)
|
||||
#define GET_CZNV (regflags.cznv)
|
||||
#define IOR_CZNV(X) (regflags.cznv |= (X))
|
||||
#define SET_CZNV(X) (regflags.cznv = (X))
|
||||
|
||||
#define COPY_CARRY() (regflags.x = regflags.cznv)
|
||||
|
||||
|
||||
/*
|
||||
* Test CCR condition
|
||||
*/
|
||||
STATIC_INLINE int cctrue (int cc)
|
||||
{
|
||||
uae_u32 cznv = regflags.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;
|
||||
}
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define USE_X86_FPUCW 1
|
242
src/md-x86-gcc/m68kops.h
Normal file
242
src/md-x86-gcc/m68kops.h
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* E-UAE - The portable Amiga Emulator
|
||||
*
|
||||
* MC68000 emulation - machine-dependent optimized operations
|
||||
*
|
||||
* (c) 2004-2007 Richard Drummond
|
||||
*/
|
||||
|
||||
#ifndef EUAE_MACHDEP_M68KOPS_H
|
||||
#define EUAE_MACHDEP_M68KOPS_H
|
||||
|
||||
/*
|
||||
* Optimized code which uses the host CPU's condition flags to evaluate
|
||||
* 68K CCR flags for certain operations.
|
||||
*
|
||||
* These are used by various opcode handlers when
|
||||
* gencpu has been built with OPTIMIZED_FLAGS defined
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test operations
|
||||
*
|
||||
* Evaluate operand and set Z and N flags. Always clear C and V.
|
||||
*/
|
||||
/* Is there any way to do this without declaring *all* memory clobbered?
|
||||
I.e. any way to tell gcc that some byte-sized value is in %al? */
|
||||
//#if defined(__APPLE__) && !defined(__x86_64__)
|
||||
#ifndef __x86_64__
|
||||
#define optflag_testl(v) \
|
||||
__asm__ __volatile__ ("andl %0,%0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,_regflags\n\t" \
|
||||
"movb %%ah,_regflags+1\n\t" \
|
||||
:: "r" (v) : "%eax","cc","memory")
|
||||
#define optflag_testw(v) \
|
||||
__asm__ __volatile__ ("andw %w0,%w0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,_regflags\n\t" \
|
||||
"movb %%ah,_regflags+1\n\t" \
|
||||
:: "r" (v) : "%eax","cc","memory")
|
||||
|
||||
#define optflag_testb(v) \
|
||||
__asm__ __volatile__ ("andb %b0,%b0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,_regflags\n\t" \
|
||||
"movb %%ah,_regflags+1\n\t" \
|
||||
:: "q" (v) : "%eax","cc","memory")
|
||||
|
||||
#define optflag_addl(v, s, d) do { \
|
||||
__asm__ __volatile__ ("addl %k1,%k0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,_regflags\n\t" \
|
||||
"movb %%ah,_regflags+1\n\t" \
|
||||
:"=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
|
||||
regflags.x = regflags.cznv; \
|
||||
} while (0)
|
||||
#define optflag_addw(v, s, d) do { \
|
||||
__asm__ __volatile__ ("addw %w1,%w0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,_regflags\n\t" \
|
||||
"movb %%ah,_regflags+1\n\t" \
|
||||
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
|
||||
regflags.x = regflags.cznv; \
|
||||
} while (0)
|
||||
|
||||
#define optflag_addb(v, s, d) do { \
|
||||
__asm__ __volatile__ ("addb %b1,%b0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,_regflags\n\t" \
|
||||
"movb %%ah,_regflags+1\n\t" \
|
||||
:"=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
|
||||
regflags.x = regflags.cznv; \
|
||||
} while (0)
|
||||
|
||||
#define optflag_subl(v, s, d) do { \
|
||||
__asm__ __volatile__ ("subl %k1,%k0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,_regflags\n\t" \
|
||||
"movb %%ah,_regflags+1\n\t" \
|
||||
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
|
||||
regflags.x = regflags.cznv; \
|
||||
} while (0)
|
||||
|
||||
#define optflag_subw(v, s, d) do { \
|
||||
__asm__ __volatile__ ("subw %w1,%w0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,_regflags\n\t" \
|
||||
"movb %%ah,_regflags+1\n\t" \
|
||||
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
|
||||
regflags.x = regflags.cznv; \
|
||||
} while (0)
|
||||
|
||||
#define optflag_subb(v, s, d) do { \
|
||||
__asm__ __volatile__ ("subb %b1,%b0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,_regflags\n\t" \
|
||||
"movb %%ah,_regflags+1\n\t" \
|
||||
: "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
|
||||
regflags.x = regflags.cznv; \
|
||||
} while (0)
|
||||
|
||||
#define optflag_cmpl(s, d) \
|
||||
__asm__ __volatile__ ("cmpl %k0,%k1\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,_regflags\n\t" \
|
||||
"movb %%ah,_regflags+1\n\t" \
|
||||
:: "rmi" (s), "r" (d) : "%eax","cc","memory")
|
||||
|
||||
#define optflag_cmpw(s, d) \
|
||||
__asm__ __volatile__ ("cmpw %w0,%w1\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,_regflags\n\t" \
|
||||
"movb %%ah,_regflags+1\n\t" \
|
||||
:: "rmi" (s), "r" (d) : "%eax","cc","memory");
|
||||
|
||||
#define optflag_cmpb(s, d) \
|
||||
__asm__ __volatile__ ("cmpb %b0,%b1\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,_regflags\n\t" \
|
||||
"movb %%ah,_regflags+1\n\t" \
|
||||
:: "qmi" (s), "q" (d) : "%eax","cc","memory")
|
||||
#else /*ifdef apple*/
|
||||
#define optflag_testl(v) \
|
||||
__asm__ __volatile__ ("andl %0,%0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,regflags\n\t" \
|
||||
"movb %%ah,regflags+1\n\t" \
|
||||
:: "r" (v) : "%eax","cc","memory")
|
||||
#define optflag_testw(v) \
|
||||
__asm__ __volatile__ ("andw %w0,%w0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,regflags\n\t" \
|
||||
"movb %%ah,regflags+1\n\t" \
|
||||
:: "r" (v) : "%eax","cc","memory")
|
||||
|
||||
#define optflag_testb(v) \
|
||||
__asm__ __volatile__ ("andb %b0,%b0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,regflags\n\t" \
|
||||
"movb %%ah,regflags+1\n\t" \
|
||||
:: "q" (v) : "%eax","cc","memory")
|
||||
|
||||
#define optflag_addl(v, s, d) do { \
|
||||
__asm__ __volatile__ ("addl %k1,%k0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,regflags\n\t" \
|
||||
"movb %%ah,regflags+1\n\t" \
|
||||
:"=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
|
||||
regflags.x = regflags.cznv; \
|
||||
} while (0)
|
||||
#define optflag_addw(v, s, d) do { \
|
||||
__asm__ __volatile__ ("addw %w1,%w0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,regflags\n\t" \
|
||||
"movb %%ah,regflags+1\n\t" \
|
||||
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
|
||||
regflags.x = regflags.cznv; \
|
||||
} while (0)
|
||||
|
||||
#define optflag_addb(v, s, d) do { \
|
||||
__asm__ __volatile__ ("addb %b1,%b0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,regflags\n\t" \
|
||||
"movb %%ah,regflags+1\n\t" \
|
||||
:"=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
|
||||
regflags.x = regflags.cznv; \
|
||||
} while (0)
|
||||
|
||||
#define optflag_subl(v, s, d) do { \
|
||||
__asm__ __volatile__ ("subl %k1,%k0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,regflags\n\t" \
|
||||
"movb %%ah,regflags+1\n\t" \
|
||||
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
|
||||
regflags.x = regflags.cznv; \
|
||||
} while (0)
|
||||
|
||||
#define optflag_subw(v, s, d) do { \
|
||||
__asm__ __volatile__ ("subw %w1,%w0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,regflags\n\t" \
|
||||
"movb %%ah,regflags+1\n\t" \
|
||||
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
|
||||
regflags.x = regflags.cznv; \
|
||||
} while (0)
|
||||
|
||||
#define optflag_subb(v, s, d) do { \
|
||||
__asm__ __volatile__ ("subb %b1,%b0\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,regflags\n\t" \
|
||||
"movb %%ah,regflags+1\n\t" \
|
||||
: "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
|
||||
regflags.x = regflags.cznv; \
|
||||
} while (0)
|
||||
|
||||
#define optflag_cmpl(s, d) \
|
||||
__asm__ __volatile__ ("cmpl %k0,%k1\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,regflags\n\t" \
|
||||
"movb %%ah,regflags+1\n\t" \
|
||||
:: "rmi" (s), "r" (d) : "%eax","cc","memory")
|
||||
|
||||
#define optflag_cmpw(s, d) \
|
||||
__asm__ __volatile__ ("cmpw %w0,%w1\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,regflags\n\t" \
|
||||
"movb %%ah,regflags+1\n\t" \
|
||||
:: "rmi" (s), "r" (d) : "%eax","cc","memory");
|
||||
|
||||
#define optflag_cmpb(s, d) \
|
||||
__asm__ __volatile__ ("cmpb %b0,%b1\n\t" \
|
||||
"lahf\n\t" \
|
||||
"seto %%al\n\t" \
|
||||
"movb %%al,regflags\n\t" \
|
||||
"movb %%ah,regflags+1\n\t" \
|
||||
:: "qmi" (s), "q" (d) : "%eax","cc","memory")
|
||||
#endif /*ifdef apple*/
|
||||
|
||||
#endif /* EUAE_MACHDEP_M68KOPS_H */
|
159
src/md-x86-gcc/maccess.h
Normal file
159
src/md-x86-gcc/maccess.h
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Memory access functions
|
||||
*
|
||||
* Copyright 1996 Bernd Schmidt
|
||||
*/
|
||||
|
||||
STATIC_INLINE uae_u32 do_get_mem_long (uae_u32 *a)
|
||||
{
|
||||
uae_u32 retval;
|
||||
|
||||
__asm__ ("bswap %0" : "=r" (retval) : "0" (*a) : "cc");
|
||||
return retval;
|
||||
}
|
||||
|
||||
STATIC_INLINE uae_u32 do_get_mem_word (uae_u16 *a)
|
||||
{
|
||||
#if 0
|
||||
uae_u8 *b = (uae_u8 *)a;
|
||||
return (*b << 8) | (*(b+1));
|
||||
#endif
|
||||
|
||||
uae_u32 retval;
|
||||
|
||||
#ifdef X86_PPRO_OPT
|
||||
__asm__ ("movzwl %w1,%k0\n\tshll $16,%k0\n\tbswap %k0\n" : "=&r" (retval) : "m" (*a) : "cc");
|
||||
#else
|
||||
__asm__ ("xorl %k0,%k0\n\tmovw %w1,%w0\n\trolw $8,%w0" : "=&r" (retval) : "m" (*a) : "cc");
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
#define do_get_mem_byte(a) ((uae_u32)*((uae_u8 *)a))
|
||||
|
||||
STATIC_INLINE void do_put_mem_long (uae_u32 *a, uae_u32 v)
|
||||
{
|
||||
__asm__ ("bswap %0" : "=r" (v) : "0" (v) : "cc");
|
||||
*a = v;
|
||||
}
|
||||
|
||||
STATIC_INLINE void do_put_mem_word (uae_u16 *a, uae_u32 v)
|
||||
{
|
||||
#ifdef X86_PPRO_OPT
|
||||
__asm__ ("bswap %0" : "=&r" (v) : "0" (v << 16) : "cc");
|
||||
#else
|
||||
__asm__ ("rolw $8,%w0" : "=r" (v) : "0" (v) : "cc");
|
||||
#endif
|
||||
*a = v;
|
||||
}
|
||||
|
||||
#define do_put_mem_byte(a,v) (*(uae_u8 *)(a) = (v))
|
||||
|
||||
#define call_mem_get_func(func,addr) ((*func)(addr))
|
||||
#define call_mem_put_func(func,addr,v) ((*func)(addr,v))
|
||||
|
||||
|
||||
#define ALIGN_POINTER_TO32(p) ((~(unsigned long)(p)) & 3)
|
||||
|
||||
#ifndef __x86_64__
|
||||
#undef NO_INLINE_MEMORY_ACCESS
|
||||
#undef MD_HAVE_MEM_1_FUNCS
|
||||
|
||||
#ifdef MD_HAVE_MEM_1_FUNCS
|
||||
STATIC_INLINE uae_u32 longget_1 (uae_cptr addr)
|
||||
{
|
||||
uae_u32 result;
|
||||
|
||||
__asm__ ("andl $0x00FFFFFF,%1\n"
|
||||
"\tcmpb $0,(%1,%3)\n"
|
||||
"\tleal 1f,%%ecx\n"
|
||||
"\tje longget_stub\n"
|
||||
"\taddl address_space,%1\n"
|
||||
"\tmovl (%1),%0\n"
|
||||
"\tbswap %0\n"
|
||||
"\t1:"
|
||||
: "=c" (result), "=d" (addr) : "1" (addr), "r" (good_address_map) : "cc");
|
||||
return result;
|
||||
}
|
||||
STATIC_INLINE uae_u32 wordget_1 (uae_cptr addr)
|
||||
{
|
||||
uae_u32 result;
|
||||
|
||||
__asm__ ("andl $0x00FFFFFF,%1\n"
|
||||
"\tcmpb $0,(%1,%3)\n"
|
||||
"\tleal 1f,%%ecx\n"
|
||||
"\tje wordget_stub\n"
|
||||
"\taddl address_space,%1\n"
|
||||
"\tmovzwl (%1),%0\n"
|
||||
"\trolw $8,%w0\n"
|
||||
"\t1:"
|
||||
: "=c" (result), "=d" (addr) : "1" (addr), "r" (good_address_map) : "cc");
|
||||
return result;
|
||||
}
|
||||
STATIC_INLINE uae_u32 byteget_1 (uae_cptr addr)
|
||||
{
|
||||
uae_u32 result;
|
||||
|
||||
__asm__ ("andl $0x00FFFFFF,%1\n"
|
||||
"\tcmpb $0,(%1,%3)\n"
|
||||
"\tleal 1f,%%ecx\n"
|
||||
"\tje byteget_stub\n"
|
||||
"\taddl address_space,%1\n"
|
||||
"\tmovzbl (%1),%0\n"
|
||||
"\t1:"
|
||||
: "=c" (result), "=d" (addr) : "1" (addr), "r" (good_address_map) : "cc");
|
||||
return result;
|
||||
}
|
||||
STATIC_INLINE void longput_1 (uae_cptr addr, uae_u32 l)
|
||||
{
|
||||
__asm__ __volatile__("andl $0x00FFFFFF,%0\n"
|
||||
"\tcmpb $0,(%0,%3)\n"
|
||||
"\tleal 1f,%%ecx\n"
|
||||
"\tje longput_stub\n"
|
||||
"\taddl address_space,%0\n"
|
||||
"\tbswap %1\n"
|
||||
"\tmovl %1,(%0)\n"
|
||||
"\t1:"
|
||||
: "=d" (addr), "=b" (l) : "0" (addr), "r" (good_address_map), "1" (l) : "cc", "memory", "ecx");
|
||||
}
|
||||
STATIC_INLINE void wordput_1 (uae_cptr addr, uae_u32 w)
|
||||
{
|
||||
__asm__ __volatile__("andl $0x00FFFFFF,%0\n"
|
||||
"\tcmpb $0,(%0,%3)\n"
|
||||
"\tleal 1f,%%ecx\n"
|
||||
"\tje wordput_stub\n"
|
||||
"\taddl address_space,%0\n"
|
||||
"\trolw $8,%1\n"
|
||||
"\tmovw %w1,(%0)\n"
|
||||
"\t1:"
|
||||
: "=d" (addr), "=b" (w) : "0" (addr), "r" (good_address_map), "1" (w) : "cc", "memory", "ecx");
|
||||
}
|
||||
STATIC_INLINE void byteput_1 (uae_cptr addr, uae_u32 b)
|
||||
{
|
||||
__asm__ __volatile__("andl $0x00FFFFFF,%0\n"
|
||||
"\tcmpb $0,(%0,%3)\n"
|
||||
"\tleal 1f,%%ecx\n"
|
||||
"\tje byteput_stub\n"
|
||||
"\taddl address_space,%0\n"
|
||||
"\tmovb %b1,(%0)\n"
|
||||
"\t1:"
|
||||
: "=d" (addr), "=b" (b) : "0" (addr), "r" (good_address_map), "1" (b) : "cc", "memory", "ecx");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Not the best place for this, but then there's no good place for a kludge
|
||||
* like this... */
|
||||
#define HAVE_UAE_U24
|
||||
typedef struct {
|
||||
unsigned char a, b, c;
|
||||
} __attribute__ ((packed)) uae_u24;
|
||||
|
||||
STATIC_INLINE uae_u24 uae24_convert (uae_u32 v)
|
||||
{
|
||||
return *(uae_u24 *)&v;
|
||||
}
|
||||
|
||||
#endif
|
24
src/md-x86-gcc/machdep.h
Normal file
24
src/md-x86-gcc/machdep.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* E-UAE - The portable Amiga Emulator
|
||||
*
|
||||
* Processor-specific definitions
|
||||
*
|
||||
* Copyright 2005 Richard Drummond
|
||||
*/
|
||||
|
||||
#ifndef MACHDEP_MACHDEP_H
|
||||
#define MACHDEP_MACHDEP_H
|
||||
|
||||
#define MACHDEP_X86
|
||||
#ifdef __x86_64__
|
||||
#define MACHDEP_NAME "amd64"
|
||||
#else
|
||||
#define MACHDEP_NAME "x86"
|
||||
#endif
|
||||
|
||||
#define HAVE_MACHDEP_TIMER
|
||||
|
||||
typedef uae_s64 frame_time_t;
|
||||
#define MAX_FRAME_TIME 9223372036854775807LL
|
||||
|
||||
#endif
|
71
src/md-x86-gcc/rpt.h
Normal file
71
src/md-x86-gcc/rpt.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* E-UAE - The portable Amiga Emulator
|
||||
*
|
||||
* Read timestamp counter on an AMD64
|
||||
*
|
||||
* Copyright 2005 Richard Drummond
|
||||
*
|
||||
* Derived from the i386 version:
|
||||
* Copyright 1997, 1998 Bernd Schmidt
|
||||
* Copyright 2003-2005 Richard Drummond
|
||||
*/
|
||||
|
||||
#ifndef EUAE_MACHDEP_RPT_H
|
||||
#define EUAE_MACHDEP_RPT_H
|
||||
|
||||
STATIC_INLINE uae_s64 read_processor_time (void)
|
||||
{
|
||||
#ifndef __x86_64__
|
||||
uae_u32 foo1, foo2;
|
||||
#else
|
||||
uae_s64 foo1, foo2;
|
||||
#endif
|
||||
uae_s64 tsc;
|
||||
|
||||
|
||||
/* Don't assume the assembler knows rdtsc */
|
||||
__asm__ __volatile__ (".byte 0x0f,0x31" : "=a" (foo1), "=d" (foo2) :);
|
||||
tsc = (((uae_u64) foo2) << 32ULL) | (uae_u64) foo1;
|
||||
|
||||
#ifdef __linux__
|
||||
/* Hack to synchronize syncbase and re-compute
|
||||
* vsynctime when TSC frequency changes */
|
||||
|
||||
/* How many times per second tsc will be synced */
|
||||
#define TSC_SYNC_FREQUENCY 8
|
||||
{
|
||||
extern frame_time_t linux_get_tsc_freq (void);
|
||||
extern void compute_vsynctime (void);
|
||||
// extern frame_time_t syncbaseo;
|
||||
extern int syncbase;
|
||||
|
||||
static frame_time_t next_tsc_synctime;
|
||||
static frame_time_t prev_syncbase;
|
||||
|
||||
if (tsc > next_tsc_synctime) {
|
||||
uae_s64 new_tsc_freq = linux_get_tsc_freq ();
|
||||
|
||||
if (new_tsc_freq > 0) {
|
||||
syncbase = new_tsc_freq;
|
||||
next_tsc_synctime = tsc + (syncbase / TSC_SYNC_FREQUENCY);
|
||||
|
||||
if (syncbase != prev_syncbase) {
|
||||
prev_syncbase = syncbase;
|
||||
compute_vsynctime ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return tsc;
|
||||
}
|
||||
|
||||
STATIC_INLINE frame_time_t machdep_gethrtime (void)
|
||||
{
|
||||
return read_processor_time ();
|
||||
}
|
||||
|
||||
frame_time_t machdep_gethrtimebase (void);
|
||||
int machdep_inithrtimer (void);
|
||||
|
||||
#endif /* EUAE_MACHDEP_RPT_H */
|
295
src/md-x86-gcc/support.c
Normal file
295
src/md-x86-gcc/support.c
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Miscellaneous machine dependent support functions and definitions
|
||||
*
|
||||
* Copyright 1996 Bernd Schmidt
|
||||
* Copyright 2003-2005 Richard Drummond
|
||||
*/
|
||||
|
||||
#include "sysconfig.h"
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include "cfgfile.h"
|
||||
#include "sleep.h"
|
||||
#include "rpt.h"
|
||||
#include "m68k.h"
|
||||
#include "events.h"
|
||||
#include "custom.h"
|
||||
|
||||
#ifndef USE_UNDERSCORE
|
||||
#define LARGE_ALIGNMENT ".align 16\n"
|
||||
#else
|
||||
#define LARGE_ALIGNMENT ".align 4,0x90\n"
|
||||
#endif
|
||||
|
||||
struct flag_struct regflags;
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
/* internal prototypes */
|
||||
void machdep_save_options (struct zfile *, const struct uae_prefs *);
|
||||
int machdep_parse_option (struct uae_prefs *, const char *, const char *);
|
||||
void machdep_default_options (struct uae_prefs *);
|
||||
|
||||
#ifdef __linux__
|
||||
frame_time_t linux_get_tsc_freq (void);
|
||||
|
||||
/*
|
||||
* Extract x86/AMD64 timestamp counter frequency
|
||||
* from /proc/cpuinfo.
|
||||
*
|
||||
* TODO: Make this more robust.
|
||||
*/
|
||||
frame_time_t linux_get_tsc_freq (void)
|
||||
{
|
||||
int cpuinfo_fd;
|
||||
char buffer[1024];
|
||||
static uae_s64 tsc_freq = 0;
|
||||
if(tsc_freq) return tsc_freq;
|
||||
|
||||
cpuinfo_fd = open ("/proc/cpuinfo", O_RDONLY);
|
||||
|
||||
if (cpuinfo_fd >= 0) {
|
||||
char *ptr = &buffer[0];
|
||||
int size_read = read (cpuinfo_fd, ptr, 1024);
|
||||
|
||||
while (size_read > 0) {
|
||||
if (strncmp (ptr, "bogomips\t: ", 11) != 0) {
|
||||
while ((size_read-- > 0) && (*ptr != '\n'))
|
||||
ptr++;
|
||||
size_read--;
|
||||
ptr++;
|
||||
continue;
|
||||
} else {
|
||||
ptr += 11;
|
||||
tsc_freq = atoll (ptr) * 1000000 / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
close (cpuinfo_fd);
|
||||
|
||||
return tsc_freq;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __BEOS__
|
||||
|
||||
# include <be/kernel/OS.h>
|
||||
|
||||
/*
|
||||
* Get timestamp counter frequency from the kernel
|
||||
*/
|
||||
static frame_time_t beos_get_tsc_freq (void)
|
||||
{
|
||||
system_info info;
|
||||
get_system_info (&info);
|
||||
return info.cpu_clock_speed;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
frame_time_t apple_get_tsc_freq (void)
|
||||
{
|
||||
int sysctl_hw;
|
||||
char buffer[1024];
|
||||
uae_s64 tsc_freq = 0;
|
||||
|
||||
sysctl_hw = open ("sysctl -a hw", O_RDONLY);
|
||||
|
||||
if (sysctl_hw >= 0) {
|
||||
char *ptr = &buffer[0];
|
||||
int size_read = read (sysctl_hw, ptr, 1024);
|
||||
|
||||
while (size_read > 0) {
|
||||
if (strncmp (ptr, "hw.cpufrequency: ", 17) != 0) {
|
||||
while ((size_read-- > 0) && (*ptr != '\n'))
|
||||
ptr++;
|
||||
size_read--;
|
||||
ptr++;
|
||||
continue;
|
||||
} else {
|
||||
ptr += 17;
|
||||
tsc_freq = atoll (ptr) * 1000000 / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
close (sysctl_hw);
|
||||
|
||||
return tsc_freq;
|
||||
}
|
||||
#endif
|
||||
|
||||
static volatile frame_time_t last_time, best_time;
|
||||
static frame_time_t timebase;
|
||||
|
||||
static volatile int loops_to_go;
|
||||
|
||||
#if defined HAVE_SETITIMER || defined HAVE_ALARM
|
||||
# define USE_ALARM
|
||||
# ifndef HAVE_SETITIMER
|
||||
# define TIME_UNIT 1000000
|
||||
# else
|
||||
# define TIME_UNIT 100000
|
||||
# endif
|
||||
#else
|
||||
# define TIME_DELAY 200
|
||||
# define TIME_UNIT (TIME_DELAY*1000)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SYNC
|
||||
# define sync()
|
||||
#endif
|
||||
|
||||
#ifdef USE_ALARM
|
||||
static void set_the_alarm (void)
|
||||
{
|
||||
# ifndef HAVE_SETITIMER
|
||||
alarm (1);
|
||||
# else
|
||||
struct itimerval t;
|
||||
t.it_value.tv_sec = 0;
|
||||
t.it_value.tv_usec = TIME_UNIT;
|
||||
t.it_interval.tv_sec = 0;
|
||||
t.it_interval.tv_usec = TIME_UNIT;
|
||||
setitimer (ITIMER_REAL, &t, NULL);
|
||||
# endif
|
||||
}
|
||||
|
||||
static int first_loop = 1;
|
||||
|
||||
#ifdef __cplusplus
|
||||
static RETSIGTYPE alarmhandler(...)
|
||||
#else
|
||||
static RETSIGTYPE alarmhandler(int foo)
|
||||
#endif
|
||||
{
|
||||
frame_time_t bar;
|
||||
bar = read_processor_time ();
|
||||
if (! first_loop && bar - last_time < best_time)
|
||||
best_time = bar - last_time;
|
||||
first_loop = 0;
|
||||
if (--loops_to_go > 0) {
|
||||
signal (SIGALRM, alarmhandler);
|
||||
last_time = read_processor_time ();
|
||||
set_the_alarm ();
|
||||
} else {
|
||||
alarm (0);
|
||||
signal (SIGALRM, SIG_IGN);
|
||||
}
|
||||
}
|
||||
#endif /* USE_ALARM */
|
||||
|
||||
#include <setjmp.h>
|
||||
static jmp_buf catch_test;
|
||||
|
||||
#ifdef __cplusplus
|
||||
static RETSIGTYPE illhandler (...)
|
||||
#else
|
||||
static RETSIGTYPE illhandler (int foo)
|
||||
#endif
|
||||
{
|
||||
// rpt_available = 0;
|
||||
longjmp (catch_test, 1);
|
||||
}
|
||||
|
||||
int machdep_inithrtimer (void)
|
||||
{
|
||||
static int done = 0;
|
||||
|
||||
if (!done) {
|
||||
// rpt_available = 1;
|
||||
|
||||
write_log ("Testing the RDTSC instruction ... ");
|
||||
signal (SIGILL, illhandler);
|
||||
if (setjmp (catch_test) == 0)
|
||||
read_processor_time ();
|
||||
signal (SIGILL, SIG_DFL);
|
||||
write_log ("done.\n");
|
||||
|
||||
/* if (! rpt_available) {
|
||||
write_log ("Your processor does not support the RDTSC instruction.\n");
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
timebase = 0;
|
||||
#ifdef __linux__
|
||||
timebase = linux_get_tsc_freq ();
|
||||
#else
|
||||
#ifdef __BEOS__
|
||||
timebase = beos_get_tsc_freq ();
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
// timebase = apple_get_tsc_freq ();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (timebase <= 0) {
|
||||
write_log ("Calibrating TSC frequency...");
|
||||
flush_log ();
|
||||
|
||||
best_time = MAX_FRAME_TIME;
|
||||
loops_to_go = 5;
|
||||
|
||||
#ifdef USE_ALARM
|
||||
signal (SIGALRM, alarmhandler);
|
||||
#endif
|
||||
|
||||
/* We want exact values... */
|
||||
sync (); sync (); sync ();
|
||||
|
||||
#ifdef USE_ALARM
|
||||
last_time = read_processor_time ();
|
||||
set_the_alarm ();
|
||||
|
||||
while (loops_to_go != 0)
|
||||
uae_msleep (10);
|
||||
#else
|
||||
int i = loops_to_go;
|
||||
frame_time_t bar;
|
||||
|
||||
while (i-- > 0) {
|
||||
last_time = read_processor_time ();
|
||||
uae_msleep (TIME_DELAY);
|
||||
bar = read_processor_time ();
|
||||
if (i != loops_to_go && bar - last_time < best_time)
|
||||
best_time = bar - last_time;
|
||||
}
|
||||
#endif
|
||||
|
||||
timebase = best_time * (1000000.0 / TIME_UNIT);
|
||||
}
|
||||
|
||||
write_log ("TSC frequency: %f MHz\n", timebase / 1000000.0);
|
||||
done = 1;
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
frame_time_t machdep_gethrtimebase (void)
|
||||
{
|
||||
return timebase;
|
||||
}
|
||||
|
||||
int machdep_init (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle processor-specific cfgfile options
|
||||
*/
|
||||
void machdep_save_options (struct zfile *f, const struct uae_prefs *p)
|
||||
{
|
||||
// cfgfile_write (f, MACHDEP_NAME ".use_tsc=%s\n", p->use_processor_clock ? "yes" : "no");
|
||||
}
|
||||
|
||||
int machdep_parse_option (struct uae_prefs *p, const char *option, const char *value)
|
||||
{
|
||||
// return cfgfile_yesno (option, value, "use_tsc", &p->use_processor_clock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void machdep_default_options (struct uae_prefs *p)
|
||||
{
|
||||
}
|
Loading…
Reference in New Issue
Block a user