/* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */

#define IN_REG68K_C

#include "generator.h"
#include "registers.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// not recommended for wxWidgets linkage
#ifdef USE_SETJMP
#include <setjmp.h>
#endif

#include "reg68k.h"
#include "cpu68k.h"
#include "ui.h"
#include "vars.h"

// __CYGWIN__ wrapper added by Ray Arachelian for LisaEm to prevent crashes in reg68k_ext exec
#ifdef __CYGWIN__
 uint32 reg68k_pc;
 uint32 *reg68k_regs;
 t_sr reg68k_sr;
#else
#if (!(defined(PROCESSOR_ARM) || defined(PROCESSOR_SPARC) || defined(PROCESSOR_INTEL) ))
uint32 reg68k_pc;
uint32 *reg68k_regs;
t_sr reg68k_sr;
#endif
#endif

#define LISA_REBOOTED(x)   { save_pram(); profile_unmount(); lisa_rebooted();     return x;}
#define LISA_POWEREDOFF(x) { save_pram(); profile_unmount(); lisa_powered_off();  return x;}


static int dbx=0;


static int insetjmpland=0;


static uint32 last_cpu68k_clocks=0;

static uint32 last_bus_error_pc=0;

static int    nmi_error_trap=0;
static uint32 last_nmi_error_pc=0;

static uint32 nmi_pc=0, nmi_addr_err=0, nmi_clk=0, nmi_stop=0;


uint16 InstructionRegister;
uint8  CPU_function_code;     // cpu function code state output bits (FC2/Fc1/FC0).  // fc2= supervisor mode, fc1/0=program/data access
                              //
                              // should set to CPU_function_code=(reg68k_sr.sr_struct.s<<2) | 1; for normal access
                              //               CPU_function_code=(reg68k_sr.sr_struct.s<<2) | 2; for execution/program access.
                              //

#define SET_CPU_FNC_DATA() {CPU_function_code=(reg68k_sr.sr_struct.s? 4:0) | 1;}
#define SET_CPU_FNC_CODE() {CPU_function_code=(reg68k_sr.sr_struct.s? 4:0) | 2;}


uint8  CPU_READ_MODE;         // 1=read, 0=write (for addr/bus error exceptions)

uint32 pc24=0, lastpc24=0, page;
static int loopy_vector=0;                  // prevent fetch from calling this again.




/*** forward references ***/
#ifdef DEBUG
void dumpmmu(uint8 c, FILE *out);
void validate_mmu_segments(char *from);
void printregs(FILE *buglog,char *tag);
void extprintregs(FILE *buglog,char *tag);

#endif

extern char *slrname(uint16 slr);       // from memory.c

