Annotation of hatari/src/m68000.c, revision 1.1.1.2

1.1       root        1: /*
                      2:   Hatari
                      3: 
                      4:   M68000 - CPU. This handles exception handling as well as a few OpCode's such as Line-F and Line-A.
                      5:   We also have a function to save off the last 'x' instruction ran which is very handy for debugging
                      6:   as we can see what code was run before a crash etc...
                      7:   (Other CPU functions can be found in 'decode.asm/.inc')
                      8: */
                      9: 
                     10: #include "main.h"
                     11: #include "bios.h"
                     12: #include "cart.h"
                     13: #include "debug.h"
                     14: #include "decode.h"
                     15: #include "disass.h"
                     16: #include "fdc.h"
                     17: #include "gemdos.h"
                     18: #include "ikbd.h"
                     19: #include "int.h"
                     20: #include "m68000.h"
                     21: #include "memAlloc.h"
                     22: #include "memorySnapShot.h"
                     23: #include "mfp.h"
                     24: #include "misc.h"
                     25: #include "psg.h"
                     26: #include "screen.h"
                     27: #include "stMemory.h"
                     28: #include "tos.h"
                     29: #include "vdi.h"
                     30: #include "view.h"
                     31: #include "xbios.h"
                     32: 
                     33: 
                     34: /* Taken from Decode.asm - Thothy */
                     35: /* These should be replaced with UAE's CPU core equivalents one day */
                     36: unsigned short SR_Before;
                     37: unsigned long ExceptionVector;
                     38: short int PendingInterruptFlag;
                     39: void *PendingInterruptFunction;
                     40: short int PendingInterruptCount;
                     41: int SoundCycles;
                     42: BOOL bInSuperMode;
                     43: unsigned long EmuCCode;
                     44: unsigned long BusAddressLocation;
                     45: 
                     46: 
                     47: /* Use these if want to bring up any bus/address error, else uses 68000 vector handler */
                     48: #ifndef FINAL_VERSION
                     49: //  #define TRAP_BUSERROR_HISTORY                 // Output history on true Bus Error(bombs display)
                     50: //  #define TRAP_ADDRESSERROR_HISTORY             // Or Address Error
                     51: //  #define TRAP_ILLEGALINSTRUCTIONERROR_HISTORY  // Or Illegal Instruction
                     52: #endif
                     53: 
                     54: BOOL bDoTraceException;          /* Do TRACE? */
                     55: 
                     56: 
                     57: //-----------------------------------------------------------------------
                     58: /*
                     59:   Reset CPU 68000 variables
                     60: */
                     61: void M68000_Reset(BOOL bCold)
                     62: {
                     63:   int i;
                     64: 
                     65:   // Clear registers, set PC, SR and stack pointers
                     66:   if (bCold) {
                     67:     for(i=0; i<(16+1); i++)
                     68:       Regs[i] = 0;
                     69:   }
                     70:   PC = TOSAddress;                            /* Start of TOS image, 0xfc0000 or 0xe00000 */
                     71:   SR = 0x2700;                                /* Starting status register */
                     72:   bDoTraceException = FALSE;                  /* No TRACE exceptions */
                     73:   bInSuperMode = TRUE;                        /* We begin in supervisor mode */
                     74:   Regs[REG_A7] = Regs[REG_A8] = 0x0000f000;   /* Stack default */
1.1.1.2 ! root       75:   PendingInterruptFlag = 0;                   /* Clear pending flag */
1.1       root       76: 
                     77:   // Read Supervisor Stack/PC for warm reset
                     78:   if (!bCold) {
                     79:     Regs[REG_A8] = STMemory_ReadLong(0x00000000);
                     80:     PC = STMemory_ReadLong(0x00000004);
                     81:   }
                     82: 
                     83:   // Hold display for extended VDI resolutions(under init our VDI)
                     84:   bHoldScreenDisplay = TRUE;
                     85: }
                     86: 
                     87: //-----------------------------------------------------------------------
                     88: /*
                     89:   Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                     90: */
                     91: void M68000_MemorySnapShot_Capture(BOOL bSave)
                     92: {
                     93:   // Save/Restore details
                     94:   MemorySnapShot_Store(&bDoTraceException,sizeof(bDoTraceException));
                     95: }
                     96: 
                     97: //-----------------------------------------------------------------------
                     98: /*
                     99:   Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                    100:   This is for 'decode.asm' variables - as cannot use 'decode.c' as will overwrite assembler .obj file!
                    101: */
                    102: void M68000_Decode_MemorySnapShot_Capture(BOOL bSave)
                    103: {
                    104:   int ID;
                    105: 
                    106:   // Save/Restore details
                    107:   MemorySnapShot_Store(Regs,sizeof(Regs));
                    108:   MemorySnapShot_Store(&STRamEnd,sizeof(STRamEnd));
                    109:   MemorySnapShot_Store(&STRamEnd_BusErr,sizeof(STRamEnd_BusErr));
                    110:   MemorySnapShot_Store(&PendingInterruptCount,sizeof(PendingInterruptCount));
                    111:   MemorySnapShot_Store(&PendingInterruptFlag,sizeof(PendingInterruptFlag));
                    112:   if (bSave) {
                    113:     // Convert function to ID
                    114:     ID = Int_HandlerFunctionToID(PendingInterruptFunction);
                    115:     MemorySnapShot_Store(&ID,sizeof(int));
                    116:   }
                    117:   else {
                    118:     // Convert ID to function
                    119:     MemorySnapShot_Store(&ID,sizeof(int));
                    120:     PendingInterruptFunction = Int_IDToHandlerFunction(ID);
                    121:   }
                    122:   MemorySnapShot_Store(&PC,sizeof(PC));
                    123:   MemorySnapShot_Store(&SR,sizeof(SR));
                    124:   MemorySnapShot_Store(&SR_Before,sizeof(SR_Before));
                    125:   MemorySnapShot_Store(&bInSuperMode,sizeof(bInSuperMode));
1.1.1.2 ! root      126:   /*MemorySnapShot_Store(&Reg_SuperSP,sizeof(Reg_SuperSP));*//*FIXME*/
        !           127:   /*MemorySnapShot_Store(&Reg_UserSP,sizeof(Reg_UserSP));*/
1.1       root      128:   MemorySnapShot_Store(&EmuCCode,sizeof(EmuCCode));
                    129:   MemorySnapShot_Store(&ExceptionVector,sizeof(ExceptionVector));  
                    130: }
                    131: 
                    132: //-----------------------------------------------------------------------
                    133: /*
                    134:   ILLEGAL - Unknown 68000 OpCode
                    135: */
                    136: void M68000_IllegalInstruction(void)
                    137: {
                    138: fprintf(stderr, "M68000_IllegalInstruction\n");
                    139:   ADD_CYCLES(34,4,3);
                    140:   ExceptionVector = EXCEPTION_ILLEGALINS;  /* Illegal vector */
                    141:   M68000_Exception();        /* Cause trap */
                    142: //  RET;
                    143: }
                    144: 
                    145: //-----------------------------------------------------------------------
                    146: /*
                    147:   BUSERROR - Access outside valid memory range
                    148: */
                    149: void M68000_BusError(unsigned long addr)
                    150: {
                    151:  /* Reset PC's stack to normal(as may have done many calls) so return to
                    152:     correct level after exception.
                    153:     Enter here with 'ebp' as address we tried to access */
1.1.1.2 ! root      154:  if(addr!=0xff8a00)
        !           155:   fprintf(stderr, "M68000_BusError at address $%lx\n", (long)addr);
1.1       root      156:  BusAddressLocation=addr;    /* Store for exception frame */
                    157:  ExceptionVector = EXCEPTION_BUSERROR;  /* Handler */
                    158:  M68000_Exception();      /* Cause trap */
                    159: /*
                    160:  asm("  mov  [BusAddressLocation],ebp\n"      // Store for exception frame
                    161:      "  mov  esp,[StackSave]\n"        // Restore stack
                    162:      "  mov  [ExceptionVector],EXCEPTION_BUSERROR\n");  // Handler
                    163:  SAVE_ASSEM_REGS();            // Save assembly registers
                    164:  asm("   call  M68000_Exception\n");        // Cause trap
                    165:  RESTORE_ASSEM_REGS();            // Restore assembly registers
                    166:  RET;                // Start decoding
                    167: */
                    168: }
                    169: 
                    170: //-----------------------------------------------------------------------
                    171: /*
                    172:   ADDRESSERROR - Access incorrect memory boundary, eg byte offset for a word access
                    173: */
                    174: void M68000_AddressError(unsigned long addr)
                    175: {
                    176: fprintf(stderr, "M68000_AddressError at address $%lx\n", (long)addr);
                    177:  BusAddressLocation=addr;    /* Store for exception frame */
                    178:  ExceptionVector=EXCEPTION_ADDRERROR;  /* Handler */
                    179:  M68000_Exception();      /* Cause trap */
                    180: /*
                    181:  // Reset PC's stack to normal(as may have done many calls) so return to correct level after exception
                    182:  __asm {
                    183:   // Enter here with 'ebp' as address we tried to access
                    184:   mov    [BusAddressLocation],ebp    // Store for exception frame
                    185:   mov    esp,[StackSave]        // Restore stack
                    186:   mov    [ExceptionVector],EXCEPTION_ADDRERROR  // Handler
                    187:   SAVE_ASSEM_REGS            // Save assembly registers
                    188:   call  M68000_Exception        // Cause trap
                    189:   RESTORE_ASSEM_REGS          // Restore assembly registers
                    190:   }
                    191:   RET                // Start decoding
                    192: */  
                    193: }
                    194: 
                    195: //-----------------------------------------------------------------------
                    196: /*
                    197:   See if in user/super mode and if need to swap SP
                    198: */
                    199: void M68000_CheckUserSuperToggle(void)
                    200: {
                    201:   unsigned long *TempReg;
                    202:   unsigned long TempSP;
                    203: 
                    204:   // Have we swapped mode?
                    205:   if ( (SR_Before&SR_SUPERMODE)!=(SR&SR_SUPERMODE) ) {
                    206:     // Yes, swap to ST's REG_A8!
                    207:     TempSP = Regs[REG_A7];
                    208:     Regs[REG_A7] = Regs[REG_A8];
                    209:     Regs[REG_A8] = TempSP;
                    210: 
                    211:     // Swap super flag
                    212:     bInSuperMode^=TRUE;
                    213:   }
                    214: 
                    215:   // Set/Clear trace mode
                    216:   if (SR&SR_TRACEMODE) {
                    217:     // Have we set the TRACE bit for the FIRST time? Don't let exception occur until NEXT instruction
                    218:     // NOTE Sometimes the TRACE bit can be set many times, so only skip exception on FIRST one
                    219:     if ((PendingInterruptFlag&PENDING_INTERRUPT_FLAG_TRACE)==0) {
                    220:       PendingInterruptFlag |= PENDING_INTERRUPT_FLAG_TRACE;
                    221:       bDoTraceException = FALSE;
                    222:     }
                    223:   }
                    224:   else
                    225:     PendingInterruptFlag &= CLEAR_PENDING_INTERRUPT_FLAG_TRACE;
                    226: }
                    227: 
                    228: //-----------------------------------------------------------------------
                    229: /*
                    230:   Called when TRACE bit is set. This causes 'exception' after each instruction, BUT
                    231:   it does not execute after the FIRST 'move SR,xxxx' to set the bit
                    232: */
                    233: void M68000_TraceModeTriggered(void)
                    234: {
                    235: /* FIXME */
                    236: /*
                    237:   __asm {
                    238:     cmp    [bDoTraceException],FALSE    // First time around? Skip exception
                    239:     je    dont_need_expection
                    240: 
                    241:     mov    [ExceptionVector],EXCEPTION_TRACE  // Handler
                    242:     SAVE_ASSEM_REGS            // Save assembly registers
                    243:     call  M68000_Exception        // Cause trap
                    244:     RESTORE_ASSEM_REGS          // Restore assembly registers
                    245: 
                    246: dont_need_expection:;
                    247:     mov    [bDoTraceException],TRUE    // Do TRACE exception next time around
                    248:     ret
                    249:   }
                    250: */
                    251: }
                    252: 
                    253: //-----------------------------------------------------------------------
                    254: /*
                    255:   Exception handler
                    256: */
                    257: void M68000_Exception(void)
                    258: {
                    259:   unsigned long Vector,MFPBaseVector;
                    260:   BOOL bRet=FALSE;
                    261: 
1.1.1.2 ! root      262:   /* Was the CPU stopped, i.e. by a STOP instruction? */
        !           263:   regs.stopped = 0;
        !           264:   unset_special (SPCFLAG_STOP);   /* All is go,go,go! */
        !           265: 
1.1       root      266:   /* At the moment, this functions ist just a wrapper to Exception() of the UAE CPU - Thothy */
                    267:   Exception(ExceptionVector/4, m68k_getpc());
1.1.1.2 ! root      268: 
1.1       root      269:   return;
                    270: 
                    271: #if 0
                    272:   // Was the CPU stopped, ie by a STOP instruction?
                    273: /* FIXME: */
                    274: /*
                    275:   if (CPUStopped) {
                    276:     PC += 4;    // Skip after the STOP instruction as CPU is now to resume!
                    277:     CPUStopped = FALSE;  // All is go,go,go!
                    278:   }
                    279: */
                    280:   /* Find exception vector, keep 32-bit address as top byte is used by TOS */
                    281:   /* exception vectors as an ID! */
                    282:   Vector = STMemory_ReadLong(ExceptionVector);
                    283: 
                    284:   /* Check for intercept - The game 'Operation Wolf' re-directs traps, */
                    285:   /* so double check is a TOS trap and not software! (ie Vector is >0xE00000) */
                    286:   if ((Vector&0xffffff)>=0xE00000) {
                    287:     if (ExceptionVector==EXCEPTION_TRAP13)
                    288:       bRet = Bios();
                    289:     else if (ExceptionVector==EXCEPTION_TRAP14)
                    290:       bRet = XBios();
                    291:     else if (ExceptionVector==EXCEPTION_TRAP1)
                    292:       bRet = GemDOS();
                    293:     else if (ExceptionVector==EXCEPTION_TRAP2) {
                    294:       bRet = VDI();
                    295:       if (!bRet) {
                    296:         // Set 'PC' as address of 'VDI_OPCODE' illegal instruction
                    297:         // This will call VDI_OpCode after completion of Trap call!
                    298:         // Use to modify return structure from VDI
                    299:         if (bUseVDIRes) {
                    300:           VDI_OldPC = PC;
                    301:           PC = CART_VDI_OPCODE_ADDR;
                    302:         }
                    303:       }
                    304:     }
                    305: 
                    306:   // Do handly bit of debugging to trap bus/address errors, before goes to TOS handler
                    307: #ifdef TRAP_BUSERROR_HISTORY
                    308:     if (ExceptionVector==EXCEPTION_BUSERROR) {
                    309:       MessageBox(NULL,"TRAP BUS ERROR",PROG_NAME,MB_OK | MB_ICONSTOP);
                    310:       Debug_File("TRAP BUS ERROR\n");
                    311:       M68000_OutputHistory();
                    312:       exit(0);
                    313:     }
                    314: #endif
                    315: #ifdef TRAP_ADDRESSERROR_HISTORY
                    316:     if (ExceptionVector==EXCEPTION_ADDRERROR) {
                    317:       MessageBox(NULL,"TRAP ADDRESS ERROR",PROG_NAME,MB_OK | MB_ICONSTOP);
                    318:       Debug_File("TRAP ADDRESS ERROR\n");
                    319:       M68000_OutputHistory();
                    320:       exit(0);
                    321:     }
                    322: #endif
                    323: #ifdef TRAP_ILLEGALINSTRUCTIONERROR_HISTORY
                    324:     if (ExceptionVector==EXCEPTION_ILLEGALINS) {
                    325:       MessageBox(NULL,"TRAP ILLEGAL INSTRUCTION ERROR",PROG_NAME,MB_OK | MB_ICONSTOP);
                    326:       Debug_File("TRAP ILLEGAL INSTRUCTION ERROR\n");
                    327:       M68000_OutputHistory();
                    328:       exit(0);
                    329:     }
                    330: #endif
                    331:   }
                    332: 
                    333:   // Did we re-direct call? No, so let's call it!
                    334:   if (!bRet) {
                    335:     // Save PC and SR to supervisor stack
                    336: /* FIXME */
                    337: /*
                    338:     __asm {
                    339:       push  ebp
                    340: 
                    341:       mov    edx,[Reg_SuperSP]
                    342: 
                    343:       sub    DWORD PTR [edx],SIZE_LONG
                    344:       mov    ebp,[edx]        // Stack pointer
                    345:       and    ebp,0xffffff        // as 24-bit address in PC memory(note _C)
                    346:       mov    ecx,[PC]        // Save PC
                    347:       SWAP_ENDIAN_LONG_ECX
                    348:       mov    DWORD PTR STRam[ebp],ecx
                    349: 
                    350:       sub    DWORD PTR [edx],SIZE_WORD
                    351:       mov    ebp,[edx]        // Stack pointer
                    352:       and    ebp,0xffffff        // as 24-bit address in PC memory(note _C)
                    353:       mov    cx,WORD PTR [SR]
                    354:       and    ecx,SR_MASK        // Remove condition codes
                    355:       mov    eax,[EmuCCode]
                    356:       shr    eax,4          // Emulation codes in correct bits
                    357:       and    eax,SR_CCODE_MASK
                    358:       or    eax,ecx          // Or in current condition codes
                    359:       SWAP_ENDIAN_WORD_AX
                    360:       mov    WORD PTR STRam[ebp],ax
                    361: 
                    362:       pop    ebp
                    363:     }
                    364: */
                    365:     // Exception frame, total 14 bytes (6 already put on stack, ie PC and SR)
                    366:     //       15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
                    367:     // SSP->|                                |RW|IN|Func.cod|         Higher
                    368:     // address
                    369:     //      |High word access address                       |
                    370:     //      |Low word access address                        |
                    371:     //      |Instruction register                           |
                    372:     //      |Status register                                |
                    373:     //      |High word program counter                      |
                    374:     //      |Low word program counter                       |         Lower address
                    375:     // 
                    376:     // RW: Write=0, Read=1
                    377:     // IN: Instruction=0, Not=1
                    378:     if ( (ExceptionVector==EXCEPTION_BUSERROR) || (ExceptionVector==EXCEPTION_ADDRERROR) ) {
                    379: /* FIXME */
                    380: /*
                    381:       __asm {
                    382:         push  ebp
                    383: 
                    384:         mov    ebp,[InsPC]      // Get PC of instruction last ran
                    385:         mov    cx,WORD PTR [ebp]    // 'Opcode' in 68000 endian
                    386:         mov    edx,[Reg_SuperSP]
                    387:         sub    DWORD PTR [edx],SIZE_WORD
                    388:         mov    ebp,[edx]      // Stack pointer
                    389:         and    ebp,0xffffff      // as 24-bit address in PC memory(note _C)
                    390:         mov    WORD PTR STRam[ebp],cx    // Store 'Instruction Register'
                    391: 
                    392:         sub    DWORD PTR [edx],SIZE_LONG
                    393:         mov    ebp,[edx]      // Stack pointer
                    394:         and    ebp,0xffffff      // as 24-bit address in PC memory(note _C)
                    395:         mov    ecx,[BusAddressLocation]  // Address which caused fault
                    396:         SWAP_ENDIAN_LONG_ECX
                    397:         mov    DWORD PTR STRam[ebp],ecx
                    398: 
                    399:         sub    DWORD PTR [edx],SIZE_WORD
                    400:         mov    ebp,[edx]      // Stack pointer
                    401:         and    ebp,0xffffff      // as 24-bit address in PC memory(note _C)
                    402:         xor    ecx,ecx
                    403:         mov    WORD PTR STRam[ebp],cx    // '0' for now
                    404: 
                    405:         pop    ebp
                    406:       }
                    407: */
                    408:     }
                    409: 
                    410:     SR_Before = SR;
                    411:     SR &= SR_CLEAR_TRACEMODE;            // Clear trace mode (bit 15)
                    412:     SR |= SR_SUPERMODE;                // Set super mode (bit 13)
                    413:     M68000_CheckUserSuperToggle();          // Check if swapped mode
                    414: 
                    415:     // Do call to vector
                    416: //    char szString[256];
                    417: //    sprintf(szString,"0x%X (0x%X)",Vector,ExceptionVector);
                    418: //    debug << szString << endl;
                    419:     PC = Vector;
                    420:     // Set Status Register so interrupt can ONLY be stopped by another interrupt of higher priority!
                    421:     if (ExceptionVector==EXCEPTION_VBLANK)
                    422:       SR = (SR&SR_CLEAR_IPL)|0x0400;        // VBL, level 4
                    423:     else if (ExceptionVector==EXCEPTION_HBLANK)
                    424:       SR = (SR&SR_CLEAR_IPL)|0x0200;        // HBL, level 2    
                    425:     else {
                    426:       MFPBaseVector = (unsigned int)(MFP_VR&0xf0)<<2;
                    427:       if ( (ExceptionVector>=MFPBaseVector) && (ExceptionVector<=(MFPBaseVector+0x34)) )
                    428:         SR = (SR&SR_CLEAR_IPL)|0x0600;      // MFP, level 6
                    429:     }
                    430:   }
                    431: #endif
                    432: }
                    433: 
                    434: //-----------------------------------------------------------------------
                    435: /*
                    436:   Handle Line-A OpCode exception(Top 4-bit in opcode are 0xA)
                    437: */
                    438: /*
                    439: void M68000_Line_A_OpCode_Execute(void)
                    440: {
                    441:   PC -= SIZE_WORD;    // PC needs to be at address of Line-A instruction
                    442:   ExceptionVector = EXCEPTION_LINE_A;
                    443:   M68000_Exception();
                    444: }
                    445: 
                    446: void M68000_Line_A_OpCode(void)
                    447: {
                    448: //FIXME   SAVE_ASSEM_REGS();        // Save assembly registers
                    449:   M68000_Line_A_OpCode_Execute();
                    450: //  RESTORE_ASSEM_REGS();        // Restore assembly registers
                    451: //  RET;
                    452: }
                    453: */
                    454: 
                    455: //-----------------------------------------------------------------------
                    456: /*
                    457:   During init do 0xA000, followed by 0xA0FF - we use this to get pointer to Line-A structure details(to fix for extended VDI res)
                    458: */
                    459: void M68000_Line_A_Trap(void)
                    460: {
                    461: /* FIXME */
                    462: /*
                    463: 
                    464:   PUSH_ALL
                    465:   __asm {
                    466:     mov    edx,DWORD PTR Regs[REG_D0*4]
                    467:     mov    [LineABase],edx
                    468:     mov    edx,DWORD PTR Regs[REG_A1*4]
                    469:     mov    [FontBase],edx
                    470:     call  VDI_LineA                // Modify Line-A structure
                    471:   }
                    472:   POP_ALL
                    473:   RET
                    474: */
                    475: }
                    476: 
                    477: //-----------------------------------------------------------------------
                    478: /*
                    479:   Handle Line-F OpCode exception(Top 4-bit in opcode are 0xF)
                    480: */
                    481: /*
                    482: void M68000_Line_F_OpCode_Execute(void)
                    483: {
                    484:   PC -= SIZE_WORD;    // PC needs to be at address of Line-F instruction
                    485:   ExceptionVector = EXCEPTION_LINE_F;
                    486:   M68000_Exception();
                    487: }
                    488: 
                    489: void M68000_Line_F_OpCode(void)
                    490: {
                    491: //FIXME   SAVE_ASSEM_REGS();    // Save assembly registers
                    492:   M68000_Line_F_OpCode_Execute();
                    493: //  RESTORE_ASSEM_REGS();      // Restore assembly registers
                    494: //  RET;
                    495: }
                    496: */
                    497: 
                    498: 
                    499: //-----------------------------------------------------------------------
                    500: /*
                    501:   Output CPU instruction history(last 'x' instructions) for debugging
                    502: */
                    503: void M68000_OutputHistory(void)
                    504: {
                    505: #ifndef FINAL_VERSION
                    506:   unsigned long StartPC;
                    507:   int i;
                    508: 
                    509:   /* First, Return back into a Window */
                    510:   Screen_ReturnFromFullScreen();
                    511:   View_ToggleWindowsMouse(MOUSE_WINDOWS);
                    512: 
                    513:   Debug_File("HISTORY\n");
                    514: 
                    515:   for(i=0; i<(INSTRUCTION_HISTORY_SIZE-1); i++) {
                    516:     StartPC = DisPC = InstructionHistory[(InstructionHistoryIndex+i+1)&INSTRUCTION_HISTORY_MASK];
                    517:     Disass_DiassembleLine();            // Disassemble instruction
                    518: 
                    519:     Debug_File("%8.8X\t%s\n",StartPC,szOpString);
                    520:   }
                    521: #endif
                    522: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.