#if !defined (_syn68k_public_h_) #define _syn68k_public_h_ #include #include /* Decide whether we are big or little endian here. Add more machines as * they are supported. */ /* DO NOT COMMIT THE || 1 below or it will screw others. */ #if !defined(BIGENDIAN) && !defined(LITTLEENDIAN) # if defined(__BIG_ENDIAN__) || defined(m68k) || defined(mc68000) \ || defined(sparc) || defined(powerpc) || defined (__ppc__) # define BIGENDIAN /* ARDI naming convention, why rock the boat? */ # elif defined(__alpha) || defined(i860) || defined(vax) || defined(i386) \ || defined(__x86_64) || 1 # define LITTLEENDIAN # else # error "Unknown CPU type" # endif #endif /* Define this for CPUs that require n byte data be aligned * on addresses congruent to zero modulo n. The name "QUADALIGN" * is another ARDI convention, why rock the boat? */ /* * Alpha not quad aligned right now because that breaks Mat's code and the * alpha can get by, for now. */ /* DO NOT COMMIT the && 0 below or it will screw others */ #if !defined (QUADALIGN) && 0 # if defined(sparc) || /* defined(__alpha) || */ defined (i860) || defined(mips) # define QUADALIGN # elif !defined(m68k) && !defined(mc68000) && !defined(i386) \ && !defined(vax) && !defined(__alpha) && !defined(powerpc) \ && !defined (__ppc__) && !defined(__x86_64) # error Unknown CPU type # endif #endif /* Turn this on if you want to enable destroying only blocks with checksum * mismatches. */ #define CHECKSUM_BLOCKS /* Turn this on if you want syn68k to poll for interrupts, instead of * being interrupted by the real OS. */ #define SYNCHRONOUS_INTERRUPTS /* Turn this on if you want to let the BIOS event wait manage the low * memory interrupt flag. */ #if 0 && defined (MSDOS) && defined (SYNCHRONOUS_INTERRUPTS) # define USE_BIOS_TIMER #endif /* Portability typedefs for signed and unsigned n-bit numbers. */ /* TODO: just use the ones from stdint.h instead of our own */ typedef int8_t int8; typedef uint8_t uint8; typedef int16_t int16; typedef uint16_t uint16; typedef int32_t int32; typedef uint32_t uint32; typedef int64_t int64; typedef uint64_t uint64; /* Typedef for address in 68k space. */ typedef uint32 syn68k_addr_t; /* Integral type big enough to hold a pointer. Presumably we'll need to use * unsigned long long on machines with 64 bit pointers. */ typedef unsigned long ptr_sized_uint; /* Because a 68k register can be referenced as a byte, word, or int32, * we represent them as a union of these types. Although not guaranteed * to be portable, operations on appropriate byte- and word- union elements * should leave the other bytes unaffected (just as they do on the 68k). * on the 68k). */ #if defined (LITTLEENDIAN) typedef union { struct { uint32 n; } ul; struct { int32 n; } sl; struct { uint16 n, hi; } uw; struct { int16 n, hi; } sw; struct { uint8 n, b1, b2, b3; } ub; struct { int8 n, b1, b2, b3; } sb; } M68kReg; #else typedef union { struct { uint32 n; } ul; struct { int32 n; } sl; struct { uint16 hi, n; } uw; struct { int16 hi, n; } sw; struct { uint8 b3, b2, b1, n; } ub; struct { int8 b3, b2, b1, n; } sb; } M68kReg; #endif /* Function type that handles callbacks (and therefore traps). */ typedef syn68k_addr_t (*callback_handler_t)(syn68k_addr_t, void *); typedef struct { syn68k_addr_t callback_address; callback_handler_t func; void *arg; } TrapHandlerInfo; #if (defined(i386) || defined(m68k)) && !defined (NO_CCR_SPEEDUPS) #define CCR_ELEMENT_8_BITS #endif #if defined (CCR_ELEMENT_8_BITS) typedef uint8 CCRElement; /* So we can setb, etc. them directly. */ #else /* !CCR_ELEMENT_8_BITS */ typedef int32 CCRElement; #endif /* !CCR_ELEMENT_8_BITS */ typedef struct { syn68k_addr_t tag; const uint16 *code; } jsr_stack_elt_t; #define JSR_STACK_SIZE 8 typedef struct { M68kReg regs[16]; /* d0...d7 followed by a0...a7 */ CCRElement ccnz, ccn, ccc, ccv, ccx; /* 0 or non-0, NOT 0 or 1! */ #if defined (MINIMAL_CPU_STATE) uint8 filler[3]; /* So we can copy small cpu states w/out boundary cruft. */ #else /* !MINIMAL_CPU_STATE */ char *amode_p, *reversed_amode_p; /* Used in interpreter. */ #if !defined (USE_BIOS_TIMER) && defined (SYNCHRONOUS_INTERRUPTS) volatile int32 interrupt_status_changed; /* High bit set when interrupted. */ #endif jmp_buf *setjmp_buf; jsr_stack_elt_t jsr_stack[JSR_STACK_SIZE]; unsigned jsr_stack_byte_index; /* # of **BYTES** into jsr stack for top. */ volatile uint16 sr; /* Status register, except cc bits (low 5 bits) == 0. */ syn68k_addr_t vbr; /* Vector base register (in 68k address space). */ uint32 cacr, caar; /* Cache Control Register/Cache Address Register. */ uint32 usp, msp, isp; /* Various stack pointers. Whichever one is * currently in use can only be found in a7; * the value here will be outdated. */ volatile uint8 interrupt_pending[8]; /* 1 if interrupt pending. */ volatile TrapHandlerInfo trap_handler_info[64]; #endif /* !MINIMAL_CPU_STATE */ } CPUState; /* This lets us put syn68k.c's global register variable before the * inline functions in this file, since that is an error. */ #if defined (GLOBAL_REGISTER_DECLS) GLOBAL_REGISTER_DECLS #endif #define EM_DREG(X) (cpu_state.regs[X].ul.n) #define EM_AREG(X) (cpu_state.regs[8 + (X)].ul.n) #define EM_D0 EM_DREG (0) #define EM_D1 EM_DREG (1) #define EM_D2 EM_DREG (2) #define EM_D3 EM_DREG (3) #define EM_D4 EM_DREG (4) #define EM_D5 EM_DREG (5) #define EM_D6 EM_DREG (6) #define EM_D7 EM_DREG (7) #define EM_A0 EM_AREG (0) #define EM_A1 EM_AREG (1) #define EM_A2 EM_AREG (2) #define EM_A3 EM_AREG (3) #define EM_A4 EM_AREG (4) #define EM_A5 EM_AREG (5) #define EM_A6 EM_AREG (6) #define EM_A7 EM_AREG (7) #define EM_FP EM_A6 #define EM_SP EM_A7 /* We need a range of "magic" addresses where we know legitimate 68k * code will be stored. When code at those addresses is "executed" by * the 68k, we will instead take special actions. We want those * addresses to be dereferenceable so we'll overlay them over a big * block of legitimate memory that can never contain m68k code. * We'll start a few bytes into the array in case anyone examines * memory before the array. */ extern uint16 callback_dummy_address_space[]; #define CALLBACK_SLOP 16 #define MAGIC_ADDRESS_BASE \ ((syn68k_addr_t) US_TO_SYN68K((unsigned long) (&callback_dummy_address_space[CALLBACK_SLOP]))) #define MAGIC_EXIT_EMULATOR_ADDRESS (MAGIC_ADDRESS_BASE + 0) #define MAGIC_RTE_ADDRESS (MAGIC_ADDRESS_BASE + 2) /* Address bits that have meaning, for the CLEAN() macro, below. */ #define LEGAL_ADDRESS_BITS 0xFFFFFFFFUL /* Here is a macro to "clean" an address; if you make it mask out the * nasty bits, you risk a noticeable performance downgrade. */ #if 1 # define CLEAN(addr) ((ptr_sized_uint)(addr)) #else # define CLEAN(addr) (((ptr_sized_uint)(addr)) & LEGAL_ADDRESS_BITS) #endif /* TODO: see if get rid of need for SIZEOF_CHAR_P, since that's something that comes from config.h and we shouldn't require users of syn68k_public.h to require config.h */ #if !defined(SIZEOF_CHAR_P) #if !defined(__x86_64) # define SIZEOF_CHAR_P 4 #else # define SIZEOF_CHAR_P 8 #endif #endif #if SIZEOF_CHAR_P == 4 extern uint32 ROMlib_offset; #define SYN68K_TO_US(addr) ((uint16 *) ((unsigned long)addr + ROMlib_offset)) /* uint16 * only the default. */ #define US_TO_SYN68K(addr) (/*(syn68k_addr_t)*/(int32) (addr) - ROMlib_offset) #elif SIZEOF_CHAR_P == 8 extern uint64 ROMlib_offset; #define SYN68K_TO_US(addr) ((uint16 *) ((uint64)(uint32)addr + ROMlib_offset)) /* uint16 * only the default. */ #define US_TO_SYN68K(addr) ((uint32) ((long) (addr) - ROMlib_offset)) #else #error "SIZEOF_CHAR_P unknown" #endif /* These macros should not be used within Syn68k, but are needed in ROMlib for translations of addresses where it's important to preserve the address 0 as 0 */ #define SYN68K_TO_US_CHECK0(addr) ({ typeof(addr) t; t = addr; t ? SYN68K_TO_US(t) : (uint16 *) 0; }) #define US_TO_SYN68K_CHECK0(addr) ({ typeof(addr) t; t = addr; t ? US_TO_SYN68K(t) : (int32) 0; }) /* Macros for byte swapping + specifying signedness. On a big endian * machine, these macros are dummies and don't actually swap bytes. * You may wish to replace these with the most efficient inline assembly * you can get, as these macros are performance-critical. * The "_IFLE" suffix stands for "if little endian". */ /* Byte swapping macros. */ #define SWAPUB(val) ((uint8) (val)) /* Here for symmetry. */ #define SWAPSB(val) ((int8) (val)) #if defined (CWV) && defined (CLV) #define ROMlib_SwapShort(n) CWV ((uint16) (n)) #define ROMlib_SwapLong(n) CLV ((uint32) (n)) #define SWAPUW(n) CWV ((uint16) (n)) #define SWAPUL(n) CLV ((uint32) (n)) #elif defined(i386) static inline uint16 ROMlib_SwapShort (unsigned short us) __attribute__ ((const)); static inline uint16 ROMlib_SwapShort (unsigned short us) { uint16 retval; asm ("rorw $8,%w0" : "=r" (retval) : "0" (us) : "cc"); return retval; } static inline uint32 ROMlib_SwapLong (uint32 ul) __attribute__ ((const)); static inline uint32 ROMlib_SwapLong (uint32 ul) { uint32 retval; #if defined (NeXT) || defined (USE_BSWAP) || defined (ALWAYS_ON_I486) asm ("bswap %0" : "=r" (retval) : "0" (ul)); #else asm ("rorw $8,%w0\n\t" "rorl $16,%k0\n\t" "rorw $8,%w0" : "=r" (retval) : "0" (ul) : "cc"); #endif return retval; } # define SWAPUW(val) ROMlib_SwapShort(val) # define SWAPUL(val) ROMlib_SwapLong(val) #elif 0 && defined(__alpha) static inline unsigned short const ROMlib_SwapShort (unsigned short us) { unsigned short retval; asm("extbl %1, 1, $2\n\t" /* r2 = 0x0A */ "sll %1, 8, %0\n\t" /* %0 = 0xB0 */ "or %0, $2, %0" /* %0 = 0xBA */ : "=r" (retval) : "r" (us) : "$2"); return retval; } static inline uint32 const ROMlib_SwapLong (uint32 ul) { uint32 retval; asm("extbl %1, 3, $2\n\t" /* r2 = 0x000A */ "sll %1, 24, $3\n\t" /* r3 = 0xD000 */ "srl %1, 8, $5\n\t" /* r5 = 0x0ABC */ "and %1, 65280, %0\n\t" /* %0 = 0x00C0 */ "or $2, $3, $4\n\t" /* r4 = 0xD00A */ "and $5, 65280, $6\n\t" /* r6 = 0x00B0 */ "sll %0, 8, %0\n\t" /* %0 = 0x0C00 */ "or $4, $6, $7\n\t" /* r7 = 0xD0BA */ "or $7, %0, %0" /* %0 = 0xDCBA */ : "=r" (retval) : "r" (ul) : "$2", "$3", "$4", "$5", "$6", "$7"); return retval; } # define SWAPUW(val) ROMlib_SwapShort(val) # define SWAPUL(val) ROMlib_SwapLong(val) #elif defined(LITTLEENDIAN) #if defined(__GNUC__) # define SWAPUW(val) ({ uint16 _v = (val); (uint16) ((_v >> 8) | (_v << 8)); }) # define SWAPUL(val) \ ({ uint32 _v = (val); \ (uint32) ((_v >> 24) | (_v << 24) | ((_v >> 8) & 0xFF00) \ | ((_v & 0xFF00) << 8)); \ }) #else static uint16 _swapuw(uint16 v) { return (v >> 8) | (v << 8); } #define SWAPUW(val) _swapuw(val) static uint32 _swapul(uint32 v) { return (v >> 24) | (v << 24) | ((v >> 8) & 0xFF00) | ((v & 0xFF00) << 8); } #define SWAPUL(val) _swapul(val) #endif #define ROMlib_SwapShort(val) SWAPUW(val) #define ROMlib_SwapLong(val) SWAPUL(val) #endif #define SWAPSW(val) ((int16) SWAPUW (val)) #define SWAPSL(val) ((int32) SWAPUL (val)) #define SWAPUB_IFLE(n) ((uint8) (n)) /* Here for symmetry. */ #define SWAPSB_IFLE(n) ((int8) (n)) #if defined (BIGENDIAN) # define SWAPUW_IFLE(n) ((uint16) (n)) # define SWAPSW_IFLE(n) ((int16) (n)) # define SWAPUL_IFLE(n) ((uint32) (n)) # define SWAPSL_IFLE(n) ((int32) (n)) #else /* LITTLEENDIAN */ # define SWAPUW_IFLE(n) SWAPUW(n) # define SWAPSW_IFLE(n) SWAPSW(n) # define SWAPUL_IFLE(n) SWAPUL(n) # define SWAPSL_IFLE(n) SWAPSL(n) #endif /* The "slow" variants are here to facilitate compile-time reduction of * swapped constants. The non-slow versions may use inline assembly, which * the C compiler won't be able to deal with, but the slow versions are * guaranteed to use standard C operators. You would only want to use the * slow versions for swapping constants. */ #define SLOW_SWAPUB(val) ((uint8) (val)) /* Here for symmetry. */ #define SLOW_SWAPSB(val) ((int8) (val)) #if defined(__GNUC__) #define SLOW_SWAPUW(val) \ ({ uint16 _v = (val); (uint16) ((_v >> 8) | (_v << 8)); }) #else #define SLOW_SWAPUW(v) ((uint16) (((v) >> 8) | ((v) << 8))) #endif #define SLOW_SWAPSW(val) ((int16) SLOW_SWAPUW (val)) #if defined(__GNUC__) #define SLOW_SWAPUL(val) \ ({ uint32 _v = (val); \ (uint32) ((_v >> 24) | (_v << 24) | ((_v >> 8) & 0xFF00) \ | ((_v & 0xFF00) << 8)); \ }) #else #define SLOW_SWAPUL(v) ((uint32) (((v) >> 24) | \ ((v) << 24) | \ (((v) >> 8) & 0xFF00) | \ (((v) & 0xFF00) << 8))) #endif #define SLOW_SWAPSL(val) ((int32) SLOW_SWAPUL (val)) #define SLOW_SWAPUB_IFLE(n) ((uint8) (n)) /* Here for symmetry. */ #define SLOW_SWAPSB_IFLE(n) ((int8) (n)) #if defined (BIGENDIAN) # define SLOW_SWAPUW_IFLE(n) ((uint16) (n)) # define SLOW_SWAPSW_IFLE(n) ((int16) (n)) # define SLOW_SWAPUL_IFLE(n) ((uint32) (n)) # define SLOW_SWAPSL_IFLE(n) ((int32) (n)) #else /* LITTLEENDIAN */ # define SLOW_SWAPUW_IFLE(n) SLOW_SWAPUW(n) # define SLOW_SWAPSW_IFLE(n) SLOW_SWAPSW(n) # define SLOW_SWAPUL_IFLE(n) SLOW_SWAPUL(n) # define SLOW_SWAPSL_IFLE(n) SLOW_SWAPSL(n) #endif /* Handy memory access macros. These implicity refer to the 68k addr space except for the _US variants that refer to the native address space.*/ /* Memory reads. */ #define READUB(addr) (*(const uint8 *) SYN68K_TO_US (CLEAN (addr))) #define READUW(addr) SWAPUW_IFLE (*(const uint16 *)SYN68K_TO_US (CLEAN (addr))) #if defined (BIGENDIAN) && defined (QUADALIGN) # define READUL(addr) \ ({ const uint16 *_p = SYN68K_TO_US (CLEAN (addr)); \ (uint32) ((_p[0] << 16) | _p[1]); \ }) # define READUL_US(addr) \ ({ const uint16 *_p = CLEAN (addr); \ (uint32) ((_p[0] << 16) | _p[1]); \ }) #elif defined (BIGENDIAN) && !defined (QUADALIGN) # define READUL(addr) (*(uint32 *) SYN68K_TO_US (CLEAN (addr))) # define READUL_US(addr) (*(uint32 *) CLEAN (addr)) #elif !defined (BIGENDIAN) && defined (QUADALIGN) #if defined(__GNUC__) # define READUL(addr) \ ({ const uint8 *_p = (const uint8 *) SYN68K_TO_US (CLEAN (addr)); \ (uint32) ((_p[0] << 24) | (_p[1] << 16) | (_p[2] << 8) | _p[3]); \ }) # define READUL_US(addr) \ ({ const uint8 *_p = (const uint8 *) CLEAN (addr); \ (uint32) ((_p[0] << 24) | (_p[1] << 16) | (_p[2] << 8) | _p[3]); \ }) #else static uint32 _readul(syn68k_addr_t addr) { const uint8 *p; p = (const uint8 *) SYN68K_TO_US (CLEAN (addr)); return (uint32) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); } #define READUL(addr) _readul(addr) static uint32 _readul_us(syn68k_addr_t addr) { const uint8 *p; p = (const uint8 *) CLEAN (addr); return (uint32) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); } #define READUL_US(addr) _readul_us(addr) #endif #else /* !defined (BIGENDIAN) && !defined (QUADALIGN) */ # define READUL(addr) SWAPUL (*(uint32 *) SYN68K_TO_US (CLEAN (addr))) # define READUL_US(addr) SWAPUL (*(uint32 *) CLEAN (addr)) #endif #define READSB(addr) ((int8) READUB (addr)) #define READSW(addr) ((int16) READUW (addr)) #define READSL(addr) ((int32) READUL (addr)) /* Memory writes. */ #define WRITEUB(addr, val) (*(uint8 *) SYN68K_TO_US (CLEAN (addr)) = (val)) #if defined (BIGENDIAN) # define WRITEUW(addr, val) (*(uint16 *) SYN68K_TO_US (CLEAN (addr)) = (val)) #else # define WRITEUW(addr, val) \ (*(uint16 *) SYN68K_TO_US (CLEAN (addr)) = SWAPUW (val)) #endif #if defined (BIGENDIAN) && defined (QUADALIGN) # define WRITEUL(addr, val) \ do { uint32 _v = (val); \ uint16 *_p = (uint16 *) SYN68K_TO_US (CLEAN (addr)); \ _p[0] = _v >> 16; \ _p[1] = _v; \ } while (0) #elif defined (BIGENDIAN) && !defined (QUADALIGN) # define WRITEUL(addr, val) (*(uint32 *) (SYN68K_TO_US (CLEAN (addr))) = (val)) #elif !defined (BIGENDIAN) && defined (QUADALIGN) # define WRITEUL(addr, val) \ do { uint32 _v = (val); \ uint8 *_p = (uint8 *) SYN68K_TO_US (CLEAN (addr)); \ _p[0] = _v >> 24; \ _p[1] = _v >> 16; \ _p[2] = _v >> 8; \ _p[3] = _v; \ } while (0) #else /* !defined (BIGENDIAN) && !defined (QUADALIGN) */ # define WRITEUL(addr, val) \ (*(uint32 *) SYN68K_TO_US (CLEAN (addr)) = SWAPUL (val)) #endif #define WRITESB(addr, val) WRITEUB ((addr), (uint8) (val)) #define WRITESW(addr, val) WRITEUW ((addr), (uint16) (val)) #define WRITESL(addr, val) WRITEUL ((addr), (uint32) (val)) /* Pop instructions. */ #define POPUB() (EM_A7 += 2, READUB (EM_A7 - 2)) #define POPUW() (EM_A7 += 2, READUW (EM_A7 - 2)) #define POPUL() (EM_A7 += 4, READUL (EM_A7 - 4)) #define POPSB() ((int8) POPUB ()) #define POPSW() ((int16) POPUW ()) #define POPSL() ((int32) POPUL ()) #define POPADDR() POPUL() /* Push instructions */ #define PUSHUB(val) WRITEUB (EM_A7 -= 2, (val)) #define PUSHUW(val) WRITEUW (EM_A7 -= 2, (val)) #define PUSHUL(val) WRITEUL (EM_A7 -= 4, (val)) #define PUSHSB(val) PUSHUB ((uint8) (val)) #define PUSHSW(val) PUSHUW ((uint16) (val)) #define PUSHSL(val) PUSHUL ((uint32) (val)) #define PUSHADDR(val) PUSHUL (val) #if !defined (CALL_EMULATOR) #define CALL_EMULATOR(addr) \ do {PUSHADDR (MAGIC_EXIT_EMULATOR_ADDRESS); \ (interpret_code (hash_lookup_code_and_create_if_needed (addr)));} while (0) #endif /* Global struct describing the CPU state. */ extern CPUState cpu_state; /* I hate to put this here, but we want our interrupt polling to * be extremely fast so we can check for interrupts anywhere in * executor that might be time consuming. */ #if defined (SYNCHRONOUS_INTERRUPTS) #define M68K_TIMER_PRIORITY 4 #define M68K_TIMER_VECTOR (24 + M68K_TIMER_PRIORITY) #define INTERRUPT_STATUS_CHANGED (-1) #define INTERRUPT_STATUS_UNCHANGED 0x7FFFFFFF #if defined (USE_BIOS_TIMER) extern uint16 dos_memory_selector; extern uint32 dos_interrupt_flag_addr; # ifdef SYN68K_C /* If we're in syn68k.c, we know that %fs holds the dos mem selector value. */ # define FETCH_INTERRUPT_STATUS() \ ({ \ int32 n; \ asm ("movl %%fs:(%1),%0" \ : "=r" (n) \ : "r" (dos_interrupt_flag_addr)); \ n; \ }) # define SET_INTERRUPT_STATUS(n) \ asm ("movl %0,%%fs:(%1)" \ : : "g" (n), "r" (dos_interrupt_flag_addr)) # else /* !SYN68K_C */ /* Temporarily use %fs to reference DOS memory. */ # define FETCH_INTERRUPT_STATUS() \ ({ \ int32 n; \ asm ("pushl %%fs\n\t" \ "movw %2,%%fs\n\t" \ "movl %%fs:(%1),%0\n\t" \ "popl %%fs" \ : "=r" (n) \ : "r" (dos_interrupt_flag_addr), "g" (dos_memory_selector)); \ n; \ }) # define SET_INTERRUPT_STATUS(n) \ asm ("pushl %%fs\n\t" \ "movw %2,%%fs\n\t" \ "movl %0,%%fs:(%1)\n\t" \ "popl %%fs" \ : : "g" (n), "r" (dos_interrupt_flag_addr), \ "g" (dos_memory_selector)) # endif /* !SYN68K_C */ #else /* !USE_BIOS_TIMER */ #define FETCH_INTERRUPT_STATUS() cpu_state.interrupt_status_changed #define SET_INTERRUPT_STATUS(n) \ ((void) (cpu_state.interrupt_status_changed = (n))) #endif /* !USE_BIOS_TIMER */ #define INTERRUPT_PENDING() (FETCH_INTERRUPT_STATUS () < 0) #endif /* SYNCHRONOUS_INTERRUPTS */ /* Functions to be called from outside the emulator. */ extern void initialize_68k_emulator (void (*while_busy)(int), int native_p, uint32 trap_vector_storage[64], uint32 dos_int_flag_addr); #if defined (SYNCHRONOUS_INTERRUPTS) extern void interrupt_generate (unsigned priority); extern void interrupt_note_if_present (void); /* called from `host_interrupt_status_changed' assembly stub in host-native.c */ extern syn68k_addr_t interrupt_process_any_pending (syn68k_addr_t pc) asm ("_interrupt_process_any_pending"); #endif /* SYNCHRONOUS_INTERRUPTS */ extern void interpret_code (const uint16 *code); /* called from asm; hence the need for the asm label, see `host_interrupt_status_changed' stub asm in host-native.c */ extern const uint16 *hash_lookup_code_and_create_if_needed (syn68k_addr_t adr) asm ("_hash_lookup_code_and_create_if_needed"); extern unsigned long destroy_blocks (syn68k_addr_t low_m68k_address, uint32 num_bytes); extern syn68k_addr_t callback_install (callback_handler_t func, void *arbitrary_argument); extern void callback_remove (syn68k_addr_t m68k_address); extern void trap_install_handler (unsigned trap_number, callback_handler_t func, void *arbitrary_argument); extern void trap_remove_handler (unsigned trap_number); extern void *callback_argument (syn68k_addr_t callback_address); extern callback_handler_t callback_function (syn68k_addr_t callback_address); extern void dump_profile (const char *file); #if defined (CHECKSUM_BLOCKS) extern unsigned long destroy_blocks_with_checksum_mismatch (syn68k_addr_t low_m68k_address, uint32 num_bytes); #endif extern void m68kaddr (const uint16 *pc); #endif /* Not _syn68k_public_h_ */