// Make sure that the bitfield unions work correctly - if they're in the wrong order, they won't.  This double checks
// that ./configure got the right order.
//
void reg68k_sanity_check_bitorder(void)
{
  int bad=0; uint16 x;
  int64 i64;
  int32 i32;
  union
  {
    uint32 l;
    uint8  c[4];
  } e;


  union {
  struct {
  uint8 h:4;
  uint8 i0:1;
  uint8 i1:1;
  uint8 i2:1;
  uint8 i3:1;
  } hi;
  uint8 i;
  }bf;

  x=reg68k_sr.sr_int;

  reg68k_sr.sr_int=0x2700;
  #define IMSK (reg68k_sr.sr_struct.i0 | (reg68k_sr.sr_struct.i1<<1) | (reg68k_sr.sr_struct.i2<<2) )

   if (sizeof(reg68k_sr)!=2) {bad=1;
                              DEBUG_LOG(0,"expected reg68k_sr to be two bytes! it is %d instead!",sizeof(reg68k_sr));
                              messagebox("Sanity Check Failed! reg68k_sr is not 2 bytes!", "Compilation Failure!");
                             }

  if (sizeof(uint8)  !=1 ) {bad=1; DEBUG_LOG(0,"Size of uint8  is not 1"); messagebox("Sanity check failed sizeof(uint8)!=1","Sanity check failed");}
  if (sizeof(uint16) !=2 ) {bad=1; DEBUG_LOG(0,"Size of uint16 is not 2"); messagebox("Sanity check failed sizeof(uint16)!=2","Sanity check failed");}
  if (sizeof(uint32) !=4 ) {bad=1; DEBUG_LOG(0,"Size of uint32 is not 4"); messagebox("Sanity check failed sizeof(uint32)!=4","Sanity check failed");}
#ifdef uint64
  if (sizeof(uint64) !=8 ) {bad=1; DEBUG_LOG(0,"Size of uint64 is not 8"); messagebox("Sanity check failed sizeof(uint64)!=8","Sanity check failed");}
#endif

  if (sizeof(int8)  !=1 ) {bad=1; DEBUG_LOG(0,"Size of int8  is not 1"); messagebox("Sanity check failed sizeof(int8)!=1","Sanity check failed");}
  if (sizeof(int16) !=2 ) {bad=1; DEBUG_LOG(0,"Size of int16 is not 2"); messagebox("Sanity check failed sizeof(int16)!=2","Sanity check failed");}
  if (sizeof(int32) !=4 ) {bad=1; DEBUG_LOG(0,"Size of int32 is not 4"); messagebox("Sanity check failed sizeof(int32)!=4","Sanity check failed");}
#ifdef int64
  if (sizeof(int64) !=8 ) {bad=1; DEBUG_LOG(0,"Size of int64 is not 8"); messagebox("Sanity check failed sizeof(int64)!=8","Sanity check failed");}
#endif

  e.l=0xdeadbeef;
  #ifdef  WORDS_BIGENDIAN
    if (e.c[0]!=0xde && e.c[1]!=0xad && e.c[2]!=0xbe && e.c[3]!=0xef )
       {bad=1; DEBUG_LOG(0,"Endian Mismatch - BIGENDIAN defined, but fails test"); messagebox("Sanity check failed: BIGENDIAN defined, but fails test","Sanity check failed");}
  #else
    if (e.c[0]!=0xef && e.c[1]!=0xbe && e.c[2]!=0xad && e.c[3]!=0xde )
       {bad=1; DEBUG_LOG(0,"Endian Mismatch - LITTLE ENDIAN defined, but fails test"); messagebox("Sanity check failed: LITTLE ENDIAN defined, but fails test","Sanity check failed");}

  #endif

  i64=-1;
  i32=-1;

  i64=(i64>>1);
  i32=(i32>>1);

  if (i64!=-1) {bad=1; DEBUG_LOG(0,"64 bit signed right shift of -1 !=-1"); messagebox("Sanity check failed: 64 bit signed right shift of -1 !=-1","Sanity check failed");}
  if (i32!=-1) {bad=1; DEBUG_LOG(0,"32 bit signed right shift of -1 !=-1"); messagebox("Sanity check failed: 32 bit signed right shift of -1 !=-1","Sanity check failed");}

  bf.i=0xf3;

  if (sizeof(bf)!=1) {bad=1; DEBUG_LOG(0,"sizeof(uint8) bitfield!=1!"); messagebox("Sanity check failed: sizeof(uint8) bitfield!=1!","Sanity Check Failure!");}

  #ifdef BYTES_HIGHFIRST
  //  bf.i=f3 bf.hi.h=f bf.hi.i0,1,2,3=0 0 1 1
   if (bf.hi.h  !=15) {bad=1; DEBUG_LOG(0,"bitfield/BYTES_HIGHFIRST hi.h!=f");  messagebox("Sanity check failed: bitfield/BYTES_HIGHFIRST hi.h!=f ","Sanity Check Failure");}
   if (bf.hi.i0 !=0 ) {bad=1; DEBUG_LOG(0,"bitfield/BYTES_HIGHFIRST hi.i0!=0"); messagebox("Sanity check failed: bitfield/BYTES_HIGHFIRST hi.i0!=0","Sanity Check Failure");}
   if (bf.hi.i1 !=0 ) {bad=1; DEBUG_LOG(0,"bitfield/BYTES_HIGHFIRST hi.i1!=0"); messagebox("Sanity check failed: bitfield/BYTES_HIGHFIRST hi.i1!=0","Sanity Check Failure");}
   if (bf.hi.i2 !=1 ) {bad=1; DEBUG_LOG(0,"bitfield/BYTES_HIGHFIRST hi.i2!=1"); messagebox("Sanity check failed: bitfield/BYTES_HIGHFIRST hi.i2!=1","Sanity Check Failure");}
   if (bf.hi.i3 !=1 ) {bad=1; DEBUG_LOG(0,"bitfield/BYTES_HIGHFIRST hi.i3!=1"); messagebox("Sanity check failed: bitfield/BYTES_HIGHFIRST hi.i3!=1","Sanity Check Failure");}


  #else
   // bf.i=f3 bf.hi.h=3 bf.hi.i0,1,2,3=1 1 1 1
   if (bf.hi.h  !=3 ) {bad=1; DEBUG_LOG(0,"bitfield/!BYTES_HIGHFIRST hi.h!=3");  messagebox("Sanity check failed: bitfield/!BYTES_HIGHFIRST hi.h!=3","Sanity Check Failure");}
   if (bf.hi.i0 !=1 ) {bad=1; DEBUG_LOG(0,"bitfield/!BYTES_HIGHFIRST hi.i0!=1"); messagebox("Sanity check failed: bitfield/!BYTES_HIGHFIRST hi.i0!=1","Sanity Check Failure");}
   if (bf.hi.i1 !=1 ) {bad=1; DEBUG_LOG(0,"bitfield/!BYTES_HIGHFIRST hi.i1!=1"); messagebox("Sanity check failed: bitfield/!BYTES_HIGHFIRST hi.i1!=1","Sanity Check Failure");}
   if (bf.hi.i2 !=1 ) {bad=1; DEBUG_LOG(0,"bitfield/!BYTES_HIGHFIRST hi.i2!=1"); messagebox("Sanity check failed: bitfield/!BYTES_HIGHFIRST hi.i2!=1","Sanity Check Failure");}
   if (bf.hi.i3 !=1 ) {bad=1; DEBUG_LOG(0,"bitfield/!BYTES_HIGHFIRST hi.i3!=1"); messagebox("Sanity check failed: bitfield/!BYTES_HIGHFIRST hi.i3!=1","Sanity Check Failure");}
  #endif


  reg68k_sr.sr_int=0x2700; if (IMSK!=7)  {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 7 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'),        (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
  reg68k_sr.sr_int=0x2600; if (IMSK!=6)  {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 6 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'),        (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
  reg68k_sr.sr_int=0x2500; if (IMSK!=5)  {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 5 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'),        (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
  reg68k_sr.sr_int=0x2400; if (IMSK!=4)  {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 4 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'),        (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
  reg68k_sr.sr_int=0x2300; if (IMSK!=3)  {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 3 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'),        (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
  reg68k_sr.sr_int=0x2200; if (IMSK!=2)  {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 2 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'),        (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
  reg68k_sr.sr_int=0x2100; if (IMSK!=1)  {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 1 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'),        (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
  reg68k_sr.sr_int=0x2000; if (IMSK!=0)  {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 0 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'),        (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}

  reg68k_sr.sr_int=0x2000; if (!reg68k_sr.sr_struct.s)  {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expected Supervisor Bit on  %c%c%c%c%c%c%c imsk:%d ",(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'),        (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 )));  bad=1;}
  reg68k_sr.sr_int=0x0000; if ( reg68k_sr.sr_struct.s)  {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expected Supervisor Bit off %c%c%c%c%c%c%c imsk:%d ",(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'),        (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
  reg68k_sr.sr_int=0x2700; if (!reg68k_sr.sr_struct.s)  {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expected Supervisor Bit on  %c%c%c%c%c%c%c imsk:%d ",(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'),        (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 )));  bad=1;}
  reg68k_sr.sr_int=0x0700; if ( reg68k_sr.sr_struct.s)  {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expected Supervisor Bit off %c%c%c%c%c%c%c imsk:%d ",(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'),        (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}

  reg68k_sr.sr_int=x;


  if (bad) {
             messagebox("Sanity Check Failed! reg68k_sr int does not match bitfields!", "Compilation Failure!");
             EXIT(1938);
           }
}


char niceascii(char c)
{ c &=127;
 if (c<31) c|=32;
 if (c==127) c='.';
 return c;
}


void lisa_addrerror(uint32 addr);

char *getvector(int v);
static int atexitset=0;

// MMU Test Patterns.  1 assumes X flag is preset before. 2 assumes X=0
//                       0         1     2     3        4      5     6      7      8     9      10     11     12     13     14     15    16
uint16 mmupattern1[17]={0xa55a,0x4ab5,0x956b,0x2ad6,0x55ad,0xab5a,0x56b4,0xad69,0x5ad2,0xb5a5,0x6b4a,0xd695,0xad2a,0x5a55,0xb4ab,0x6956,0xd2ad};
uint16 mmupattern2[17]={0xa55a,0x4ab4,0x9569,0x2ad2,0x55a5,0xab4a,0x5694,0xad29,0x5a52,0xb4a5,0x694a,0xd295,0xa52a,0x4a55,0x94ab,0x2956,0x52ad};

static uint8 pending_vector_bitmap=0;

#ifdef DEBUG
extern void append_floppy_log(char *s);
#endif

// only two are available: empty or dual parallel
int get_nmi_pending_irq(void) {return 0;}

int get_exs2_pending_irq_empty(void) {return 0;}
int get_exs1_pending_irq_empty(void) {return 0;}
int get_exs0_pending_irq_empty(void) {return 0;}


int get_exs0_pending_irq_2xpar(void) { return (via[3].via[IFR]&via[3].via[IER])|((via[4].via[IFR]&via[4].via[IER]));}
int get_exs1_pending_irq_2xpar(void) { return (via[5].via[IFR]&via[5].via[IER])|((via[6].via[IFR]&via[6].via[IER]));}
int get_exs2_pending_irq_2xpar(void) { return (via[7].via[IFR]&via[7].via[IER])|((via[8].via[IFR]&via[8].via[IER]));}



// These is here in this file because they are shared IRQs, it belongs more in the via6522.c file but there is a
// videoirq and floppy component too, so it should be in a shared place.  Might as well be static inline for speed.

int get_irq1_pending_irq(void )
{
            // this is just a fixup for the COPS VIA, doesn't affect the rest of this.
            if (via[1].via[IER] & via[1].via[IFR] & 0x7f) via[1].via[IFR] |=0x80; else  via[1].via[IFR] &=0x7f;

            // IRQ1 is the only shared IRQ - Vertical Retrace, Floppy FDIR, and VIA2 (Parallel Port) all use it.
            // fix via IFR bit 0x80's so bit 7 is properly reflecting enabled IRQ's.  Correct these bits before checking.
            if (via[2].via[IER] & via[2].via[IFR] & 0x7f) via[2].via[IFR] |=0x80; else  via[2].via[IFR] &=0x7f;

            DEBUG_LOG(0,"IRQ1: vertical:%d fdir:%d VIA2-IFR bits:%s%s%s%s%s%s%s%s returning:%d",
               (verticallatch && (videoirq & 1)), floppy_FDIR ,
               (via[2].via[IFR] &  VIA_IRQ_BIT_CA2         ? "0:CA2 ": " "   ),
               (via[2].via[IFR] &  VIA_IRQ_BIT_CA1         ? "1:CA1 ": " "   ),
               (via[2].via[IFR] &  VIA_IRQ_BIT_SR          ? "2:SR  ": " "   ),
               (via[2].via[IFR] &  VIA_IRQ_BIT_CB2         ? "3:CB2 ": " "   ),
               (via[2].via[IFR] &  VIA_IRQ_BIT_CB1         ? "4:CB1 ": " "   ),
               (via[2].via[IFR] &  VIA_IRQ_BIT_T2          ? "5:T2  ": " "   ),
               (via[2].via[IFR] &  VIA_IRQ_BIT_T1          ? "6:T1  ": " "   ),
               (via[2].via[IFR] &  VIA_IRQ_BIT_SET_CLR_ANY ? "7:ANY ": "None"),

               ((verticallatch && (videoirq & 1)) || floppy_FDIR || (via[2].via[IFR] & 0x80)));



            return ((verticallatch && (videoirq & 1)) || floppy_FDIR || (via[2].via[IFR] & 0x80)); //was vertical, not verticallatch
}


#ifdef PARANOID
#define HIGHEST(x) (highest=((x)>highest ? (x):highest))
#else
#define HIGHEST(x) (highest=(x))
#endif
// re/calculates the pending_vector_bitmap and returns the highest IRQ to be serviced.

// this is mirrored from cops.c
static inline int get_cops_pending_irq(void )
{
     // bit 7 of IFR indicates whether any VIA1 IRQ's have been fired, so check to see if any of them have, then set bit 7
     if (via[1].via[IER] & via[1].via[IFR] & 0x7f)
     {
       via[1].via[IFR] |=0x80;
       return 0x80;
     }

     via[1].via[IFR] &=0x7f;
     return 0;
}





static inline uint8 get_pending_vector(void)
{
  int highest=0;


  //---- recalculated pending vector bitmap, and find the highest IRQ to be serviced  ------------


  #ifdef DEBUG
  pending_vector_bitmap=                                         // no such thing as IRQ0 on 68000
   (get_irq1_pending_irq() ? BIT1:0) |                           // VTIR/FDIR/VIA2   IRQ1
   (get_cops_pending_irq() ? BIT2:0) |                           // COPS/VIA1        IRQ2
   (get_exs2_pending_irq() ? BIT3:0) |                           // Expansion slot 2 IRQ3
   (get_exs1_pending_irq() ? BIT4:0) |                           // Expansion slot 1 IRQ4
   (get_exs0_pending_irq() ? BIT5:0) |                           // Expansion slot 0 IRQ5
   (get_scc_pending_irq()  ? BIT6:0) |                           // SCC              IRQ6
   (get_nmi_pending_irq()  ? BIT7:0) ;                           // NMI              IRQ7

    highest=highest_bit_num(pending_vector_bitmap);
    if (highest==0xff) highest=0;

   DEBUG_LOG(0,"IRQ1:: vertical retrace:%d floppy_FDIR:%d via2_IFR:%02x  IRQ2:via1_IFR:%02x",
           (vertical && (videoirq & 1)),
           floppy_FDIR,
           via[2].via[IFR],
           via[1].via[IFR]);

   if (highest==1 && floppy_FDIR && (!((regs.sr.sr_int>>8)&7))) append_floppy_log("get_pending_vector:Floppy FDIR IRQ1 is about to be taken if called\n");

   DEBUG_LOG(0,"Next pending vector is:%d, map is:%s%s%s%s%s%s%s",highest,
        ((pending_vector_bitmap & BIT1)  ? "v1":"."),
        ((pending_vector_bitmap & BIT2)  ? "v2":"."),
        ((pending_vector_bitmap & BIT3)  ? "v3":"."),
        ((pending_vector_bitmap & BIT4)  ? "v4":"."),
        ((pending_vector_bitmap & BIT5)  ? "v5":"."),
        ((pending_vector_bitmap & BIT6)  ? "v6":"."),
        ((pending_vector_bitmap & BIT7)  ? "v7":".") );


  #else

  if       (get_nmi_pending_irq()  ) {highest=7;pending_vector_bitmap=BIT7;}
  else if  (get_scc_pending_irq()  ) {highest=6;pending_vector_bitmap=BIT6;}
  else if  (get_exs0_pending_irq() ) {highest=5;pending_vector_bitmap=BIT5;}
  else if  (get_exs1_pending_irq() ) {highest=4;pending_vector_bitmap=BIT4;}
  else if  (get_exs2_pending_irq() ) {highest=3;pending_vector_bitmap=BIT3;}
  else if  (get_cops_pending_irq() ) {highest=2;pending_vector_bitmap=BIT2;}
  else if  (get_irq1_pending_irq() ) {highest=1;pending_vector_bitmap=BIT1;}

  #endif



  return highest;
}


#ifdef DEBUG
static char templine[1024];
#endif

#define IS_VECTOR_AVAILABLE_INT(avno) (  ((reg68k_sr.sr_int >> 8) & 7)<(avno)  || (avno)==7)
#define IS_VECTOR_AVAILABLE_EXT(avno) (  ((regs.sr.sr_int   >> 8) & 7)<(avno)  || (avno)==7)

int is_vector_available(int avno)
{
   if (insetjmpland) return (IS_VECTOR_AVAILABLE_INT(avno));
   return IS_VECTOR_AVAILABLE_EXT(avno);
}




static inline void fire_pending_external_autovector(void)
{
 uint8 i=get_pending_vector();
 DEBUG_LOG(0,"Firing pending IRQ:%d if it meets the mask",i);


 if (IS_VECTOR_AVAILABLE_EXT(i))
    {
    #ifdef DEBUG
    snprintf(templine,1024,"fire_pending_ext_av:Firing IRQ1 while floppy_FDIR is set. mask:%d",((regs.sr.sr_int>>8) & 7) );
    if (i==1 && floppy_FDIR) append_floppy_log(templine);
    #endif

    reg68k_external_autovector(i);

    }
}

static inline void fire_pending_internal_autovector(void)
{
 uint8 i=get_pending_vector();
 DEBUG_LOG(0,"Firing pending IRQ:%d if it meets the mask",i);
 if (IS_VECTOR_AVAILABLE_INT(i))
     {
       #ifdef DEBUG
       snprintf(templine,1024,"fire_pending_int_av:Firing IRQ1 while floppy_FDIR is set. mask:%d",((reg68k_sr.sr_int>>8) & 7) );
       if (i==1 && floppy_FDIR) append_floppy_log("fire_pending_int_av:Firing IRQ1 while floppy_FDIR is set");
       #endif
       reg68k_internal_autovector(i);
     }
 #ifdef DEBUG
 else
    {
     DEBUG_LOG(0,"Could not fire IRQ:%d because it did not meet the mask.",i);
    }
 #endif

}

#ifdef DEBUG


void check_mmu_pattern(uint32 x)
{
 int i,found=0;

 for (i=0; i<17; i++)
   {
    if (x==mmupattern1[i])
            {found=1; fprintf(buglog,"MMUPATTERN: %4x found at %2d in 1 con:%d @pc=%08x a0=%08x reg#:%d\n",mmupattern1[i],i,1+(segment1|segment2),pc24,reg68k_regs[8],reg68k_regs[8]>>17); break;}
    if (x==mmupattern2[i]) {found=2; fprintf(buglog,"MMUPATTERN: %4x found at %2d in 2 con:%d @pc=%08x a0=%08x reg#:%d\n",mmupattern2[i],i,1+(segment1|segment2),pc24,reg68k_regs[8],reg68k_regs[8]>>17); break;}
   }
   if ( !found) fprintf(buglog,"MMUPATTERN: %4x not found        con:%d @pc=%08x a0=%08x reg#:%d\n",x,1+(segment1|segment2),pc24,reg68k_regs[8],reg68k_regs[8]>>17);
}

void dumpmmupage(uint8 c, uint8 i, FILE *out)
{
    char s[1024];

    int16 pagestart, pageend;
    lisa_mem_t rfn, wfn;
    uint32 mymaxlisaram=maxlisaram;

    if (maxlisaram==1024*1024) mymaxlisaram+=0x80000;

    get_slr_page_range(c,i,&pagestart,&pageend,&rfn,&wfn);
    fprintf(out,"mmu[%d][%d].slr:%04x in->(%08x-%08x)  base:%08x->sor:%04x %s ch:%d pgrange:%d-%d arange: out-> %08x-%08x  r/wfn:%d:%d\n",
        c,i,
             mmu_all[c][i].slr,
             i<<17,
             (i<<17) | 0x1FFFF,

        mmu_all[c][i].sor<<9,mmu_all[c][i].sor,
        printslr(s,1024,mmu_all[c][i].slr),
        mmu_all[c][i].changed,pagestart,pageend,

        ((((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)),
        (((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511)),rfn,wfn    );

    if ((unsigned)(((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)>mymaxlisaram)
            {fprintf(out,"**** START RANGE OVER MAXLISARAM (%08x)!!!!!! chopped to 2mb it's:%08x, unchopped:%08x****\n\n",mymaxlisaram,
            (((((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)) & TWOMEGMLIM),
            (((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)    );}

    if ((unsigned)((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511)>mymaxlisaram)
            {fprintf(out,"**** END RANGE OVER MAXLISARAM (%08x)!!!!!! chopped to 2mb it's:%08x, unchopped:%08x****\n\n",mymaxlisaram,
            (((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511) & TWOMEGMLIM),
            (((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511))  );}


}

void dumpmmu(uint8 c, FILE *out)
{
    //char s[1024];
    int i,f;

    //int16 pagestart, pageend;
    //lisa_mem_t rfn, wfn;

    fprintf(out,"\nmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm dump_mmu mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm\n\n");

	for (i=0; i<128; i++)
	{
        dumpmmupage(c,i,out);
        // keep,might want to re-enable this later
        /*
        get_slr_page_range(c,i,&pagestart,&pageend,&rfn,&wfn);
        fprintf(out,"mmu[%d][%d].slr:%04x in->(%08x-%08x)  base:%08x->sor:%04x %s ch:%d pgrange:%d-%d arange: out-> %08x-%08x  r/wfn:%d:%d\n",
            c,i,
                 mmu_all[c][i].slr,
                 i<<17,
                 (i<<17) | 0x1FFFF,

            mmu_all[c][i].sor<<9,mmu_all[c][i].sor,
            printslr(s,1024,mmu_all[c][i].slr),
            mmu_all[c][i].changed,pagestart,pageend,

            ((((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)),
            (((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511)),rfn,wfn    );

        // is this +i before  + pagestart i.e i+pagestart) and i+pageend) needed/allowed here?
        if ((unsigned)(((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)>maxlisaram)
                {fprintf(out,"**** START RANGE OVER MAXLISARAM (%08x)!!!!!! chopped to 2mb it's:%08x, unchopped:%08x****\n\n",maxlisaram,
                (((((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)) & TWOMEGMLIM),
                (((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)    );}

        if ((unsigned)((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511)>maxlisaram)
                {fprintf(out,"**** END RANGE OVER MAXLISARAM (%08x)!!!!!! chopped to 2mb it's:%08x, unchopped:%08x****\n\n",maxlisaram,
                (((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511) & TWOMEGMLIM),
                (((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511))  );}
        */
	}

    fflush(out);
    fprintf(out,"\n\n");
    for ( i=0; i<32768; i++)
    {
       fprintf(out,"%08x-%08x mmu[%d] mmu_t[%d][%04x].addr=%08x rfn=%s wfn=%s ipct:%s out:%08x-%08x",
            (i*512),(i*512)+511,(i*512)>>17,
            c,i,
            mmu_trans_all[c][i].address,
            mspace(mmu_trans_all[c][i].readfn),
            mspace(mmu_trans_all[c][i].writefn),
            (mmu_trans_all[c][i].table ? "yes":"no"),
            ((i*512)+mmu_trans_all[c][i].address),((i*512)+511+mmu_trans_all[c][i].address)
            );

            // 1000000000000000
            // 5432109876543210
            if (mmu_trans_all[c][i].readfn==sio_mmu)
            {
                f=rmmuslr2fn(mmu_all[c][i>>8].slr,i);
                fprintf(out,"mmu_sio: (%d) %s",f,mspace(f));
            }
       fprintf(out,"\n");
    }
    fflush(out);
}


void dumpallmmu(void)
{
    //long i;
    FILE *out;
    static char filename[128];
    static int instance;

    debug_log_enabled=1;
    #ifdef DEBUG
    debug_on("mmu-dump");
    #endif

    instance++;
    snprintf(filename,128,"/log/lisaem-output-mmu-%08x-%d.txt",pc24,instance);
    DEBUG_LOG(0,filename);
    out=fopen(filename,"wt");

    //fprintf(out,"SRC::init_7E70SLR is set to: r/w %04x/%04x\n",mmu_trans_all[0][0x7e70].readfn,mmu_trans_all[0][0x7e70].writefn);

    //dump_scc();
    #ifdef DEBUG
    if (insetjmpland) printregs(out,"");
    #endif
    dumpmmu(0,out); dumpmmu(1,out); dumpmmu(2,out); dumpmmu(3,out); dumpmmu(4,out);

    //if (insetjmpland) printregs(buglog,"");

    fclose(out);
}


#endif



unsigned int reg68k_external_step(void)
{
	static t_ipc ipc;
	static t_iib *piib;
    static unsigned long clks;

  /* !!! entering global register usage area !!! */
    #ifdef USE_SETJMP
	jmp_buf jb;


    if (!setjmp(jb))
    #endif
    {
    /* move PC and register block into global processor register variables */
		reg68k_pc = regs.pc;
		reg68k_regs = regs.regs;
        reg68k_sr.sr_int = regs.sr.sr_int;

        regs.pending = get_pending_vector();
		if (regs.pending && ((reg68k_sr.sr_int >> 8) & 7) < regs.pending)
			reg68k_internal_autovector(regs.pending);

		if (!(piib = cpu68k_iibtable[fetchword(reg68k_pc)]))
            DEBUG_LOG(1,"Invalid instruction @ %08X\n", reg68k_pc); // RA

       #if DEBUG
       if (!piib) DEBUG_LOG(0,"about to pass NULL IIB");
       #endif

        cpu68k_ipc(reg68k_pc, piib,&ipc);
        if (!abort_opcode)
           cpu68k_functable[fetchword(reg68k_pc) * 2 + 1] (&ipc);
    /* restore global registers back to permanent storage */
        regs.pc = reg68k_pc; regs.sr = reg68k_sr;
        #ifdef USE_SETJMP
		longjmp(jb, 1);
        #endif
	}
    cpu68k_clocks += ipc.clks;
    DEBUG_LOG(0,"cpu68k_clocks:%016llx this opcode:%d",cpu68k_clocks,ipc.clks);
    return clks;                  /* number of clocks done */
}

uint32 getreg(uint8 regnum)  //16=pc, 17=sp 0=7Dregs 8-15Aregs
{
    if (!insetjmpland)
            {
                if (regnum==16) return regs.pc;
                if (regnum==17) return regs.sp;
                if (regnum<16 ) return regs.regs[regnum];

            }

    else   {
                if (regnum==16) return reg68k_pc;
                if (regnum==17) return regs.sp;
                if (regnum<16 ) return reg68k_regs[regnum];
           }
    return 0xdeadbeef;

}


#ifdef DEBUG
void printregs(FILE *buglog,char *tag)
{


    if (!debug_log_enabled) return;
    if (!insetjmpland) {extprintregs(buglog,tag); return;}

    fprintf(buglog,"%sD 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x %c%c%c%c%c%c%c imsk:%d pnd:%s%s%s%s%s%s%s (%d/%d/%s cx:%d)SRC:\n",tag,
		reg68k_regs[0], reg68k_regs[1], reg68k_regs[2], reg68k_regs[3], reg68k_regs[4],
		reg68k_regs[5], reg68k_regs[6], reg68k_regs[7],
		(reg68k_sr.sr_struct.t ? 't':'.'),
        (reg68k_sr.sr_struct.s ? 'S':'.'),
        (reg68k_sr.sr_struct.z ? 'z':'.'),
        (reg68k_sr.sr_struct.x ? 'x':'.'),
		(reg68k_sr.sr_struct.n ? 'n':'.'),
		(reg68k_sr.sr_struct.v ? 'v':'.'),
        (reg68k_sr.sr_struct.c ? 'c':'.'),
        ((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 )),

        (pending_vector_bitmap & 1) ? "1":"",
        (pending_vector_bitmap & 2) ? "2":"",
        (pending_vector_bitmap & 4) ? "3":"",
        (pending_vector_bitmap & 8) ? "4":"",
        (pending_vector_bitmap & 16) ? "5":"",
        (pending_vector_bitmap & 32) ? "6":"",
        (pending_vector_bitmap & 64) ? "7":"",

        segment1,segment2,start ? "START":"normal",context );

    fprintf(buglog,"%sA 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x SP:%08x PC:%08x SRC:\n\n",tag,
		reg68k_regs[8], reg68k_regs[9], reg68k_regs[10],reg68k_regs[11],reg68k_regs[12],
        reg68k_regs[13],reg68k_regs[14],reg68k_regs[15],regs.sp,reg68k_pc);
    fflush(buglog);
}

/*
		reg68k_pc = regs.pc;
		reg68k_regs = regs.regs;
		reg68k_sr = regs.sr;
 */
void extprintregs(FILE *buglog,char *tag)
{


    if (!debug_log_enabled) return;
    if (insetjmpland) {printregs(buglog,tag); return;}


                    // the SRC: at the end is so I can grep the output and see both registers and source code. :)
    fprintf(buglog,"%sD 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x %c%c%c%c%c%c%c irqmsk:%d  %d/%d/%d context:%d SRC:\n",tag,
        regs.regs[0], regs.regs[1], regs.regs[2], regs.regs[3], regs.regs[4],
        regs.regs[5], regs.regs[6], regs.regs[7],
        (regs.sr.sr_struct.t ? 't':'.'),
        (regs.sr.sr_struct.s ? 'S':'.'),
        (regs.sr.sr_struct.z ? 'z':'.'),
        (regs.sr.sr_struct.x ? 'x':'.'),
        (regs.sr.sr_struct.n ? 'n':'.'),
        (regs.sr.sr_struct.v ? 'v':'.'),
        (regs.sr.sr_struct.c ? 'c':'.'),
        ((regs.sr.sr_struct.i2 ? 4:0 )+(regs.sr.sr_struct.i1 ? 2:0 )+(regs.sr.sr_struct.i0 ? 1:0 )),
        segment1,segment2,start,context );

    fprintf(buglog,"%sA 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x SP:%08x PC:%08x SRC:\n\n",tag,
        regs.regs[8], regs.regs[9], regs.regs[10],regs.regs[11],regs.regs[12],
        regs.regs[13],regs.regs[14],regs.regs[15],regs.sp,regs.pc);
    fflush(buglog);
}
#endif


void dumpram(char *reason)
{
 FILE *ramdump;
 char filename[256];
 uint32 i,j; //,k;
 uint16 slr, sor; //, mfn;
 //uint32 a9 =((pc24) & 0x00ffffff)>>9;
 //uint32 a17=((pc24) & 0x00ffffff)>>17;
 uint32 mad; //filter; mtd;
 //lisa_mem_t fn;

 snprintf(filename,256,"/log/lisaem-output-ramdump-%s-%08x.%016llx",reason,pc24,cpu68k_clocks);
 ramdump=fopen(filename,"wt");

 fprintf(ramdump,"context:%d segment1:%d, segment2:%d, start:%d pc24:%08x\n\n",context,segment1,segment2,start,pc24);


 fprintf(ramdump,"ramsize:%08x, lastcx:%d, cx:%d seg1:%d, seg2:%d, start:%d, mmudirty:%08x,%08x,%08x,%08x,%08x\n",
        maxlisaram,
        lastcontext, context,
        segment1, segment2, start,
        mmudirty_all[0],mmudirty_all[1],mmudirty_all[2],mmudirty_all[3],mmudirty_all[4]);

 fprintf(ramdump,"diag1:%d, diag2:%d, soft:%d, hard:%d, vert:%d, vidlatch:%02x, lastvidlatch:%02x, vidlatchaddr:%08x, lastvidlatchadr:%08x",
        diag1, diag2,
        softmem,
        hardmem,
        vertical,
        videolatch, lastvideolatch,  videolatchaddress, lastvideolatchaddress);

        //videoramdirty,
        //videoximgdirty,

 fprintf(ramdump,"regs D 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x SR:%02x %c%c%c%c%c%c%c irqmsk:%d  %d/%d/%d context:%d\n",
		reg68k_regs[0], reg68k_regs[1], reg68k_regs[2], reg68k_regs[3], reg68k_regs[4],
        reg68k_regs[5], reg68k_regs[6], reg68k_regs[7], reg68k_sr.sr_int,
		(reg68k_sr.sr_struct.t ? 't':'.'),
        (reg68k_sr.sr_struct.s ? 'S':'.'),
        (reg68k_sr.sr_struct.z ? 'z':'.'),
        (reg68k_sr.sr_struct.x ? 'x':'.'),
		(reg68k_sr.sr_struct.n ? 'n':'.'),
		(reg68k_sr.sr_struct.v ? 'v':'.'),
        (reg68k_sr.sr_struct.c ? 'c':'.'),
        ((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 )),
        segment1,segment2,start,context );

 fprintf(ramdump,"regs A 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x SP:%08x PC:%08x\n\n\n",
		reg68k_regs[8], reg68k_regs[9], reg68k_regs[10],reg68k_regs[11],reg68k_regs[12],
        reg68k_regs[13],reg68k_regs[14],reg68k_regs[15],regs.sp,reg68k_pc);


 for (i=0; i<5; i++)
  for ( j=0; j<128; j++)
  {
    slr=mmu_all[i][j].slr;
    sor=mmu_all[i][j].sor;

    mad=((sor & 0x0fff)<<9) & TWOMEGMLIM;

  fprintf(ramdump,"mmu[%d][%3d].slr:%04x,sor:%04x  %08x-%08x::-->(%08x)  type::%s\n",
        i,j,slr,sor,((uint32)j<<17),((uint32)j<<17)+((1<<17)-1),mad,
        slrname(slr)
        );
 }
 fflush(ramdump);



 for ( i=0; i<maxlisaram; i+=16)
  {
   if (lisaram[i+0]|lisaram[i+1]|lisaram[i+2]| lisaram[i+3]| lisaram[i+4]| lisaram[i+5]| lisaram[i+6]| lisaram[i+7]|
        lisaram[i+8]|lisaram[i+9]|lisaram[i+10]|lisaram[i+11]|lisaram[i+12]|lisaram[i+13]|lisaram[i+14]|lisaram[i+15])
   fprintf(ramdump,"RAM %06x: %02x %02x %02x %02x %02x %02x %02x %02x:%02x %02x %02x %02x %02x %02x %02x %02x |%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
        i,
        lisaram[i+0],lisaram[i+1],lisaram[i+2], lisaram[i+3], lisaram[i+4], lisaram[i+5], lisaram[i+6], lisaram[i+7],
        lisaram[i+8],lisaram[i+9],lisaram[i+10],lisaram[i+11],lisaram[i+12],lisaram[i+13],lisaram[i+14],lisaram[i+15],
        ((lisaram[i+0 ]>' ' && lisaram[i+0 ]<127) ? lisaram[i+0 ]:'.'),
        ((lisaram[i+1 ]>' ' && lisaram[i+1 ]<127) ? lisaram[i+1 ]:'.'),
        ((lisaram[i+2 ]>' ' && lisaram[i+2 ]<127) ? lisaram[i+2 ]:'.'),
        ((lisaram[i+3 ]>' ' && lisaram[i+3 ]<127) ? lisaram[i+3 ]:'.'),
        ((lisaram[i+4 ]>' ' && lisaram[i+4 ]<127) ? lisaram[i+4 ]:'.'),
        ((lisaram[i+5 ]>' ' && lisaram[i+5 ]<127) ? lisaram[i+5 ]:'.'),
        ((lisaram[i+6 ]>' ' && lisaram[i+6 ]<127) ? lisaram[i+6 ]:'.'),
        ((lisaram[i+7 ]>' ' && lisaram[i+7 ]<127) ? lisaram[i+7 ]:'.'),
        ((lisaram[i+8 ]>' ' && lisaram[i+8 ]<127) ? lisaram[i+8 ]:'.'),
        ((lisaram[i+9 ]>' ' && lisaram[i+9 ]<127) ? lisaram[i+9 ]:'.'),
        ((lisaram[i+10]>' ' && lisaram[i+10]<127) ? lisaram[i+10]:'.'),
        ((lisaram[i+11]>' ' && lisaram[i+11]<127) ? lisaram[i+11]:'.'),
        ((lisaram[i+12]>' ' && lisaram[i+12]<127) ? lisaram[i+12]:'.'),
        ((lisaram[i+13]>' ' && lisaram[i+13]<127) ? lisaram[i+13]:'.'),
        ((lisaram[i+14]>' ' && lisaram[i+14]<127) ? lisaram[i+14]:'.'),
        ((lisaram[i+15]>' ' && lisaram[i+15]<127) ? lisaram[i+15]:'.')  );
  }


 fflush(ramdump);
 fclose(ramdump);
}



#ifdef DEBUG
char *get_rom_label(uint32 pc24)
{

if (!debug_log_enabled) return "";


switch ( pc24 & 0x00ffff)
{
case 0x0000:   return "BASE     ";
case 0x0008:   return "2BUSVCT   ";
case 0x000C:   return "3ADRVCT   ";
case 0x0010:   return "ILLVCT   ";
case 0x0014:   return "DIV0VCT  ";
case 0x0018:   return "CHKVCT   ";
case 0x001C:   return "TRAPVCT  ";
case 0x0020:   return "PRIVCT   ";
case 0x0024:   return "TRCVCT   ";
case 0x0028:   return "L10VCT   ";
case 0x002C:   return "L11VCT   ";
case 0x0030:   return "EXCPERR  ";
case 0x003A:   return "SAVEREGS ";
case 0x003E:   return "SAVEREG2 ";
case 0x0052:   return "SVCMSG   ";
case 0x0060:   return "SPURVCT  ";
case 0x0064:   return "LVL1VCT  ";
case 0x0068:   return "LVL2VCT  ";
case 0x006C:   return "LVL3VCT  ";
case 0x0070:   return "LVL4VCT  ";
case 0x0074:   return "LVL5VCT  ";
case 0x0078:   return "LVL6VCT  ";
case 0x007C:   return "LVL7V-NMI";
case 0x0080:   return "JMPTBL   ";
case 0x00C8:   return "SPIN     ";
case 0x00CA:   return "NMIEXCP??";
case 0x00F6:   return "BEGIN    ";
case 0x0152:   return "BEGIN2   ";
case 0x018A:   return "BEGIN3   ";
case 0x0194:   return "ROMTST   ";
case 0x019E:   return "DOSUM    ";
case 0x01B0:   return "MMUTST   ";
case 0x01D8:   return "MMUERR   ";
case 0x01E0:   return "MMULP    ";
case 0x0200:   return "TSTLOOP  ";
case 0x0202:   return "REGTST   ";
case 0x0216:   return "MMUINIT  ";
case 0x022A:   return "MMURW    ";
case 0x023C:   return "RWCHK1   ";
case 0x024C:   return "RWCHK2   ";
case 0x0254:   return "RWCHK3   ";
case 0x025E:   return "CHKBASE  ";
case 0x0270:   return "MMUACHK  ";
case 0x0286:   return "ACHK1    ";
case 0x0290:   return "MMUSET   ";
case 0x029C:   return "ACHK2    ";
case 0x02B0:   return "MADRERR  ";
case 0x02B4:   return "CHKRW    ";
case 0x02C2:   return "RWERR    ";
case 0x02C6:   return "SETMMU   ";
case 0x02E4:   return "LOADORG  ";
case 0x0316:   return "LOADLMT  ";
case 0x0348:   return "MMUTST2  ";
case 0x03F4:   return "MMUERR2  ";
case 0x03FA:   return "MMUERR3  ";
case 0x0408:   return "MMULPCHK ";
case 0x0410:   return "CONCHK   ";
case 0x043E:   return "CONOK    ";
case 0x0440:   return "START    ";
case 0x0446:   return "MEMSIZ   ";
case 0x045E:   return "CHKLO    ";
case 0x04BC:   return "SAVELO   ";
case 0x04CE:   return "TSTHI    ";
case 0x04E2:   return "CHKHI    ";
case 0x04FA:   return "SAVEHI   ";
case 0x0500:   return "WRAPXIT  ";
case 0x0502:   return "SIZXIT   ";
case 0x0508:   return "CHKMEM   ";
case 0x0554:   return "LOTONE   ";
case 0x0566:   return "RSTMMU   ";
case 0x0590:   return "REMAP    ";
case 0x05A4:   return "MAPINV   ";
case 0x05BA:   return "WRTMMU   ";
case 0x05D0:   return "READMMU  ";
case 0x0620:   return "MEMTST1  ";
case 0x0654:   return "TONEDLY  ";
case 0x066C:   return "INITMEM  ";
case 0x06A6:   return "INITVCT  ";
case 0x06AC:   return "SETVCTRS ";
case 0x06E2:   return "SETBUSVC ";
case 0x06EC:   return "MISC     ";
case 0x06F8:   return "IERR     ";
case 0x0704:   return "NMI      ";
case 0x0730:   return "NOTPE    ";
case 0x0736:   return "TRPERR   ";
case 0x0742:   return "BERR     ";
case 0x074E:   return "AERR     ";
case 0x0758:   return "EXCP0    ";
case 0x0764:   return "EXCP1    ";
case 0x0774:   return "SCCSET   ";
//case 0x0780:   return "VIA2CHK  ";
case 0x0780:   return "VIA2TST  ";
case 0x07AE:   return "VIA2VCT  ";
case 0x07B8:   return "VIATST   ";
case 0x07D0:   return "VIARW    ";
case 0x07F4:   return "VIAFAIL  ";
case 0x07F6:   return "VIARWEND ";
case 0x07FA:   return "CONSET   ";
case 0x0800:   return "CONOFF   ";
case 0x0802:   return "CONSET2  ";
case 0x0822:   return "SCRNTST  ";
case 0x086A:   return "SCRNERR  ";
case 0x086C:   return "SCRNOK   ";
case 0x0874:   return "SCRNSAV  ";
case 0x0886:   return "SETVLTCH ";
case 0x08A2:   return "VIA1TST  ";
//case 0x08A2:   return "INVTST   ";
case 0x08B0:   return "VIA1CHK  ";
case 0x08DC:   return "DSPCPURM ";
case 0x08EA:   return "COPSENBL ";
case 0x090A:   return "COPSBAD  ";
case 0x0916:   return "COPSVCT  ";
case 0x0918:   return "IOVCT    ";
case 0x0920:   return "CPSINIT  ";
case 0x093E:   return "TURNON   ";
case 0x0956:   return "COPSCMD  ";
case 0x09C2:   return "RSTSCAN  ";
case 0x09DC:   return "RST0     ";
case 0x09F0:   return "GET0     ";
case 0x09F6:   return "RST2     ";
case 0x0A06:   return "RST1     ";
case 0x0A38:   return "GETJMP   ";
case 0x0A3C:   return "RSTXIT   ";
case 0x0A52:   return "MSCHK    ";
case 0x0A60:   return "SCANERR  ";
case 0x0A66:   return "IOCERR   ";
case 0x0A6A:   return "SCANXIT  ";
case 0x0A7E:   return "GETDATA  ";
case 0x0AA2:   return "GETIT    ";
case 0x0AAA:   return "RSTKBD   ";
case 0x0AC4:   return "CLRRST   ";
case 0x0ACC:   return "DELAY_1  ";
case 0x0AD4:   return "DELAY5   ";
case 0x0ADC:   return "KBDDELAY ";
case 0x0AE2:   return "DELAY    ";
case 0x0AE8:   return "BEEP     ";
case 0x0AEE:   return "CLICK    ";
case 0x0AF6:   return "TONE     ";
case 0x0B06:   return "TONE2    ";
case 0x0B52:   return "SILENCE  ";
case 0x0B5A:   return "NOIO     ";
case 0x0B76:   return "NOIO2    ";
case 0x0B8E:   return "NOIO3    ";
case 0x0B96:   return "VIDTST   ";
case 0x0BA2:   return "VIDCHK   ";
case 0x0BD4:   return "VIDERR   ";
case 0x0BE0:   return "VIDXIT   ";
case 0x0BF6:   return "RDSERN   ";
case 0x0C1C:   return "GETBITS1 ";
case 0x0C50:   return "GETBITS2 ";
case 0x0C82:   return "GETBYTES ";
case 0x0CB2:   return "CHECKSUM ";
case 0x0CF8:   return "EXIT     ";
case 0x0D0A:   return "FINDSYNC ";
case 0x0D34:   return "GETNIBBL ";
case 0x0D58:   return "TAG      ";
case 0x0D5C:   return "PARTST   ";
case 0x0DD2:   return "PARERR   ";
case 0x0DE8:   return "PARXIT   ";
case 0x0DF4:   return "WWPERR   ";
case 0x0DF8:   return "VIA1VCT  ";
case 0x0E02:   return "MEMTST2  ";
case 0x0E0E:   return "MEMLOOP  ";
case 0x0E4E:   return "TSTDONE  ";
case 0x0E6A:   return "BASICTST ";
//case 0x0E6A:   return "RUNTESTS ";
case 0x0E6C:   return "CALL3    ";
case 0x0E84:   return "TSTINIT  ";
case 0x0E98:   return "SAVRSLT  ";
case 0x0EB0:   return "RAMTEST  ";
case 0x0EC0:   return "RAMRW    ";
case 0x0ECC:   return "RAMCHK2  ";
case 0x0EDE:   return "RAMNXT   ";
case 0x0EE6:   return "ADRTST   ";
case 0x0EF6:   return "ADRCHK   ";
case 0x0F00:   return "ADRCLR   ";
case 0x0F0C:   return "RDERR    ";
case 0x0F14:   return "PRTYINT1 ";
case 0x0F68:   return "TSTSTAT  ";
case 0x0F72:   return "PRTYINT2 ";
case 0x0FC6:   return "PRIXIT   ";
case 0x0FD0:   return "PCERR    ";
case 0x0FF0:   return "GETPADDR ";
case 0x1000:   return "IOTST    ";
case 0x1008:   return "SCCTEST  ";
case 0x101A:   return "VECTLOOP ";
case 0x1038:   return "B96DATA  ";
case 0x1048:   return "SETSCC   ";
case 0x1054:   return "LPTEST   ";
case 0x1058:   return "SCCLOOP  ";
case 0x1066:   return "SCCOUT   ";
case 0x106C:   return "SCCLOOP2 ";
case 0x107A:   return "SCCIN    ";
case 0x108A:   return "SCCLXIT  ";
case 0x108C:   return "SCCLERR  ";
case 0x108E:   return "SCCEXIT  ";
case 0x10BE:   return "WRITESCC ";
case 0x10CA:   return "INITBDAT ";
case 0x10CE:   return "INITB2   ";
case 0x10D0:   return "RSTSCC   ";
case 0x10EE:   return "SCCVCT   ";
case 0x110C:   return "DSKTST   ";
case 0x1174:   return "INTERR   ";
case 0x1180:   return "DSKXIT   ";
case 0x1186:   return "DSKVCT   ";
case 0x1198:   return "SETTYPE  ";
case 0x11C0:   return "COPSCHK  ";
case 0x11E2:   return "SCANCPS  ";
case 0x11EA:   return "KEYSCAN  ";
case 0x125E:   return "XLATE    ";
case 0x127A:   return "KEYTBL   ";
case 0x128B:   return "TBLEND   ";
case 0x128C:   return "CLKTST   ";
case 0x12A0:   return "READCLK  ";
case 0x12B2:   return "RDCLK0   ";
case 0x12D4:   return "RDCLK1   ";
case 0x12E2:   return "CLKERR   ";
case 0x12EE:   return "CONFIG   ";
case 0x12F6:   return "CONFIG2  ";
case 0x1306:   return "RDSLOTS  ";
case 0x1332:   return "NOCRD1   ";
case 0x1334:   return "SLOT2    ";
case 0x1350:   return "NOCRD2   ";
case 0x1352:   return "SLOT3    ";
case 0x136E:   return "NOCRD3   ";
case 0x1370:   return "CFGEXIT  ";
case 0x1380:   return "CHKID    ";
case 0x139A:   return "TSTCHK   ";
case 0x13AA:   return "TST2     ";
case 0x140E:   return "EXCHK    ";
case 0x145E:   return "IOCHK    ";
case 0x14EA:   return "ERRDISP  ";
case 0x14F8:   return "KBDCHK   ";
case 0x1514:   return "MEMCHK   ";
case 0x153C:   return "CHKMADR  ";
case 0x154C:   return "SCNRSLTS ";
case 0x1572:   return "MERRCHK  ";
case 0x1582:   return "MEMERR   ";
case 0x1590:   return "IOSCHK   ";
case 0x15C0:   return "TSTXIT   ";
case 0x15C4:   return "TSTXIT2  ";
case 0x15CC:   return "GOTOMON  ";
case 0x15DC:   return "PMVCT    ";
case 0x15E6:   return "OTHER    ";
case 0x1622:   return "DSPCODE  ";
case 0x1630:   return "DSPDEC   ";
case 0x1634:   return "GETDIG   ";
case 0x1668:   return "DSPCXIT  ";
case 0x166E:   return "OUTCHR   ";
case 0x1678:   return "OUTCH    ";
case 0x1696:   return "OUTNIB   ";
case 0x16A8:   return "ALPHA    ";
case 0x16B0:   return "DSPCH    ";
case 0x16B8:   return "NOTIFY   ";
case 0x16C8:   return "HIPTCH   ";
case 0x16CC:   return "LOPTCH   ";
case 0x16CE:   return "SETDUR   ";
case 0x16DE:   return "SYSOK    ";
case 0x16E2:   return "DOBOOT   ";
case 0x16E6:   return "BOOTCHK  ";
case 0x1754:   return "DVCECHK  ";
case 0x1818:   return "PMEXIT   ";
case 0x1820:   return "PMERR    ";
case 0x182E:   return "LSTCHK   ";
case 0x1836:   return "CHKPM    ";
case 0x184E:   return "SAV2PM   ";
case 0x187E:   return "WRTSUM   ";
case 0x188C:   return "VFYCHKSM ";
case 0x1890:   return "CKLOOP   ";
case 0x18AE:   return "CKXIT    ";
case 0x18B0:   return "EXPAND   ";
case 0x18D6:   return "SEARCH   ";
case 0x18F8:   return "BOOTMENU ";
case 0x1986:   return "ICONCHK  ";
case 0x19D6:   return "SCNSLTS  ";
case 0x19EE:   return "CHKS2    ";
case 0x1A00:   return "CHKS3    ";
case 0x1A14:   return "WT4BOOT  ";
case 0x1A36:   return "CHKPROFI ";
case 0x1A94:   return "DSPMNTRY ";
case 0x1AAA:   return "ICONMENU ";
case 0x1B44:   return "CHKSLOT  ";
case 0x1B68:   return "CHKICONS ";
case 0x1B94:   return "CHKSXIT  ";
case 0x1B9A:   return "RDSLT    ";
case 0x1BCC:   return "TWGBOOT  ";
case 0x1C24:   return "CLRINT   ";
case 0x1C2C:   return "DOREAD   ";
case 0x1C48:   return "RDRETRY  ";
case 0x1C6C:   return "RDSCTR1  ";
case 0x1C82:   return "STRTBOOT ";
case 0x1C98:   return "DSKTIMER ";
case 0x1C9A:   return "DSKCHK   ";
case 0x1CAA:   return "DSKBAD   ";
case 0x1CBC:   return "DSKOUT   ";
case 0x1CC0:   return "DSKDIS   ";
case 0x1CC4:   return "DSKERR   ";
case 0x1D0A:   return "TBOOTERR ";
case 0x1D0E:   return "DSKERR2  ";
case 0x1D14:   return "DSKERR3  ";
case 0x1D1C:   return "SAVEXCP  ";
case 0x1D2A:   return "BTERR    ";
case 0x1D46:   return "DSABLDSK ";
case 0x1D5C:   return "CHKDRIVE ";
case 0x1D70:   return "TWGRD    ";
case 0x1D76:   return "TWGREAD  ";
case 0x1DB4:   return "XFRHDR   ";
case 0x1DCE:   return "XFRDATA  ";
case 0x1DF0:   return "TWGOUT   ";
case 0x1DF2:   return "TWGERR   ";
case 0x1DFA:   return "TWGOK    ";
case 0x1DFE:   return "TWGRXIT  ";
case 0x1E04:   return "CMDCHK   ";
case 0x1E3E:   return "CHKFIN   ";
case 0x1E56:   return "EJCTDSK  ";
case 0x1E72:   return "CLRFDIR  ";
case 0x1E96:   return "CHKFDIR  ";
case 0x1EA6:   return "DSPWTICO ";
//case 0x1EA6:   return "WAITALRT ";
case 0x1EB0:   return "VCTRINIT ";
case 0x1ECE:   return "PROBOOT  ";
case 0x1EFC:   return "PBOOT    ";
case 0x1F10:   return "HDSKERR  ";
case 0x1F3A:   return "BOOTFAIL ";
case 0x1F3E:   return "BFAIL2   ";
case 0x1F5E:   return "HDERR2   ";
case 0x1F66:   return "HDERR3   ";
case 0x1F70:   return "PROREAD  ";
case 0x1F82:   return "CHKBSY   ";
case 0x1F90:   return "TRYRD    ";
case 0x1FD2:   return "RDDATA   ";
case 0x1FDE:   return "PROERR   ";
case 0x1FE6:   return "PROXIT   ";
case 0x1FEA:   return "PROXIT2  ";
case 0x1FF0:   return "PROINIT  ";
case 0x2032:   return "READIT   ";
case 0x2048:   return "STRTRD   ";
case 0x2060:   return "GETSTAT  ";
case 0x2074:   return "STRTXIT  ";
case 0x2076:   return "STAT01   ";
case 0x2092:   return "COPY6    ";
case 0x20A0:   return "COPY6LP  ";
case 0x20B2:   return "STATERR  ";
case 0x20B6:   return "STATXIT  ";
case 0x20BC:   return "FINDD2   ";
case 0x20CE:   return "GETRSP   ";
case 0x20DC:   return "RSPOK    ";
case 0x20DE:   return "SNDR1    ";
case 0x20E6:   return "FINDERR  ";
case 0x20F6:   return "FNDXIT   ";
case 0x20FC:   return "WFBSY    ";
case 0x2100:   return "WFBSY1   ";
case 0x210E:   return "SENDRSP  ";
case 0x2122:   return "WFNBSY   ";
case 0x212A:   return "WFNBSY2  ";
case 0x2132:   return "WFNBSY3  ";
case 0x2138:   return "WFNBSY1  ";
case 0x2146:   return "DOCRES   ";
case 0x215E:   return "IOSBOOT  ";
case 0x2186:   return "STATOK   ";
case 0x2194:   return "NOCRD    ";
case 0x219E:   return "INVID    ";
case 0x21A2:   return "BADBRD   ";
case 0x21A6:   return "SENDMSG  ";
case 0x21CC:   return "RDIOSLT  ";
case 0x21EA:   return "LOADPGM  ";
case 0x222A:   return "INVSUM   ";
case 0x222C:   return "SAVERR   ";
case 0x2234:   return "RDIOXIT  ";
case 0x223A:   return "CHKPASS  ";
case 0x2244:   return "CHKPAS2  ";
case 0x2250:   return "CLRPM    ";
case 0x229A:   return "CHKTIM   ";
case 0x22EA:   return "TWGCHK   ";
case 0x2344:   return "TSTERR   ";
case 0x2364:   return "DISINT   ";
case 0x2376:   return "WRTMSG   ";
case 0x238A:   return "CNTINC   ";
case 0x2398:   return "DSPTIM   ";
case 0x23BE:   return "NOCHG    ";
case 0x23E8:   return "SHUTDOWN ";
case 0x23FC:   return "DSCONT   ";
case 0x2444:   return "SELF     ";
case 0x2448:   return "SETERR1  ";
case 0x244C:   return "SETERR2  ";
case 0x244E:   return "DSPERR   ";
case 0x245E:   return "CMDERR   ";
case 0x2466:   return "TODSET   ";
case 0x247C:   return "SETXIT   ";
case 0x247E:   return "TWGTST   ";
case 0x249A:   return "TWGLOOP  ";
case 0x24C2:   return "TOOLONG  ";
case 0x24C4:   return "TERR     ";
case 0x24CA:   return "DSPCLK   ";
case 0x2510:   return "TWGDSP   ";
case 0x2534:

               if (debug_log_enabled)
                   {DEBUG_LOG(0,"Returning to Lisa POST Monitoring, so disabling debug now.");
                    debug_off();
                   }

               return "INITMON  ";
case 0x2544:   return "INIT1    ";
case 0x255C:   return "INIT2    ";
case 0x2570:   return "INIT3    ";
case 0x259C:   return "MONITOR  ";
case 0x25A4:   return "LEVEL1   ";
//case 0x25EC:   return "OTHRBTNS ";
case 0x25EC:   return "DOMENU   ";
case 0x262A:   return "GETL1    ";
case 0x2652:   return "DORESET  ";
case 0x265E:   return "CONTCHK  ";
case 0x26DA:   return "GETL1XIT ";
case 0x26DE:   return "LEV1LOOP ";
case 0x26E6:   return "GETERR   ";
case 0x26F0:   return "CLRSCRN  ";
case 0x26F2:   return "WRTSCRN  ";
case 0x2702:   return "READKEY  ";
case 0x270C:   return "SQUAWK   ";
case 0x271A:   return "KEYTOASC ";
case 0x273C:   return "LEVEL2   ";
case 0x2744:   return "DSPMENU  ";
case 0x274C:   return "GETLEV2  ";
case 0x27A0:   return "WRTMENU  ";
case 0x27D0:   return "DSPMENUB ";
case 0x2814:   return "MAKESVCW ";
case 0x2836:   return "DSPMEM   ";
case 0x285E:   return "RDCNT    ";
case 0x28A2:   return "SETMEM   ";
case 0x28C6:   return "RDDTA    ";
case 0x2908:   return "CALLRTN  ";
case 0x2934:   return "LOOPTST  ";
case 0x29C0:   return "MMUTSTE1 ";
case 0x29CA:   return "MEMTST3  ";
case 0x29DC:   return "LOOPTBL  ";
case 0x29F4:   return "VIDAJST  ";
case 0x2A26:   return "DRWHORZ  ";
case 0x2A40:   return "DRWVERT  ";
case 0x2A6C:   return "POWERCYC ";
case 0x2A74:   return "INVALID  ";
case 0x2A82:   return "LEV2LOOP ";
case 0x2A86:   return "INVXIT   ";
case 0x2A92:   return "PROMPT   ";
case 0x2ABA:   return "RDINPUT  ";
case 0x2AC4:   return "READIN   ";
case 0x2B08:   return "SCROLL   ";
case 0x2B50:   return "PUTLF    ";
case 0x2B6C:   return "PUTBS    ";
case 0x2B7A:   return "CLRIT    ";
case 0x2B86:   return "ENQKBD   ";
case 0x2B96:   return "GETCH    ";
case 0x2BA4:   return "GETA     ";
case 0x2BB2:   return "GETPARM  ";
case 0x2BB6:   return "READQ    ";
case 0x2BDC:   return "OKCH     ";
case 0x2BE8:   return "GETEXIT  ";
case 0x2BEE:   return "INVPARM  ";
case 0x2BF2:   return "GETXIT2  ";
case 0x2BF4:   return "CONVERT  ";
case 0x2C0A:   return "DBOXDSPL ";
case 0x2C28:   return "CLRDBOX  ";
case 0x2C46:   return "GETINPUT ";
case 0x2C4E:   return "GET1     ";
case 0x2C52:   return "CHKIT    ";
//case 0x002CBA:   return "GET2     ";
case 0x2CBA:   return "WAIT2    ";
case 0x2CBE:   return "CHKIT2   ";
case 0x2D0C:   return "GET3     ";
case 0x2D0E:   return "WAIT3    ";
case 0x2D38:   return "WT4INPUT ";
//case 0x2D38:   return "COPS0    ";
case 0x2D48:   return "COPS1    ";
case 0x2D5C:   return "COPS2    ";
case 0x2D9E:   return "COPS4    ";
case 0x2DBE:   return "READCOPS ";
case 0x2DD8:   return "POWEROFF ";
case 0x2E2A:   return "ENBLDRVS ";
case 0x2E46:   return "CHKPOSN  ";
case 0x2E5A:   return "GETNTRY  ";
case 0x2E9C:   return "CHKPXIT  ";
case 0x2EA2:   return "CHKINPUT ";
case 0x2EAC:   return "RDENTRY  ";
case 0x2EC2:   return "INVERT   ";
case 0x2F2A:   return "MOUSEMOV ";
case 0x2F42:   return "SCALE    ";
case 0x2F56:   return "FINE     ";
case 0x2F6C:   return "COARSE   ";
case 0x2F7C:   return "BOUNDS   ";
case 0x2FB2:   return "MOUSINIT ";
case 0x2FCC:   return "CURSORIN ";
case 0x2FEA:   return "CURSORHI ";
case 0x300E:   return "CURSORDI ";
case 0x30D6:   return "DRAWDESK ";
case 0x30DA:   return "CLRDESK  ";
case 0x30EE:   return "GRAY     ";
case 0x30F4:   return "GRAY1    ";
case 0x3106:   return "BLACKEN  ";
case 0x3108:   return "WHITEN   ";
case 0x3114:   return "CLRMENU  ";
case 0x3128:   return "PAINT_BO ";
//case 0x3128:   return "PAINTB1  ";
case 0x312E:   return "INVERSE  ";
case 0x3132:   return "CONT     ";
case 0x3136:   return "PAINTB2  ";
case 0x3148:   return "STARTOP  ";
case 0x314A:   return "MOVINST  ";
case 0x314E:   return "EXCLUSIV ";
case 0x3150:   return "COMPARE  ";
case 0x3156:   return "NEXTLINE ";
case 0x3164:   return "MAKEPCAL ";
case 0x3168:   return "MAKEALER ";
case 0x3180:   return "MAKETEST ";
case 0x31B2:   return "MAKEDBOX ";
case 0x31C6:   return "MAKEWIND ";
case 0x31E6:   return "MAKEBOX  ";
case 0x325A:   return "PAINTV1  ";
//case 0x325A:   return "PAINT_V  ";
case 0x326A:   return "PAINTBIT ";
case 0x327A:   return "MAKEBUTN ";
case 0x32F8:   return "DRAWBUTN ";
case 0x3342:   return "DRAWSIDE ";
case 0x336A:   return "MAKEMENU ";
case 0x33B8:   return "WRITETIT ";
case 0x3406:   return "GETROWCO ";
case 0x3418:   return "GETLENGT ";
case 0x3424:   return "DSPRGICO ";
case 0x342C:   return "OUTPUT   ";
case 0x3432:   return "LOOP0    ";
case 0x3438:   return "LOOP1    ";
case 0x343A:   return "LOOP2    ";
case 0x3450:   return "DSPNUMIC ";
case 0x3464:   return "DSPNUM   ";
case 0x34DA:   return "DSPERRIC ";
case 0x34EC:   return "DSPBAD   ";
case 0x34FA:   return "MRGICON  ";
case 0x352C:   return "DSPALRTI ";
case 0x3556:   return "DSPQICON ";
case 0x3574:   return "INVICON  ";
case 0x3588:   return "DSPCPU   ";
case 0x3592:   return "DSPMBRD  ";
case 0x359C:   return "DSPIOB   ";
case 0x35A6:   return "DSPXCRD  ";
case 0x35AE:   return "DODSPLY  ";
case 0x35B6:   return "CHKCPU   ";
case 0x35BE:   return "CHKMBRD  ";
case 0x35C6:   return "CHKIOBRD ";
case 0x35CE:   return "CHKXCRD  ";
case 0x35D4:   return "DSPCHECK ";
case 0x35E2:   return "DSPICON  ";
case 0x35EC:   return "DLOOP    ";
case 0x35F2:   return "MLOOP    ";
case 0x35FC:   return "BLACK    ";
case 0x35FE:   return "CHECK    ";
case 0x360A:   return "DONE     ";
case 0x361A:   return "XLOOP    ";
case 0x3634:   return "DSPSTRIN ";
case 0x3686:   return "DSPALL   ";
case 0x36A6:   return "DSPGERMN ";
case 0x36AA:   return "DSPFRNCH ";
case 0x36B0:   return "DSPOUT   ";
case 0x36B8:   return "DSPIT    ";
case 0x36D2:   return "DSPMSLSH ";
case 0x36DA:   return "DSPALRTM ";
case 0x36EE:   return "CONVRTD5 ";
case 0x36F6:   return "DSPMSGR  ";
case 0x3700:   return "DSPMSG   ";
case 0x3716:   return "DSPDONE  ";
case 0x371A:   return "SETCRSR  ";
case 0x371E:   return "SETCRSR2 ";
case 0x373A:   return "DSPVAL   ";
case 0x37A0:   return "OUT      ";
case 0x37B4:   return "DSPVXIT  ";
case 0x37BA:   return "SPACE    ";
case 0x37C0:   return "FONTTBL  ";
case 0x38AA:   return "QUESTCH  ";
case 0x38B0:   return "INVCHAR  ";
case 0x38B6:   return "APPLICON ";
case 0x38BC:   return "ASCIITAB ";
case 0x391C:   return "CRSRMASK ";
//case 0x391C:   return "CRSRDATA ";
case 0x393C:   return "ONE      ";
case 0x3941:   return "TWO      ";
case 0x3946:   return "THREE    ";
case 0x394B:   return "IOBRD    ";
case 0x398B:   return "CPUBRD   ";
case 0x39CE:   return "MEMBRD   ";
case 0x3A14:   return "XCARD    ";
case 0x3A3D:   return "WAITICON ";
case 0x3A9F:   return "PROICON  ";
case 0x3ADA:   return "UPPER    ";
case 0x3B1E:   return "DRIVEN   ";
case 0x3B56:   return "INSERTD  ";
case 0x3BA5:   return "KEYBDOUT ";
case 0x3C2B:   return "MOUSEOUT ";
case 0x3C65:   return "QUESTION ";
case 0x3C88:   return "CHECKMRK ";
case 0x3CD6:   return "BADMRK   ";
case 0x3D1E:   return "DISKETTE ";
case 0x3D54:   return "LISA     ";
case 0x3DCE:   return "BRNMSG   ";
case 0x3DE0:   return "TIMMSG   ";
case 0x3DE9:   return "TWGMSG   ";
case 0x3DF4:   return "LOOPMSG  ";
case 0x3E03:   return "PMMSG    ";
case 0x3E10:   return "TWGFAIL  ";
case 0x3E23:   return "TWGRSLT  ";
case 0x3E3A:   return "CHKMSG   ";
case 0x3E58:   return "RTRYMSG  ";
case 0x3E78:   return "CONTMSG  ";
case 0x3E98:   return "STRTMSG  ";
case 0x3EBD:   return "PERIODS  ";
case 0x3EC1:   return "MENUHDG  ";
case 0x3EC9:   return "DISPMSG  ";
case 0x3ED9:   return "SETMSG   ";
case 0x3EE9:   return "CALLMSG  ";
case 0x3EF9:   return "LPMSG    ";
case 0x3F09:   return "VIDMSG   ";
case 0x3F19:   return "CYCLMSG  ";
case 0x3F29:   return "QUITMSG  ";
case 0x3F39:   return "MENUID   ";
case 0x3F40:   return "TSTMENU  ";
case 0x3FBB:   return "ADDRMSG  ";
case 0x3FC5:   return "DATAMSG  ";
case 0x3FCC:   return "CNTMSG   ";
case 0x3FD4:   return "TSTMSG   ";
case 0x3FDB:   return "WHATMSG  ";
case 0x3FF4:   return "HDGMSG   ";
case 0x3FFC:   return "VRSN     ";
case 0x3FFD:   return "REV      ";
case 0x3FFE:   return "LAST     ";
default: return NULL;
}

}
#endif


extern void xxxcheckcontext(uint8 c, char *text);

void xdumpram(void) {dumpram("atexit");}


#ifdef DEBUG

extern char *gettimername(uint8 t);
#ifdef LOOKAHEAD
        static int been_here_before=0;
#endif

   #ifdef PROCNAME_DEBUG
   int is_valid_procname(uint8 c)
   {
    c &=0x7f;
    if (c>='A' && c<='Z') return 1;
    if (c=='_' || c==' ') return 1;
    if (c>='0' && c<='9') return 1;
    return 0;
   }

   int is_valid_procname_w(uint16 w)
   {
     return (is_valid_procname(w>>8) && is_valid_procname(w & 0x7f) );
   }
   #endif
#endif


int get_address_mmu_rfn_type(uint32 addr)
{
 addr=addr & 0x00ffffff;
 return mmu_trans[(addr>>9) & 32767].readfn;
}


//int32 reg68k_external_execute(int32 clocks)  // note, no longer using clocks, using the timer mechanism now! CLEANUP code karma CLEAN UP CODEKARMA
int32 reg68k_external_execute(void)
{

#ifdef DEBUG

        char text[1024];

        #ifdef SUPPRESS_LOOP_DISASM
                int32 suppress_printregs=0;
                int32 last_regs_idx=0;
                t_regs last_regs[MAX_LOOP_REGS];               // last opcode register values
        #endif

#endif



#define MAX_INSTR_PER_CALL 1000

    static t_ipc *ipc;
    static mmu_trans_t *mt;
    static uint32 last_pc;

#ifdef USE_SETJMP
    jmp_buf jb;
#endif

#ifdef DEBUG
    if ( !atexitset)
    {
    atexit(dump_scc);
    atexit(dumpallmmu);
    atexit(xdumpram);
    atexit(dumpvia);
    atexitset=1;
    }

//   if (insetjmpland)
//       {fprintf(buglog,"*** DANGER Entering %s:%s:%d from %s setjmpland*****\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside")); fflush(buglog); EXIT(1);}

#endif

  #ifdef USE_SETJMP
  if (!setjmp(jb))
  #endif
    {

    /* move PC and register block into global variables */
        reg68k_pc   = regs.pc;//20060129// & 0x00ffffff;
		reg68k_regs = regs.regs;
        reg68k_sr.sr_int   = regs.sr.sr_int;
        insetjmpland=1;


        last_bus_error_pc=0;


        // this sets cpu68k_clocks_stop


        if ( (reg68k_pc) & 1  || (regs.pc &1)  )  LISA_REBOOTED(0);


        get_next_timer_event();




        #ifdef DISASM_SKIPPED_OPCODES
        if (debug_log_enabled && pc24>lastpc24 && lastpc24>0)
         if ( (pc24-lastpc24)<128)
         {
          uint32 cursor=lastpc24;
          char text[1024];
          static t_ipc myipc;
          static t_iib *mypiib;

          DEBUG_LOG(0,"disassembling skipped opcodes between %08x-%08x",cursor,pc24);

          pc24 = reg68k_pc & 0x00ffffff;


          while (cursor<pc24)
            {
              abort_opcode=2;
              if (!(mypiib = cpu68k_iibtable[fetchword(cursor)]))
                   {DEBUG_LOG(1,"Invalid instruction @ %08X\n", cursor); cursor=pc24;
                    break;
                   }
               if (abort_opcode==1) cursor=pc24;
               abort_opcode=2;
               #ifdef DEBUG
                 if (!mypiib) DEBUG_LOG(0,"About to send null IPC!");
               #endif
               cpu68k_ipc(cursor, mypiib,&myipc); if (abort_opcode==1) cursor=pc24;

               if (mypiib->clocks!=myipc->clks) DEBUG_LOG(0,"ERROR:iib clocks:%d != ipc clocks:%d !", mypiib->clocks , myipc->clks);

               abort_opcode=2;  diss68k_gettext(&myipc, text); if (abort_opcode==1) cursor=pc24;

               fprintf(buglog,"\nx:%08x (skipped) opcode=%04x %s             +%d clks   SRC:\n",cursor,myipc.opcode,text,myipc->clks);

               cursor +=myipc.wordlen*2;        if (!myipc.wordlen) {DEBUG_LOG(0,"*** Doh! ipc.wordlen=0 **"); exit(14);}
            }
           if (abort_opcode==1) DEBUG_LOG(0,"**DANGER*** GOT abort_opcode!******\n");
           debug_log_enabled=1;
         }
        #endif
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        lastpc24=pc24;



        DEBUG_LOG(0,"\n\ncpu68k_clocks is:%016llx before entering do-while loop\nwill expire at %016llx",cpu68k_clocks,
                cpu68k_clocks_stop);
        do {
            abort_opcode=0;
            SET_CPU_FNC_CODE();


            pc24 = reg68k_pc & 0x00ffffff;
            if (reg68k_pc & 1)  LISA_REBOOTED(0);





///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// disassemble skipped code (within reason)
// 1/0000d42e (lisacx 0 0/0/0) opcode=303c MOVE.W
// 2005.04.15 hack to get at the LisaTest Video test routines.

// Screenshot
//if (pc24==0xd5ec) ascii_screendump();


#ifdef LOOKAHEAD
    if (pc24==LOOKSTARTADDR && been_here_before==0)
      {
        uint32 cursor=pc24;
        char text[1024];
        static t_ipc myipc;
        static t_iib *mypiib;

        been_here_before=1;
        debug_off();
        debug_on("lookahead"); debug_log_enabled=1;

        DEBUG_LOG(0,"lookahead disassembling skipped opcodes between %08x-%08x",cursor,pc24);

        pc24 = reg68k_pc & 0x00ffffff;


        while (cursor<LOOKENDADDR)
          {
            abort_opcode=2;
            if (!(mypiib = cpu68k_iibtable[fetchword(cursor)]))
                 {DEBUG_LOG(1,"Invalid instruction @ %08X\n", cursor); cursor=pc24;
                  break;
                 }
             if (abort_opcode==1) cursor=LOOKENDADDR;
             abort_opcode=2;
             #ifdef DEBUG
               if (!mypiib) DEBUG_LOG(0,"About to send null IPC!");
               #endif
             cpu68k_ipc(cursor, mypiib,&myipc); if (abort_opcode==1) cursor=LOOKENDADDR;

             abort_opcode=2;  diss68k_gettext(&myipc, text); if (abort_opcode==1) cursor=LOOKENDADDR;

             if (mypiib->clocks!=myipc.clks) DEBUG_LOG(0,"ERROR:iib clocks:%d != ipc clocks:%d !", mypiib->clocks , myipc.clks);
             fprintf(buglog,"\nL:%08x  opcode=%04x   %-70s  +%d clks",cursor,myipc.opcode,text,myipc.clks);

             cursor +=myipc.wordlen*2;        if (!myipc.wordlen) {DEBUG_LOG(0,"*** Doh! ipc.wordlen=0 **"); exit(14);}
          }
         if (abort_opcode==1) DEBUG_LOG(0,"**DANGER*** GOT abort_opcode!******\n");
         debug_log_enabled=0; debug_off();
       }
#endif




          ////////////////////////////////////////////////////////////////////////////////////////////////////////////


            mt=&mmu_trans[(pc24>>9) & 32767];
            if (mt->readfn==bad_page)
                {
                 DEBUG_LOG(0,"\n\nCurrent opcode lives inside a bad_page, throwing lisa_mmu_exception @ %d/%08x. Previous IR=%04x",
                      context,pc24,InstructionRegister);
                 DEBUG_LOG(0,"mmu_trans[%04x] segment #%d\n\n",(pc24>>9) & 32767,(pc24>>17));
                 //fflush(buglog);dumpmmupage(context, (pc24>>17), buglog); fflush(buglog);
                 lisa_mmu_exception(pc24);
                 break;           // this break here causes the "fucked timing" danger warning - it can be ignored
                }



            lastsflag=reg68k_sr.sr_struct.s;

            #ifdef DEBUG

               #ifdef SUPPRESS_LOOP_DISASM

                  if (!suppress_printregs)
                  {
                     if (debug_log_enabled)  {printregs(buglog,"");}
                  }
                  else
                  {
                   int32 i;  int32 j=(suppress_printregs & 32767); int flag=0;
                   char line[1024], buf[1024];

                   //snprintf(line,1024,"loop:: %08x: ",pc24);

                // might want to change j to be the previous instruction - but doesn't matter very much I suppose
                   for (i=0; i<8;  i++)  if (last_regs[j].regs[i]!=reg68k_regs[i]) {snprintf(buf,1024,"D%d:%08x ",i,reg68k_regs[i]); strncat(line,buf,1024);flag=1;}
                   for (i=8; i<16; i++)  if (last_regs[j].regs[i]!=reg68k_regs[i]) {snprintf(buf,1024,"A%d:%08x ",i-8,reg68k_regs[i]); strncat(line,buf,1024);flag=1;}
                   if (last_regs[j].sr.sr_int!=reg68k_sr.sr_int)
                   {flag=1;
                        snprintf(buf,1024,"%c%c%c%c%c%c%c imsk:%d ",
                        (reg68k_sr.sr_struct.t ? 't':'.'),
                        (reg68k_sr.sr_struct.s ? 'S':'.'),
                        (reg68k_sr.sr_struct.z ? 'z':'.'),
                        (reg68k_sr.sr_struct.x ? 'x':'.'),
                        (reg68k_sr.sr_struct.n ? 'n':'.'),
                        (reg68k_sr.sr_struct.v ? 'v':'.'),
                        (reg68k_sr.sr_struct.c ? 'c':'.'),
                        ((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 )) );
                        strncat(line,buf,1024);
                   }
                   if (flag) fprintf(buglog,"%s\n",line);
                  }
               #else
                if (debug_log_enabled)  {printregs(buglog,"");} // printlisatime(buglog);}
               #endif
            #endif

			// get the page and the mmu_translation table entry for this pc24
            page=pc24>>9;     mt=&mmu_trans[page];



            // Is this page table allocated?  If not allocate it as needed.
			if (mt!=NULL && mt->table!=NULL)
			{
               ipc=&(mt->table->ipc[(pc24 & 0x1ff)>>1]);

               // we have an IPC, now check it to see that it matches what's in there
               // this is a sanity check against moved pages, but not against self
               // modifying code which only changes operands - that would be too slow
               // to check.

     #ifdef DEBUG
        dbx=debug_log_enabled; debug_log_enabled=0;
     #endif

               abort_opcode=2;
               #ifndef EVALUATE_EACH_IPC
               if (ipc->opcode != (fetchword(pc24)))
               #endif
                {
                    if (abort_opcode==1) break;


                    if (!mt->table) mt->table=get_ipct();  //we can skip fre_ipct

                    cpu68k_makeipclist(pc24); if (abort_opcode==1) break;
                    ipc=&(mt->table->ipc[(pc24 & 0x1ff)>>1]);
				}
                abort_opcode=0;


     #ifdef DEBUG
        {
            #ifdef ICACHE_DEBUG
            if (dbx && pc24>16)
            {
              int i;  uint8 c,nice[1024], hex[1024], tmp[1024];

              nice[0]=0; hex[0]=0;

              for (i=0; i<32; i++)
                  {
                     abort_opcode=2;
                     c=lisa_ram_safe_getbyte(context,(pc24-16+i));
                     if (i & 1) snprintf(tmp,1024,"%02x ",c);
                     else       snprintf(tmp,1024,"%02x",c);

                     strncat(hex,tmp,1024);
                     nice[i]=niceascii(c);
                  }

              debug_log_enabled=dbx;     // re-enable debug log only after icache fetches to prevent verbosity

              fprintf(buglog,"%08x:%s|%s clk:%016llx\n",pc24-16,hex,nice,cpu68k_clocks);
              //DEBUG_LOG(0,"icache:%04x:%04x:%04x:%04x:%04x  clk:%08x",ipc->opcode,icache2,icache4, icache6, icache8,cpu68k_clocks);
              abort_opcode=0;
            }
            else debug_log_enabled=dbx;
            #else
                 debug_log_enabled=dbx;
            #endif
        }
     #endif

            } // end of if (mt!=NULL && mt->table!=NULL)
            else // need to make this IPC table
            {
                //if ( !mt)  { fprintf(buglog,"Doh! mt is null! bye!"); EXIT(4);  }
                abort_opcode=2; mt->table=get_ipct();  if (abort_opcode==1) break;
                abort_opcode=0;

                abort_opcode=2;
                cpu68k_makeipclist(pc24);
                if (abort_opcode==1) break;

                #ifdef DEBUG
                       if ( !mt->table)  {DEBUG_LOG(-1,"reg68k_extern_exec: got a null mt->table from makeipclist!");}
                #endif

                ipc=&(mt->table->ipc[(pc24 & 0x1ff)>>1]);
           }

			// If the page isn't RAM or ROM, then we can't execute it.
			// I can get rid of this check to speed things up... but...

#ifdef DEBUG
            if (mt->readfn!=ram && mt->readfn!=sio_rom && mt->readfn!=sio_mmu)
			{
                DEBUG_LOG(0,"[Woot! Trying to execute from non-ram/rom! Living dangerously!");
                DEBUG_LOG(0,"[Bye Bye! PC24= %08x  ipc# %d mt->readfn=%d %s\n",pc24,(pc24 & 0x1ff)>>1,mt->readfn,mspace(mt->readfn));
                DEBUG_LOG(0,"[If we got there there's a problem with rmmuslr2fn not returning the proper readfn!");

                fflush(buglog); fflush(stdout); cpu68k_printipc(ipc); fflush(stdout);

                DEBUG_LOG(-1,"[exit 1]");
                fprintf(buglog,"executing from non ram\n");
                EXIT(397);
			}
			else
#endif
			{


// keep this can use for debugger later
#ifdef xxxHALT_AT
if ( (pc24==0xfe06f2 || pc24==0xfe14F2 || pc24==0xfe144a pc==0xfe) && mt->readfn==sio_rom)
    {
    videoximgdirty=1000;
    videoramdirty=1;
    fprintf(buglog,"halt."); fflush(buglog);
    EXIT(398);
    clks = -20; //cpu68k_clocks += mt->table->t.clocks;
    regs.pc = reg68k_pc;
    regs.sr.sr_int = reg68k_sr.sr_int;
    #ifdef USE_SETJMP
    longjmp(jb, 1);
    #endif
    return -clks;                 /* i.e. number of clocks done too much */
    }
#endif



///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef DEBUG



                if (debug_log_enabled)
                {
                     if (mt->readfn==sio_mmu && rom_source_file && dtc_rom_fseeks && ((pc24 & 0xffff)<0x3fff))
                     {   char buff[1024];
                         fseek(rom_source_file,dtc_rom_fseeks[pc24 & 0x3fff],SEEK_SET);
                         fgets(buff,1024,rom_source_file); if (strlen(buff)>5) fprintf(buglog,"%08x: SRC: %s\n",pc24,buff);
                     }

                    #ifdef SUPPRESS_LOOP_DISASM
                    {
                     int i,j,k=0;

                     suppress_printregs=0;

                     j=last_regs_idx;
                     do   {j--; if (j<0) j=MAX_LOOP_REGS-1;
                           if (pc24==last_regs[j].pc) k=1;
                     }     while (j!=last_regs_idx && !k);

                     // copy to current register
                     j=last_regs_idx+1;  if (j>=MAX_LOOP_REGS) j=0;

                     last_regs[j].pc=pc24;
                     last_regs[j].sp=regs.sp;
                     last_regs[j].sr.sr_int=reg68k_sr.sr_int;
                     for (i=0; i<16; i++)  last_regs[j].regs[i]=reg68k_regs[i];
                     last_regs_idx=j;


                     if ((ipc->opcode & 0xf000)==0xa000)
                      {
                        char temp[256];
                        snprintf(temp,256,"::%08x ",fetchlong(pc24+2));
                        strncat(text,temp,256);
                      }

                     if ((ipc->opcode & 0xf000)==0xf000)
                      {
                        char temp[256];
                        snprintf(temp,256,"::%08x ",fetchlong(pc24+2));
                        strncat(text,temp,256);
                      }


            #ifdef PROCNAME_DEBUG
            {  uint16 w,w1,w2,w3;

               w=lisa_ram_safe_getword(context,(pc24-2));
               //DEBUG_LOG(0,"entering procedure: got 5th word:%04x",w);
               if (w<0x00f0)
               {
                       w3=lisa_ram_safe_getword(context,(pc24-10));
                 //      DEBUG_LOG(0,"entering procedure got word in 0th spot:%04x is valid & 0x8000:%d is valid:%d",w3,(w3 & 0x8000),
                 //           is_valid_procname_w(w3 & 0x7f7f));
                 if ( (w3 & 0x8000) && is_valid_procname_w(w3 & 0x7f7f) )
                    {
                       w2=lisa_ram_safe_getword(context,(pc24-8));
                       w1=lisa_ram_safe_getword(context,(pc24-6));
                       w =lisa_ram_safe_getword(context,(pc24-4));

                   //    DEBUG_LOG(0,"entering procedure Got words:%04x %04x %04x %04x",w3,w2,w1,w);

                       if (is_valid_procname_w(w) && is_valid_procname_w(w1) && is_valid_procname_w(w2) )
                               fprintf(buglog,"\n\n****** Entering Procedure: %c%c%c%c%c%c%c%c *********\n\n",
                                       ((w3>>8) & 0x7f),(w3 & 0x7f),
                                       ((w2>>8) & 0x7f),(w2 & 0x7f),
                                       ((w1>>8) & 0x7f),(w1 & 0x7f),
                                       ((w >>8) & 0x7f),(w  & 0x7f)     );

                    }
               }
            }
            #endif       // end of PROCNAME_DEBUG


                     if (!k)
                      {if (ipc->opcode!=0xe350)

                       fprintf(buglog,"%d/%08x (lisacx %d %d/%d/%d) opcode=%04x %s    SRC:clk:%016llx +%ld clks\n",context,pc24,
                       (segment1|segment2),segment1,segment2,start,ipc->opcode,text,cpu68k_clocks, ipc->clks);


                      }
                      else suppress_printregs=32768|j;
                    }
                    #else
                    if (ipc->opcode!=0xe350)



                    fprintf(buglog,"%d/%08x (lisacx %d %d/%d/%d) opcode=%04x %s    SRC:clk:%016llx: +%ld clks\n",context,pc24,
                    (segment1|segment2),segment1,segment2,start,ipc->opcode,text,cpu68k_clocks,ipc->clks);


                    #endif

                }
                last_cpu68k_clocks=cpu68k_clocks;


// Cheat to skip over big wait loop in NMI code
#ifdef SKIP_BIGWAIT_NMI_CODE
if (lisa_os_boot_mouse_x_ptr==0xfec)
{/////////////////////////////////////////////////////////////////////////////////////////

if ( ipc->opcode==0x5381)
{
 // hack to speed up lisatest?
 if (pc24==0xd36e && reg68k_regs[1]==0x3d090) reg68k_regs[1]=1;
 if (pc24==0xdd52 && reg68k_regs[1]>1 ) {reg68k_regs[1]=1;}
}
else                                    // 2005.04.05 06:22am - Turn Debugging on LisaTest CPU ErrorLevel
    if (pc24==0x0000d2c8 && ipc->opcode==0xb3cb && reg68k_regs[6]==0x00000018 && reg68k_regs[8]<0x001ff000)
    {
      debug_on("LisaTest-cpu-errorlogic"); debug_log_enabled=1; debug_log_enabled=1; last_dbe=1;
      reg68k_regs[8]=0x001fff00; reg68k_regs[9]=0x001fff00;
      memerror=0xFFF8;
      DEBUG_LOG(0,"LisaTest CPU Error Logic - enabling debug 2005.04.05");
    }


}///////////////////////////////////////////////////////////////////////////////////////////
#endif



#endif



///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

                if (abort_opcode==1) {fprintf(buglog,"MMU/BUS/Address exception occured on opcode fetch!\n"); fflush(buglog); EXIT(476);}
                abort_opcode=0;          // clear any addr/bus errors/traps/etc that may have occured.

                InstructionRegister=ipc->opcode;

                if (ipc->function)                               // if the IPC is valid, and loaded
                     {SET_CPU_FNC_DATA(); ipc->function(ipc);}   // execute the function, else rebuild the IPC
                else {
                        static t_iib *piib;
     #ifdef DEBUG
        dbx=debug_log_enabled; debug_log_enabled=0;
     #endif

                        if (!(piib = cpu68k_iibtable[fetchword(reg68k_pc)]))
                            DEBUG_LOG(1,"Invalid instruction @ %08X\n", reg68k_pc); // RA

                        DEBUG_LOG(0,"Got an IPC without a function, doing it manually");

                        SET_CPU_FNC_CODE();
                        #ifdef DEBUG
                          if (!ipc)  DEBUG_LOG(0,"About to send null IPC!");
                          if (!piib) DEBUG_LOG(0,"About to send null IPC!");
                        #endif

                        cpu68k_ipc(reg68k_pc,piib,ipc);

                        if (piib->clocks!=ipc->clks)
                            DEBUG_LOG(0,"ERROR:iib clocks:%d != ipc clocks:%d !", piib->clocks , ipc->clks);

                        DEBUG_LOG(0,"About to call the IPC I just got manually, if it's not null...");

                        if (abort_opcode==1) break;


                        ipc->function=cpu68k_functable[fetchword(reg68k_pc) * 2 + 1];


                        //cpu68k_functable[fetchword(reg68k_pc) * 2 + 1] (&ipc); (&ipc);

                        SET_CPU_FNC_DATA();
     #ifdef DEBUG
        debug_log_enabled=dbx;
     #endif
                        if (abort_opcode==1) {DEBUG_LOG(0,"MMU/BUS/Address exception occured on opcode fetch!\n"); fflush(buglog); break;}
                        else {
                                InstructionRegister=ipc->opcode;
                                abort_opcode=0;
                                if (ipc->function) ipc->function(ipc);
                                else {   DEBUG_LOG(0,"No ipc function at %d/%08x, even after attempting to get one!\n",context,pc24); EXIT(277); }
                             }
                    }  // if we have it, execute, else loop is done. :)




                pc24 = reg68k_pc; //20060321// & 0x00ffffff;

                abort_opcode=0;

                #ifdef DEBUG
                if (ipc->clks >160) {DEBUG_LOG(0,"***INSANELY FUCKED UP IPC STRUCT TIMING! ***BUG**** ipc->clks==%d",ipc->clks);cpu68k_printipc(ipc);}
                #endif
                //else DEBUG_LOG(0,"ipc->clks this cycle:%ld",ipc->clks);

                cpu68k_clocks+=ipc->clks;
        } // if execute from ram/rom else statement

#ifdef DEBUG
    if (0==reg68k_pc)
       {
        DEBUG_LOG(0,"pc=0 LastPC24=%08x pc24=%08x abort_opcode:%d",lastpc24,pc24,abort_opcode);
       }
#endif


   } while (cpu68k_clocks_stop>=cpu68k_clocks && !regs.stop);


#ifdef DEBUG
    DEBUG_LOG(0,"pc=%08x cpu68k_clocks is:%016llx stop is :%016llx diff:%016llx  regs.stop is %d event:%d %s after exiting do-while loop",
            reg68k_pc, cpu68k_clocks,cpu68k_clocks_stop,
            cpu68k_clocks_stop-cpu68k_clocks, regs.stop,
            next_timer_id(),gettimername(next_timer_id() ) );

    printregs(buglog,"");
#endif

   // handle NMI - NMI unlike Bus Error occurs AFTER the current opcode completes. ////////////////////////////////////////////
   if (nmi_clk && nmi_pc)
   {  // regs.stop=nmi_stop;                                    // NMI can only occur on memory access resulting in soft parity error, not while cpu is stopped
         regs.stop=0;
         reg68k_internal_vector(0x1f, reg68k_pc,nmi_addr_err);  // 7 is wrong for vector, right for autovector.
         nmi_addr_err=0;  nmi_clk=0; nmi_pc=0; nmi_stop=0;      // clear flags
         regs.stop=0;
   }
   else  // NMI did not occur, instead, see if there's a pending IRQ
         fire_pending_internal_autovector();                    // check for the next pending IRQ's.

   if (regs.stop) {
                    DEBUG_LOG(0,"********** clocks stopped @PC:%08x (clk:%016llx), skipping to next event (clk:%lld)****",
                               reg68k_pc,cpu68k_clocks,cpu68k_clocks_stop);

                    //20070309 - if diff >60ms, induce a delay to keep the clock honest.
                    if ((cpu68k_clocks_stop-cpu68k_clocks)>5000*60)  // 60ms
                         gen_clock_diff_sleep(cpu68k_clocks_stop-cpu68k_clocks);

                    cpu68k_clocks=cpu68k_clocks_stop;
                  }

   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   last_pc=reg68k_pc;

  /* restore global registers back to permanent storage */
  regs.pc = reg68k_pc;  regs.sr.sr_int = reg68k_sr.sr_int;
  insetjmpland=0;
  #ifdef USE_SETJMP
  longjmp(jb, 1);
  #endif
 }


if (cpu68k_clocks_stop<=cpu68k_clocks)
{   int32 old=cpu68k_clocks;
     check_current_timer_irq();
     DEBUG_LOG(0,"After check_current_timer_irq: cpu68k_clocks is:%016llx before it was: %016llx diff:%016llx",cpu68k_clocks,old, cpu68k_clocks-old);
}


 return 0; //-clks;                       // i.e. number of clocks done too much
}




void reg68k_external_autovector(int avno)
{
#ifdef USE_SETJMP
      jmp_buf jb;
#endif


      if (insetjmpland)
       {DEBUG_LOG(0,"*** DANGER Entering %s:%s:%d from %s setjmpland*****\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside")); fflush(buglog);
        reg68k_internal_autovector(avno);
        return;
        EXIT(1);
       }
    #ifdef USE_SETJMP
    if (!setjmp(jb))
    #endif
      {
    /* move PC and register block into global processor register variables */
		reg68k_pc = regs.pc;
		reg68k_regs = regs.regs;
        reg68k_sr.sr_int = regs.sr.sr_int;
        DEBUG_LOG(0,"Inside setjmp land, about to call internal_autovector:%d reg68k_pc:%08x reg68k_sr:%08x",avno,reg68k_pc,reg68k_sr.sr_int);
        insetjmpland=1;

        reg68k_internal_autovector(avno);

        DEBUG_LOG(0,"Autovector:%d reg68k_pc:%08x reg68k_sr:%08x regs.pc:%08x regs.sr:%08x, exiting setjmp land",avno,reg68k_pc,reg68k_sr.sr_int,regs.pc,regs.sr.sr_int);
    /* restore global registers back to permanent storage */
		regs.pc = reg68k_pc;
        regs.sr.sr_int = reg68k_sr.sr_int;

        insetjmpland=0;
        #ifdef USE_SETJMP
        longjmp(jb, 1);
        #endif
	}
}


void reg68k_external_vector(int vector, uint32 oldpc,uint32 addr_error)
{
#ifdef USE_SETJMP
    jmp_buf jb;
#endif

    DEBUG_LOG(0,"VECTOR: %d, OLDPC:%08x memerr@:%08x",vector,oldpc,addr_error);
       if (insetjmpland)
       {fprintf(buglog,"*** DANGER Entering %s:%s:%d from %s setjmpland*****\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside")); fflush(buglog);
        reg68k_internal_vector(vector,oldpc,addr_error);
        return;
        EXIT(1);
       }

    #ifdef USE_SETJMP
    if (!setjmp(jb))
    #endif
     {
    /* move PC and register block into global processor register variables */

        DEBUG_LOG(0,"In setjmp land vector:%d oldpc:%08x regs.pc:%08x regs.sr:%x",vector,oldpc,regs.pc,regs.sr.sr_int);

        reg68k_pc = regs.pc;
		reg68k_regs = regs.regs;
        reg68k_sr.sr_int = regs.sr.sr_int;
        insetjmpland=1;

        DEBUG_LOG(0,"Calling internal_vector from external reg68k_pc:%08x reg68k_sr:%x",reg68k_pc,reg68k_sr.sr_int);
        reg68k_internal_vector(vector,oldpc,addr_error);
        DEBUG_LOG(0,"Done with internal_vector vector:%d reg68k_pc:%08x reg68k_sr:%08x regs.pc:%08x regs.sr:%08x, exiting setjmp land",
                vector,
                reg68k_pc,
                reg68k_sr.sr_int,regs.pc,regs.sr.sr_int);


    /* restore global registers back to permanent storage */
		regs.pc = reg68k_pc;
        regs.sr.sr_int = reg68k_sr.sr_int;

        insetjmpland=0;
        #ifdef USE_SETJMP
        longjmp(jb, 1);
        #endif
	}
}







/*** reg68k_internal_vector - go to vector - this call assumes global
     registers are already setup ***/

char vectxt[128];
char *getvector(int v)
{
 switch (v)
 {

     case 0:      sprintf(vectxt,"0x%x (%d) reset ssp",v,v); return vectxt;                       // 0
     case 1:      sprintf(vectxt,"0x%x (%d) reset initial pc",v,v); return vectxt;                // 4
     case 2:      sprintf(vectxt,"0x%x (%d) bus error",v,v); return vectxt;                       // 8
     case 3:      sprintf(vectxt,"0x%x (%d) address error",v,v); return vectxt;                   // 12
     case 4:      sprintf(vectxt,"0x%x (%d) illegal instruction",v,v); return vectxt;             // 16
     case 5:      sprintf(vectxt,"0x%x (%d) zero divide",v,v); return vectxt;
     case 6:      sprintf(vectxt,"0x%x (%d) chk instruction",v,v); return vectxt;
     case 7:      sprintf(vectxt,"0x%x (%d) trapv",v,v); return vectxt;
     case 8:      sprintf(vectxt,"0x%x (%d) priviledge violation",v,v); return vectxt;
     case 9:      sprintf(vectxt,"0x%x (%d) trace",v,v); return vectxt;
     case 10:     sprintf(vectxt,"0x%x (%d) A-line trap",v,v); return vectxt;
     case 11:     sprintf(vectxt,"0x%x (%d) F-line trap",v,v); return vectxt;

     case 14:     sprintf(vectxt,"0x%x (%d) format error (RTE/TRAP?)",v,v); return vectxt;

     case 15:     sprintf(vectxt,"0x%x (%d) uninitialized interrupt vector",v,v); return vectxt;

     case 24:     sprintf(vectxt,"0x%x (%d) spurious irq - buserr during irq processing causes this",v,v); return vectxt;

     case 25:     sprintf(vectxt,"0x%x (%d) other (disk,vertical,via) autovect #1 ",v,v); return vectxt;
     case 26:     sprintf(vectxt,"0x%x (%d) keybd autovect #2 ",v,v); return vectxt;
     case 27:     sprintf(vectxt,"0x%x (%d) slot2 autovect #3 ",v,v); return vectxt;
     case 28:     sprintf(vectxt,"0x%x (%d) slot1 autovect #4 ",v,v); return vectxt;
     case 29:     sprintf(vectxt,"0x%x (%d) slot0 autovect #5 ",v,v); return vectxt;
     case 30:     sprintf(vectxt,"0x%x (%d) rs232 autovect #6 ",v,v); return vectxt;
     case 31:     sprintf(vectxt,"0x%x (%d) NMI autovector #7 ",v,v); return vectxt;

     case 32:     sprintf(vectxt,"0x%x (%d) trap #0  ",v,v); return vectxt;
     case 33:     sprintf(vectxt,"0x%x (%d) trap #1  ",v,v); return vectxt;
     case 34:     sprintf(vectxt,"0x%x (%d) trap #2  ",v,v); return vectxt;
     case 35:     sprintf(vectxt,"0x%x (%d) trap #3  ",v,v); return vectxt;
     case 36:     sprintf(vectxt,"0x%x (%d) trap #4  ",v,v); return vectxt;
     case 37:     sprintf(vectxt,"0x%x (%d) trap #5 (hwlib) ",v,v); return vectxt;
     case 38:     sprintf(vectxt,"0x%x (%d) trap #6 (setup mmuseg) ",v,v); return vectxt;
     case 39:     sprintf(vectxt,"0x%x (%d) trap #7 (D0=%04x->SR, JMP (A0=%08x) ",v,v,(uint16)(reg68k_regs[0] & 0xffff),reg68k_regs[8]); return vectxt;
     case 40:     sprintf(vectxt,"0x%x (%d) trap #8  ",v,v); return vectxt;
     case 41:     sprintf(vectxt,"0x%x (%d) trap #9  ",v,v); return vectxt;
     case 42:     sprintf(vectxt,"0x%x (%d) trap #a  ",v,v); return vectxt;
     case 43:     sprintf(vectxt,"0x%x (%d) trap #b  ",v,v); return vectxt;
     case 44:     sprintf(vectxt,"0x%x (%d) trap #c  ",v,v); return vectxt;
     case 45:     sprintf(vectxt,"0x%x (%d) trap #d  ",v,v); return vectxt;
     case 46:     sprintf(vectxt,"0x%x (%d) trap #e  ",v,v); return vectxt;
     case 47:     sprintf(vectxt,"0x%x (%d) trap #f  ",v,v); return vectxt;
}
if (v>63)    sprintf(vectxt,"0x%x (%d) user irq vector #%d",v,v,v-64); return vectxt;

sprintf(vectxt,"0x%x (%d) unassigned/reserved",v,v); return vectxt;
}

void lisaos_trap5(void)
    {
        char *label="unknown";

        if (!debug_log_enabled) return;

        switch(reg68k_regs[7] & 0x0000ffff)
        {
        case 0x00:     /* 0028  */ label="driverin"; break;
        case 0x68:     /* 0032  */ label="diskdriv"; break;
        case 0x6a:     /* 0046  */ label="twiggydr"; break;
        case 0x6c:     /* 005a  */ label="disksync"; break;
        case 0x8c:     /* 006a  */ label="nmisync "; break;
        case 0xaa:     /* 0076  */ label="copsync "; break;
        case 0x9e:     /* 0082  */ label="poll    "; break;
        case 0x02:     /* 008e  */ label="mouseloc"; break;
        case 0x04:     /* a4    */ label="mouseupd"; break;
        case 0x06:     /* b4    */ label="mousesca"; break;
        case 0x08:     /* c4    */ label="mousethr"; break;
        case 0xa8:     /* d4    */ label="nouseodo"; break;
        case 0x0a:     /* e4    */ label="cursorlo"; break;
        case 0x0c:     /* f8    */ label="cursortr"; break;
        case 0x0e:     /* 108   */ label="cursorim"; break;
        case 0x10:     /* 158   */ label="cursorhi"; break;
        case 0x12:     /* 164   */ label="cursorsh"; break;
        case 0x14:     /* 188   */ label="cursordi"; break;
        case 0x6e:     /* 194   */ label="cursorob"; break;
        case 0x70:     /* 1a0   */ label="cursorin"; break;
        case 0x9c:     /* 1ac   */ label="cursorre"; break;
        case 0x86:     /* 1b8   */ label="busyimag"; break;
        case 0x88:     /* 208   */ label="busydela"; break;
        case 0x16:     /* 218   */ label="framecou"; break;
        case 0x8a:     /* 228   */ label="screensi"; break;
        case 0x18:     /* 23e   */ label="screenad"; break;
        case 0x1a:     /* 24e   */ label="altscree"; break;
        case 0x8e:     /* 25e   */ label="screenke"; break;
        case 0x90:     /* 26e   */ label="setscree"; break;
        case 0x1c:     /* 27e   */ label="contrast"; break;
        case 0x1e:     /* 28e   */ label="setcontr"; break;
        case 0x20:     /* 29e   */ label="rampcont"; break;
        case 0x82:     /* 2ae   */ label="dimcontr"; break;
        case 0x84:     /* 2be   */ label="setdimco"; break;
        case 0x22:     /* 2ce   */ label="fadedela"; break;
        case 0x24:     /* 2de   */ label="setfaded"; break;
        case 0x26:     /* 2ee   */ label="powerdow"; break;
        case 0x28:     /* 2fa   */ label="powercyc"; break;
        case 0x2a:     /* 30a   */ label="volume  "; break;
        case 0x2c:     /* 31a   */ label="setvolum"; break;
        case 0x2e:     /* 32a   */ label="noise   "; break;
        case 0x30:     /* 33a   */ label="silece  "; break;
        case 0x32:     /* 346   */ label="beep    "; break;
        case 0x38:     /* 358   */ label="keyboard"; break;
        case 0x96:     /* 368   */ label="legends "; break;
        case 0x98:     /* 378   */ label="setlegen"; break;
        case 0x34:     /* 388   */ label="keyisdow"; break;
        case 0x36:     /* 39c   */ label="keymap  "; break;
        case 0x3c:     /* 3b8   */ label="keybdpee"; break;
        case 0x92:     /* 3d0   */ label="altkeype"; break;
        case 0x3a:     /* 3fa   */ label="keybdeve"; break;
        case 0x94:     /* 412   */ label="altkeyev"; break;
        case 0x3e:     /* 43c   */ label="repeatra"; break;
        case 0x40:     /* 452   */ label="setrepea"; break;
        case 0x42:     /* 464   */ label="keypushe"; break;
        case 0x72:     /* 476   */ label="nmikey  "; break;
        case 0x74:     /* 486   */ label="setnmike"; break;
        case 0xa0:     /* 498   */ label="toggleke"; break;
        case 0xa2:     /* 4ab   */ label="settoggl"; break;
        case 0x9a:     /* 4ba   */ label="microtim"; break;
        case 0x44:     /* 4ca   */ label="timer   "; break;
        case 0x46:     /* 4da   */ label="alarmass"; break;
        case 0x48:     /* 4f2   */ label="alarmret"; break;
        case 0x4a:     /* 502   */ label="alarmabs"; break;
        case 0x4c:     /* 514   */ label="alarmrel"; break;
        case 0x4e:     /* 526   */ label="alarmoff"; break;
        case 0x50:     /* 536   */ label="datetime"; break;
        case 0x52:     /* 558   */ label="setdatet"; break;
        case 0x54:     /* 57a   */ label="datetoti"; break;
        case 0x58:     /* 5a4   */ label="timestam"; break;
        case 0x5a:     /* 5b4   */ label="settimes"; break;
        case 0x5c:     /* 5c4   */ label="timetoda"; break;
        }
        fprintf(buglog,"TRAP #5 Hardware Library call taken D7=%08x, (%s)\n",reg68k_regs[7],label);
    }


// called by mmuflush to make sure that the correct context is set!
void reg68k_update_supervisor_internal(void)  {lastsflag=reg68k_sr.sr_struct.s;}
void reg68k_update_supervisor_external(void)  {lastsflag=regs.sr.sr_struct.s;}

// Macros for 68000 Vector operations - these are turned into macro's to make the source code more readable and still faster than fn's

#define A7PUSH_BYTE(x)    {abort_opcode=2; reg68k_regs[15] -= 1;    storebyte(reg68k_regs[15], (x));}
#define A7PUSH_WORD(x)    {abort_opcode=2; reg68k_regs[15] -= 2;    storeword(reg68k_regs[15], (x));}
#define A7PUSH_LONG(x)    {abort_opcode=2; reg68k_regs[15] -= 4;    storelong(reg68k_regs[15], (x));}
#define GETVECTOR(x)      (fetchlong((x) * 4))
#define SWAPA7withSSP()   {reg68k_regs[15] ^= regs.sp; regs.sp ^= reg68k_regs[15]; reg68k_regs[15] ^= regs.sp;}
#define SETSUPERVISOR(x)  {reg68k_sr.sr_struct.s = (x);}
#define GETSUPERVISOR()   (reg68k_sr.sr_struct.s)

/* reg68k_internal_autovector - go to autovector - this call assumes global
     registers are already setup
interrupts must not occur during cpu68k_frozen, as this flag indicates
that we are catching up events due to a dma transfer.  Since the dma
transfer is triggered by a memory write at which stage the current value
of the PC is not written anywhere (due to being in the middle of a 68k
	block and it's in a local register), we MUST NOT use regs.pc - this
routine uses reg68k_pc but this is loaded by reg68k_external_autovector,
which is called by event_nextevent() and therefore will be a *WRONG*
	reg68k_pc!
*/



void reg68k_internal_autovector(int avno)
{

    reg68k_internal_vector(V_AUTO + avno - 1,reg68k_pc,0);  //-1


    #ifdef DISABLED_2005_02_02
    int curlevel = (reg68k_sr.sr_int >> 8) & 7;
	uint32 tmpaddr;
    uint16 saved_sr=reg68k_sr.sr_int;

       if (!insetjmpland)
       {fprintf(buglog,"*** DANGER Entering %s:%s:%d from %s setjmpland*****\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside")); fflush(buglog);
       reg68k_external_autovector(avno);
       return;
       EXIT(1);
       }

    DEBUG_LOG(0,"curlevel:%d avno:%d cpufrozen: %ld",curlevel,avno,cpu68k_frozen);
    fflush(buglog); fflush(stdout);

    if ((curlevel < avno || avno == 7) && !cpu68k_frozen)
    {
      #ifdef DEBUG
       if (avno==1 && floppy_FDIR) append_floppy_log("reg68k_int_av_ ***Firing IRQ1 because FDIR is set***\n");
      #endif

       if (regs.stop && nmi_clk && nmi_pc) {regs.stop=0; nmi_addr_err=0;  nmi_clk=0; nmi_pc=0; nmi_stop=0;}      // clear flags
       else  if (regs.stop)
        {
            DEBUG_LOG(0,"exiting from STOP opcode @%08x - will continue at %08x after ISR handles IRQ:%d.",reg68k_pc,reg68k_pc+4,vno);
            reg68k_pc += 4;  /* autovector whilst in a STOP instruction */
			regs.stop = 0;
            regs.pc = reg68k_pc; regs.sr = reg68k_sr;
		}


        if (!GETSUPERVISOR()) {
            SWAPA7withSSP();
            SETSUPERVISOR(1);

            DEBUG_LOG(0,"S mode change SP:%08x/A7:%08x swapped.",reg68k_regs[15],regs.sp);

           // if (segment1|segment2)
              {
               //lastsflag=reg68k_sr.sr_struct.s;
               regs.pc = reg68k_pc; regs.sr = reg68k_sr;
               SET_MMU_DIRTY(0xdec0de);
               mmuflush(0x3000);
               fprintf(buglog,"post mmuflush context=%d s1/s2=%d/%d start=%d\n",context,segment1,segment2,start);
              }
           // Supervisor flag set causes context change
		}
        lastsflag=reg68k_sr.sr_struct.s;

        A7PUSH_LONG(reg68k_pc); if (abort_opcode==1) {fprintf(buglog,"Doh! got abort_opcode=%d on storeword of SR!\n",abort_opcode); EXIT(779);}
        A7PUSH_WORD(saved_sr);  if (abort_opcode==1) {fprintf(buglog,"Doh! got abort_opcode=1 on storeword of SR!\n"); EXIT(780);}

        // insert format/vector here    // RA for 68010+ disable for 68000/68008.
        //   FV=0x1000 | ((V_AUTO + avno - 1) * 4);
        //or FV=0x0000 | ((V_AUTO + avno - 1) * 4);
        //reg68k_regs[15] -= 2;
        //storeword(reg68k_regs[15], FV);
        ////////////////////////////////

		reg68k_sr.sr_struct.t = 0;
		reg68k_sr.sr_int &= ~0x0700;
		reg68k_sr.sr_int |= avno << 8;
		tmpaddr = reg68k_pc;

        DEBUG_LOG(0,"autovector#%d V_AUTO:%08x Vector address: %d * 4 = %08x",avno,V_AUTO,(V_AUTO + avno - 1),((V_AUTO + avno - 1)*4));

        abort_opcode=0;
        reg68k_pc = fetchlong((V_AUTO + avno - 1) * 4);
        if (abort_opcode==1) {fprintf(buglog,"Doh! got abort_opcode=1 while fetching vector for IRQ!\n"); EXIT(781);}

        DEBUG_LOG(0,"INTERNAL AUTOVECTOR %d: oldpc %x -> newpc is %x\n", avno, tmpaddr, reg68k_pc);

      //  if (avno<7 && avno) pending_vector_bitmap &= ~(1<<(avno-1));

      //  regs.pending = get_pending_vector();
        // restore regs to extern
        regs.pc = reg68k_pc;
        regs.sr.sr_int = reg68k_sr.sr_int;

    }
    else
    {

//      if (avno<7 && avno) pending_vector_bitmap |= (1<<(avno-1));
//      regs.pending = get_pending_vector();
//     if (!regs.pending || regs.pending < avno)
//     {
//        printregs(buglog,"");
//        DEBUG_LOG(0,"INTERNAL AUTOVECTOR %d: was not taken because IRQ level:%d filtered it. set pending to it...SR:%04x:%04x %s\n\n",avno,curlevel,regs.sr.sr_int,reg68k_sr.sr_int,
//                ((regs.sr.sr_int!=reg68k_sr.sr_int) ? "DANGER":"ok"));
//
//        regs.pending = avno;
//      }
//        //regs.pending = 0;

	}
    #endif
}


void reg68k_internal_vector(int vno, uint32 oldpc, uint32 addr_error)
{
   static uint32 lastoldpc;
   static int32  lastclk;
   static int lastvno;
   uint16 saved_sr=reg68k_sr.sr_int;

   int avno=(vno-V_AUTO+1);
   int curlevel = (reg68k_sr.sr_int >> 8) & 7;
   //unused//static uint32 tmpaddr;
   uint16 busfunctioncode;
   uint8 old_supervisor=reg68k_sr.sr_struct.s;



    /*-----------------12/8/2003 9:56PM-----------------
     * needs to do this: RA
     *
     * SSP-2 ->SSP                      // push FV -- 680010+ only
     * Format/Vector Offset -> (SSP)
     * SSP-4->4->SSP                    // push PC
     * PC->(SSP)
     * SSP-2 ->SSP                      // push SR
     * SR->(SSP)
     * Vector Address->PC               // PC=Vector
     *
     * --------------------------------------------------*/


   // #ifdef DEBUG
   //     validate_mmu_segments("reg68k internal_vector");
   //  #endif

   // avoid bus/addr error repeats on multi-operand opcodes...
   if (lastclk==cpu68k_clocks && lastvno==vno)
      {
        DEBUG_LOG(0,"Suppressing internal_vector - VECTOR:%d, oldpc:%08x clk:%016llx",vno,oldpc,cpu68k_clocks);
        return;
      }

   lastclk =cpu68k_clocks;   lastvno =vno;   lastoldpc =oldpc;


   if (!insetjmpland)
       {fprintf(buglog,"*** DANGER Entering %s:%s:%d from %s setjmpland - unclean sloppy code*****\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside")); fflush(buglog);
        reg68k_external_vector(vno,oldpc,addr_error);
        return;
        EXIT(1);
       }

   #ifdef DEBUG

    DEBUG_LOG(0,"Entering: internal_vector - VECTOR:%d, addr_err:%08x oldpc:%08x, pc24:%08x, reg68k_pc:%08x",
                 vno,addr_error,oldpc,pc24,reg68k_pc);

    if (oldpc!=reg68k_pc && vno<32)
    DEBUG_LOG(0,"DANGER DANGER DANGER oldpc:%08x is not reg68k_pc:%08x, pc24:%08x oldpc24:%08x vector:%d",oldpc, reg68k_pc,pc24,lastpc24,vno);

    if (vno==37) lisaos_trap5();        // log LisaOS trap #5 calls by name
    printregs(buglog,"irqdone");


   #endif

   if (avno>0 && avno<8)                // If it's an autovector, check the IRQ mask before allowing it to occur.
      {
        DEBUG_LOG(0,"PC:%08x AutoVector is:%d vector:%d curlevel is %d cpu stop status is:%d",reg68k_pc,avno,vno,curlevel,regs.stop);
        if (! (IS_VECTOR_AVAILABLE_INT(avno))) {DEBUG_LOG(0,"Vector requested is not available (INTMASK too low)");return;}
      }
   else avno=0;                         // clear avno since it wasn't an autovector - this saves time later on the avno check.


   if (!GETSUPERVISOR()) {

       SWAPA7withSSP();
       SETSUPERVISOR(1);
     // 2005.02.01 - removed if statement to force flush here on switch from user to supervisor mode
     //if (segment1|segment2)                 // if we're not in supervisor space already, flush the mmu
       {DEBUG_LOG(0,"Turning Supervisor flag on while in internal_vector flushing mmu context=%d s1/s2=%d/%d start=%d\n",context,segment1,segment2,start);
        SET_MMU_DIRTY(0xdec0de);  mmuflush(0x3000);
        DEBUG_LOG(0,"post mmuflush context=%d s1/s2=%d/%d start=%d\n",context,segment1,segment2,start);
       }

       DEBUG_LOG(5,"S mode change SP:%08x/A7:%08x swapped.",reg68k_regs[15],regs.sp);
       lastsflag=reg68k_sr.sr_struct.s;  regs.pc = reg68k_pc; regs.sr.sr_int = reg68k_sr.sr_int;
    }

   // might be a retake of the same addr/bus error on same opcode.  doh!  ie: when btst is done (read, write) two bus errors can occur
   // this is here because the previous run would have set Supervisor, and if it was already set before that, that's fine too
   // the problem is the following fetchlong can't be done until mmu context is set, and mmu is flushed, else gremlins

   abort_opcode=2;
   if (GETVECTOR(vno)==oldpc)  {loopy_vector--; abort_opcode=0;//DEBUG_LOG(0,"retake of same vector");
                                return;}
   if (abort_opcode==1)        {DEBUG_LOG(0,"Doh! got abort_opcode=1 on vector fetch in %s!\n",__FUNCTION__); EXIT(782);}
   abort_opcode=0;

   if (regs.stop && nmi_clk && nmi_pc) {regs.stop=0; nmi_addr_err=0;  nmi_clk=0; nmi_pc=0; nmi_stop=0;}      // clear flags
   else if (regs.stop)
   {
       DEBUG_LOG(0,"exiting from STOP opcode @%08x - will continue at %08x after ISR handles IRQ:%d.",reg68k_pc,reg68k_pc+4,vno);
       oldpc+=4;
       regs.stop = 0;
       reg68k_pc=oldpc;
       pc24=oldpc;
       regs.pc = oldpc; regs.sr = reg68k_sr;
   }

    DEBUG_LOG(0,"PUSH PC %08x context:%d",oldpc,context);
         if (vno==2 || vno==3)
         {

            if        ((InstructionRegister & 0xff00)==0x4a00) {oldpc+=2;}
            else if   ((InstructionRegister & 0xff00)==0x4e00)
            {
              if      ((InstructionRegister & 0x00f0)==0x00d0) {oldpc+=2;}
              else if ((InstructionRegister & 0x00ff)==0x0075) {oldpc+=2; regs.sp+=4;}
              else if ((InstructionRegister & 0x00ff)==0x0073) {oldpc+=0;}
              else if ((InstructionRegister & 0x00ff)==0x00f9) {oldpc+=2;}
              else if ((InstructionRegister & 0x00ff)==0x00b9) {oldpc+=6;}
              else if ((InstructionRegister & 0x00ff)==0x00a8) {oldpc+=4;}
              else if ((InstructionRegister & 0x00ff)==0x0090) {oldpc+=2;}
              else    oldpc+=(cpu68k_iibtable[InstructionRegister]->wordlen<<1);
            }
         }


         A7PUSH_LONG(oldpc); //   ? (oldpc+(cpu68k_iibtable[InstructionRegister]->wordlen<<1)) : oldpc);

         if (abort_opcode==1) {DEBUG_LOG(0,"Doh! got abort_opcode=1 on push pc %s!\n",__FUNCTION__); EXIT(783);}
    DEBUG_LOG(0,"PUSH SR %04x context:%d",saved_sr,context);  A7PUSH_WORD(saved_sr); if (abort_opcode==1) {DEBUG_LOG(0,"Doh! got abort_opcode=1 on push sr in %s!\n",__FUNCTION__); EXIT(784);}
    // "Short format 0 only four words are to be removed from the top of the stack. SR and PC are loaded from the stack frame."
    abort_opcode=0;

   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   if (vno==2 || vno==3)               // PUSH IS IN THIS ORDER: ---> PC,SR,IR,ADDR,BUSFN
   {  // memerror=(uint16)(( CHK_MMU_TRANS(addr_error) )>>5);

       memerror=(uint16)((               addr_error  )>>5);

       busfunctioncode=CPU_function_code | (CPU_READ_MODE<<4) |1;

       cpu68k_clocks+=(116*2); // Addr/Bus  // *2 2005.04.13.18:43

       DEBUG_LOG(0,"BUS_OR_ADDR: ADDR error:%d at PC:%08x pc24:%08x addr:%08x clk:%016llx - pushing extended exception frame for 68000",
            vno,oldpc,pc24,addr_error,cpu68k_clocks);

       DEBUG_LOG(0,"PUSH IR:%04x context:%d",InstructionRegister,context); A7PUSH_WORD(InstructionRegister);  if (abort_opcode==1) {DEBUG_LOG(0,"Doh! got abort_opcode=1 on push IR    in %s!\n",__FUNCTION__); EXIT(784);}
       DEBUG_LOG(0,"PUSH AE:%08x context:%d",addr_error,context);          A7PUSH_LONG(addr_error);           if (abort_opcode==1) {DEBUG_LOG(0,"Doh! got abort_opcode=1 on push ADDRC in %s!\n",__FUNCTION__); EXIT(784);}
       DEBUG_LOG(0,"PUSH BF:%04x context:%d",busfunctioncode,context);     A7PUSH_WORD(busfunctioncode);      if (abort_opcode==1) {DEBUG_LOG(0,"Doh! got abort_opcode=1 on push BUSFN in %s!\n",__FUNCTION__); EXIT(784);}

       // prevent autovectors from interrupting BUS/ADDR exception ISR's.
       //DEBUG_LOG(0,"Set Mask to 7 for BUS/ADDR Exception");

       // this might not be such a good idea
       // reg68k_sr.sr_int |=(7 << 8);      // no need for &= since we turn on all 3 bits.
       regs.pc = reg68k_pc;  regs.sr.sr_int = reg68k_sr.sr_int;
   }
   else // is this an autovector? if so handle that.
   {    if (avno)                                   //2005.02.02 - code refactoring/consolidation
        {
         #ifdef DEBUG
          if (avno==1 && floppy_FDIR) append_floppy_log("reg68k_int_av_ ***Firing IRQ1 because FDIR is set***\n");
         #endif

        //reg68k_sr.sr_struct.t = 0;                // disable trace bit - no need for it - it's handled below
          reg68k_sr.sr_int &= ~0x0700;              // clear IRQ Mask
          reg68k_sr.sr_int |= (avno<<8);            // set IRQ mask to avno
        //tmpaddr = reg68k_pc;                      // not used

          DEBUG_LOG(0,"autovector#%d V_AUTO:%08x Vector address: %d * 4 = %08x",vno-V_AUTO+1,V_AUTO,vno,(vno*4));

        //abort_opcode=2;reg68k_pc = GETVECTOR(vno);  if (abort_opcode==1) {fprintf(buglog,"Doh! got abort_opcode=1 while fetching vector for IRQ!\n"); EXIT(781);}
        }

       cpu68k_clocks+=87;  // IRQ1-7

   }


   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    abort_opcode=2;  reg68k_pc=GETVECTOR(vno);    // should turn this into vector 15 - spurious IRQ
    if (abort_opcode==1) {DEBUG_LOG(0,"Doh got abort_opcode=1 on vector fetch in %s - BYE BYE\n",__FUNCTION__); EXIT(58);}
    abort_opcode=0;

    DEBUG_LOG(0,"SRC: VECTOR IRQ: %s oldpc:%08x -> newpc:%08x A7=%08x SP=%08x Mode pre-IRQ:%s\n",
            getvector(vno), oldpc, reg68k_pc,reg68k_regs[15],regs.sp, (old_supervisor ? "Supervisor":"User"));

    regs.pending = get_pending_vector();                                           // not sure that I need this any longer - RA

    if (0==reg68k_pc) {debug_on("reg68k_pc=0"); DEBUG_LOG(0,"reg68k_pc got nullified. bye");  exit(59);}
    if (reg68k_pc& 1)   LISA_REBOOTED();

    reg68k_sr.sr_struct.t=0;                                                       // turn off trace on trap.
    regs.pc = reg68k_pc; regs.sr.sr_int = reg68k_sr.sr_int;                        // flush to external copy of regs
    DEBUG_LOG(0,"Done with vector fn. regs.pc=%08x reg68k_pc:%08x",regs.pc,reg68k_pc);

    abort_opcode=0;
    return;
}


#ifdef DEBUG
void print_pc_and_regs(char *text)
{
  fprintf(buglog,"\n\n%s PC%08x\n",text, reg68k_pc);  fflush(buglog);
  printregs(buglog,""); fflush(buglog);
}
#endif

void lisa_buserror(uint32 addr_error)
{
    reg68k_internal_vector(2 ,reg68k_pc, addr_error);
    abort_opcode=1;
}

#define LINE(x) DEBUG_LOG(0,"%s:%s:%d %s LINE LOG"       ,__FILE__,__FUNCTION__,__LINE__,x); fflush(buglog);

void lisa_mmu_exception(uint32 addr_error)
{
   char temp[1024];

   //20060105 memerror=(uint16)(( CHK_MMU_TRANS(addr_error)+(maxlisaram!=RAM1024K ? 0:RAM512K) )>>5);
   memerror=(uint16)(( CHK_MMU_TRANS(addr_error) )>>5);

   DEBUG_LOG(0,"MMU BUSERROR: IR:%04x @ %d/@%08x :: buserr@addr:%08x -> phys-addr:%08x SOR:%04x SLR:%04x %s",
         InstructionRegister,context,reg68k_pc,
         addr_error,
         CHK_MMU_REGST(addr_error),
         mmu[(addr_error & MMUSEGFILT)>>17].sor,
         mmu[(addr_error & MMUSEGFILT)>>17].slr,
         printslr(temp,1024, mmu[(addr_error & MMUSEGFILT)>>17].slr)
         );

   reg68k_internal_vector(2,reg68k_pc,addr_error);
   abort_opcode=1;
}


void lisa_addrerror(uint32 addr_error)
{
    DEBUG_LOG(0,"Odd Address Exception @%08x PC=%08x clk:%016llx ",addr_error,reg68k_pc,cpu68k_clocks);

    DEBUG_LOG(0,"ADDRESS EXCEPTION @%08x PC=%08x",addr_error,reg68k_pc);
    reg68k_internal_vector(3,reg68k_pc,addr_error);
    abort_opcode=1;
}


// this may only be called from internal land!
void lisa_nmi_vector(uint32 addr_error)
{
   //unused//uint32 pc_before_nmi=reg68k_pc;

   //20060105memerror=(uint16)(( CHK_MMU_TRANS(addr_error)+(maxlisaram!=RAM1024K ? 0:RAM512K) )>>5);
    memerror=(uint16)(( CHK_MMU_TRANS(addr_error) )>>5);

   DEBUG_LOG(0,"NMI @%08x PC=%08x clk:%016llx memerr latch:%04x - resucitated memlatch:%08x",addr_error,reg68k_pc,cpu68k_clocks,memerror,(uint32)(memerror<<5));
   DEBUG_LOG(0,"NMI Exception @%08x (phys:%08x) PC=%08x clk:%016llx ",
                addr_error,
                (CHK_MMU_TRANS(addr_error)),
                reg68k_pc,
                cpu68k_clocks);

   DEBUG_LOG(0,"NMI ERROR: current state: context:%d seg1:%d seg2:%d start:%d",context,segment1,segment2,start);




   nmi_pc      = reg68k_pc;
   nmi_addr_err= addr_error;
   nmi_clk     = cpu68k_clocks;
   nmi_stop    = regs.stop;

   regs.stop=1;
   return;

  ///////////// old dead code////////////////// CODEKARMA CODE KARMA CLEANUP CLEAN UP
   return;



   #ifdef disabled_2005_02_01
   DEBUG_LOG(0,"NMI @%08x pc24==%08x reg68k_pc:%08",addr_error,pc24,reg68k_pc);

   if (abort_opcode || last_nmi_error_pc==reg68k_pc) {fprintf(buglog,"suppressing NMI - abort_opcode=1\n"); return;}

    //#ifdef DEBUG
      if (nmi_error_trap>3 || last_nmi_error_pc==pc24) {fprintf(buglog,"NMI on top of NMI!\n"); EXIT(786);};
      last_nmi_error_pc=reg68k_pc;
      nmi_error_trap++;
    //#endif

    DEBUG_LOG(0,"*** SRC: Lisa NMI - likely for parity test @ %08x pc=%08x ***",addr_error,reg68k_pc);

    // Be sure to change from regs68k.pc to reg68k_pc if changing this to internal!

    DEBUG_LOG(0,"int VECTOR 1F (autovector 6 NMI.  mem addr:%08x, reg68k_pc:%08x pc24:%08x lastpc24:%08x",addr_error,reg68k_pc,pc24, lastpc24);

   // reg68k_external_autovector(7);         // using 7 now    ???

       if (!insetjmpland)
       {fprintf(buglog,"*** DANGER Entering %s:%s:%d from %s setjmpland*****\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside")); fflush(buglog); EXIT(1);}

    reg68k_internal_vector(0x1f, reg68k_pc,addr_error);  // 7 is wrong for vector, right for autovector.
    abort_opcode=1; // not tru                     // NMI is an IRQ - DOES not abort an opcode.  Just signals after completion of opcode

    DEBUG_LOG(0,"Done with external_vector call. reg68k_pc is now %08x, it originally was %08x",reg68k_pc,pc_before_nmi);
    if (pc24 & 1) fprintf(buglog,"%s:%s:%d PC24 is now odd!!!!%08x\n",__FILE__,__FUNCTION__,__LINE__,pc24);
    //#ifdef DEBUG
      nmi_error_trap--;
    //#endif
   #endif
}

void lisa_external_nmi_vector(uint32 addr_error)
{
   uint32 pc_before_nmi=reg68k_pc;

   DEBUG_LOG(0,"External NMI vector @%08x PC=%08x clk:%016llx ",addr_error,reg68k_pc,cpu68k_clocks);

   DEBUG_LOG(0,"\n** NMI @%08x pc24==%08x\n",addr_error,pc24);
   DEBUG_LOG(0,"NMI extern ");

   if (abort_opcode || last_nmi_error_pc==reg68k_pc) {fprintf(buglog,"suppressing NMI - abort_opcode=1\n"); return;}

    //#ifdef DEBUG
      if (nmi_error_trap>3 || last_nmi_error_pc==pc24) {fprintf(buglog,"NMI on top of NMI!\n"); EXIT(786);};
      last_nmi_error_pc=reg68k_pc;
      nmi_error_trap++;
    //#endif

    DEBUG_LOG(0,"*** SRC: Lisa NMI - likely for parity test @ %08x pc=%08x ***",addr_error,reg68k_pc);

    // Be sure to change from regs68k.pc to reg68k_pc if changing this to internal!

    DEBUG_LOG(0,"int VECTOR 1F (autovector 6 NMI.  mem addr:%08x, reg68k_pc:%08x pc24:%08x lastpc24:%08x",addr_error,reg68k_pc,pc24, lastpc24);

   if (!insetjmpland)
       {fprintf(buglog,"*** DANGER Entering %s:%s:%d from %s setjmpland*****\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside")); fflush(buglog); EXIT(1);}

   // reg68k_external_autovector(7);         // using 7 now    ???
    memerror=(uint16)(( CHK_MMU_TRANS(addr_error) )>>5);
    reg68k_external_vector(0x1f, reg68k_pc,addr_error);  // 7 is wrong for vector, right for autovector.  // DANGER DANGER was pc24
    abort_opcode=1;                                      /// VERY STRANGE THAT THIS NEEDS TO BE SO!!! Something odd about this???

    DEBUG_LOG(0,"Done with external_vector call. reg68k_pc is now %08x, it originally was %08x",reg68k_pc,pc_before_nmi);
    if (reg68k_pc & 1) fprintf(buglog,"%s:%s:%d reg68k_pc is now odd!!!!%08x\n",__FILE__,__FUNCTION__,__LINE__,pc24);
    //#ifdef DEBUG
      nmi_error_trap--;
    //#endif
}


