X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=cpu%2Fa68k%2Fmake68kd.c;fp=cpu%2Fa68k%2Fmake68kd.c;h=9f64748f08621bd4481b7e3fe452ee5b651e8044;hb=cc68a136aa179a5f32fe40208371eb9c2b0aadae;hp=0000000000000000000000000000000000000000;hpb=2cadbd5e56966f8b7a4e9790aba2f719cfcc38e8;p=picodrive.git diff --git a/cpu/a68k/make68kd.c b/cpu/a68k/make68kd.c new file mode 100644 index 0000000..9f64748 --- /dev/null +++ b/cpu/a68k/make68kd.c @@ -0,0 +1,8192 @@ +/*--------------------------------------------------------------- + * Motorola 68000 32 Bit emulator + * + * Copyright 1998-2001 Mike Coates, All rights reserved + * Darren Olafson + *--------------------------------------------------------------- + * + * Thanks to ... + * + * Neil Bradley (lots of optimisation help & ideas) + * + *--------------------------------------------------------------- + * History (so we know what bugs have been fixed) + * + * 02.11.98 MJC - CMPM bug, overwriting first value + * 04.11.98 MJC - Debug timing - same as C core + * save PC on calls to C memory routines + * 05.11.98 NS - Re-insert changes to make work on OS/2 + * 06.11.98 MJC - Flags saved on ADDA commands + * X set on ADD commands + * 23.11.98 MJC - Alternate Memory Read/Write for non DOS ports + * 24.11.98 CK - Add WIN32 specific stuff + * 25.11.98 DEO - ABCD Size not initialised + * 21.12.98 MJC - Change register saving on Memory Banking + * 13.01.99 M/D - Change to new C core disassembler + * 19.01.99 MJC - Proper? support for new Interrupt System + * 17.02.99 MJC - TRACE68K define added + * ABCD,SBCD not keeping Z flag + * JMP, JSR for some EA combo's damaging flags + * DIVU - Overflow not being set correctly + * ASL/ASR - Flag Handling now correct + * some minor optimisations + * 13.03.99 DEO - Added new cycle timing + * 24.03.99 MJC - TRACE68K define removed + * NEW INTERRUPT SYSTEM only + * interrupt check sped up (when not taken) + * STOP checks for interrupt + * 01.04.99 MJC - OS2 specifics added + * MOVEM reference point moved + * Data and Address register mode combined for :- + * movecodes + * dumpx + * 04.05.99 MJC - Add Previous PC support to MOVE.B #X,XXXXXX.L (F1 Dream) + * ABCD/SBCD could corrupt zero flag + * DIVS/DIVU overflow should not update register + * 22.05.99 MJC - Complete support of Previous PC on C calls + * Some optional bits now selected by DEFINES + * 27.05.99 MJC - Interrupt system changed + * 28.05.99 MJC - Use DEFINES in more places + * Interrupt check running one opcode when taken + * 16.07.99 MJC - Reset - Preload next opcode / external call + * 68010 commands almost complete + * more compression on jump table (16k smaller) + * Some optimising + * shl reg,1 -> add reg,reg + * or ecx,ecx:jz -> jecxz + * 22.08.99 DEO - SBCD/ABCD sets N flag same as carry + * 19.10.99 MJC - Change DOS memory routines + * Change DOS Clobber flags (ESI no longer safe) + * Save EAX around memory write where needed + * bit commands optimised + * 25.10.99 MJC - Was keeping masked register on read/write + * if register was preserved over call + * ESI assumed 'safe' again + * 25.10.99 MJC - Bank ID moved to CPU context + * 03.11.99 KENJO - VC++6.0 seems not to preserve EDI. Fixed "ABCD -(A0), -(A0)" crash / "roxr (A0)"-type shift crash + * 13.11.99 KENJO - Fixed "NABC" + * Now Win32 uses FASTCALL type call for interrupt callback + * 09.02.00 MJC - Check CPU type before allowing 68010/68020 instructions + * remove routines for 5 non existant opcodes + * 05.03.00 MJC - not command decrement A7 by 1 for bytes + * 10.03.00 MJC - as did btst,cmpm and nbcd + * 22.03.00 MJC - Divide by zero should not decrement PC by 2 before push + * Move memory banking into exception routine + * 14.04.00 Dave - BTST missing Opcode + * ASL.L > 31 shift + * 20.04.00 MJC - TST.B Also missing A7 specific routine + * - Extra Define A7ROUTINE to switch between having seperate + * routines for +-(A7) address modes. + * 24.06.00 MJC - ADDX/SUBX +-(A7) routines added. + * TAS should not touch X flag + * LSL/LSR EA not clearing V flag + * CHK not all opcodes in jump table + * Add define to mask status register + * 04.07.00 MJC - Keep high byte of Program Counter on Bxx and Jxx + * Fix flag handling on NEGX + * Really fix ADDX/SUBX +-(A7) + * PC could be set wrong after CHK.W instruction + * DIVS/DIVU always clear C flag + * ABCD/SBCD missing +-(A7) Routine + * TAS missing +-(A7) Routine + * Bitwise Static missing +-(A7) Routine + * CMPM missing +-(A7) Routine + * 30.09.00 DEO - added mull, divl, bfextu + * added '020 addressing modes + * fixed $6xff branching + * 23.01.01 MJC - Spits out seperate code for 68000 & 68020 + * allows seperate optimising! + * 17.02.01 MJC - Support for encrypted PC relative fetch calls + * 11.03.01 GUTI - change some cmp reg,0 and or reg,reg with test + * 13.03.01 MJC - Single Icount for Asm & C cores + * 16.05.01 ASG - use push/pop around mem calls instead of store to safe_REG + * optimized a bit the 020 extension word decoder + * removed lots of unnecessary code in branches + *--------------------------------------------------------------- + * Known Problems / Bugs + * + * 68000 + * None - Let us know if you find any! + * + * 68010 + * Instructions that are supervisor only as per 68000 spec. + * move address space not implemented. + * + * 68020 + * only long Bcc instruction implemented. + *--------------------------------------------------------------- + * Notes + * + * STALLCHECK should be defined for Pentium Class + * undefined for P2/Celerons + * + * ALIGNMENT is normally 4, but seems faster on my P2 as 0 ! + * + *--------------------------------------------------------------- + * + * Future Changes + * + * 68020 instructions to be completed + * assembler memory routines + + * + * and anything else that takes our fancy! + *---------------------------------------------------------------*/ + +/* Specials - Switch what program allows/disallows */ + +#undef STALLCHECK /* Affects fetching of Opcode */ +#undef SAVEPPC /* Save Previous PC */ // dave +#define ENCRYPTED /* PC relative = decrypted */ +#define ASMBANK /* Memory banking algorithm to use */ // dave +#define A7ROUTINE /* Define to use separate routines for -(a7)/(a7)+ */ +#define ALIGNMENT 4 /* Alignment to use for branches */ +#undef MASKCCR /* Mask the status register to filter out unused bits */ +#define KEEPHIGHPC /* Keep or Ignore bits 24-31 */ +#define QUICKZERO /* selects XOR r,r or MOV r,0 */ + +#include +#include +#include +#include + +/* New Disassembler */ + +char * codebuf; +int DisOp; + +#define cpu_readmem24bew(addr) (0) +#define cpu_readmem24bew_word(addr) (DisOp) + +#define MEMORY_H /* so memory.h will not be included... */ +/* +#include "d68k.c" +*/ +#undef MEMORY_H + +#undef cpu_readmem24bew +#undef cpu_readmem24bew_word + +#include "cpuintrf.h" + +/* + * Defines used by Program + * + */ + +#define VERSION "0.30" + +#define TRUE -1 +#define FALSE 0 + +#define EAX 0 +#define EBX 1 +#define ECX 2 +#define EDX 3 +#define ESI 4 +#define PC ESI +#define EDI 5 +#define EBP 6 + + +#define NORMAL 0 +#define PCREL 1 + +/* Register Location Offsets */ + +#define ICOUNT "_m68k_ICount" + +#define REG_DAT "R_D0" +#define REG_DAT_EBX "[R_D0+ebx*4]" +#define REG_ADD "R_A0" +#define REG_A7 "R_A7" +#define REG_USP "R_USP" +#define REG_ISP "R_ISP" +#define REG_SRH "R_SR_H" +#define REG_CCR "R_CCR" +#define REG_X "R_XC" +#define REG_PC "R_PC" +#define REG_IRQ "R_IRQ" +#define REG_S "R_SR" +#define REG_IRQ_CALLBACK "R_IRQ_CALLBACK" +#define REG_RESET_CALLBACK "R_RESET_CALLBACK" + + +/* 68010 Regs */ + +#define REG_VBR "R_VBR" +#define REG_SFC "R_SFC" +#define REG_DFC "R_DFC" + +#define FASTCALL_FIRST_REG "ecx" +#define FASTCALL_SECOND_REG "edx" + + + +/* + * Global Variables + * + */ + +FILE *fp = NULL; + +char *comptab = NULL; +char *CPUtype = NULL; + +int CPU = 0; +int FlagProcess = 0; +int CheckInterrupt = 0; +int ExternalIO = 0; +int Opcount = 0; +int TimingCycles = 0; +int AddEACycles = 0; +int AccessType = NORMAL; +int ppro = 0; + + + +/* External register preservation */ + +#ifdef DOS + +/* Registers normally saved around C routines anyway */ +/* GCC 2.9.1 (dos) seems to preserve EBX,EDI and EBP */ +static char SavedRegs[] = "-B--SDB"; + +#elif defined(WIN32) + +/* visual C++, win32, says it preserves ebx, edi, esi, and ebp */ +/* ---------- VC++ deosn't preserve EDI? (Kenjo, 110399) ---------- */ +static char SavedRegs[] = "-B--S-B"; + +#else + +/* Assume nothing preserved */ +static char SavedRegs[] = "-------"; + +#endif + + + +/* Jump Table */ + +int OpcodeArray[65536]; + +/* Lookup Arrays */ + +static char* regnameslong[] = +{ "EAX","EBX","ECX","EDX","ESI","EDI","EBP"}; + +static char* regnamesword[] = +{ "AX","BX","CX","DX", "SI", "DI", "BP"}; + +static char* regnamesshort[] = +{ "AL","BL","CL","DL"}; + + + +/*********************************/ +/* Conversion / Utility Routines */ +/*********************************/ + +/* Convert EA to Address Mode Number + * + * 0 Dn + * 1 An + * 2 (An) + * 3 (An)+ + * 4 -(An) + * 5 x(An) + * 6 x(An,xr.s) + * 7 x.w + * 8 x.l + * 9 x(PC) + * 10 x(PC,xr.s) + * 11 #x,SR,CCR Read = Immediate, Write = SR or CCR + * in order to read SR to AX, use READCCR + * 12-15 INVALID + * + * 19 (A7)+ + * 20 -(A7) + * + */ + +int EAtoAMN(int EA, int Way) +{ + int Work; + + if (Way) + { + Work = (EA & 0x7); + + if (Work == 7) Work += ((EA & 0x38) >> 3); + + if (((Work == 3) || (Work == 4)) && (((EA & 0x38) >> 3) == 7)) + { + Work += 16; + } + } + else + { + Work = (EA & 0x38) >> 3; + + if (Work == 7) Work += (EA & 7); + + if (((Work == 3) || (Work == 4)) && ((EA & 7) == 7)) + { + Work += 16; + } + } + + return Work; +} + +/* + * Generate Main or Sub label + */ + +char *GenerateLabel(int ID,int Type) +{ + static int LabID,LabNum; +/* + static char disasm[80]; + char *dis = disasm; +*/ + if (Type == 0) + { + CheckInterrupt=0; /* No need to check for Interrupts */ + ExternalIO=0; /* Not left Assembler Yet */ + TimingCycles=0; /* No timing info for this command */ + AddEACycles=1; /* default to add in EA timing */ + Opcount++; /* for screen display */ + + DisOp = ID; +/* + m68k_disassemble(dis,0); + sprintf(codebuf, "OP%d_%4.4x:\t\t\t\t; %s", CPU,ID, dis); +*/ + sprintf(codebuf, "OP%d_%4.4x:\t\t\t\t;", CPU,ID); + + LabID = ID; + LabNum = 0; + } + else + { + LabNum++; + sprintf(codebuf, "OP%d_%4.4x_%1x", CPU,LabID, LabNum); + } + + return codebuf; +} + +/* + * Generate Alignment Line + */ + +void Align(void) +{ + fprintf(fp, "\t\t ALIGN %d\n\n",ALIGNMENT); +} + +/* + * Copy X into Carry + * + * There are several ways this could be done, this allows + * us to easily change the way we are doing it! + */ + +void CopyX(void) +{ + /* Copy bit 0 from X flag store into Carry */ + + fprintf(fp, "\t\t bt dword [%s],0\n",REG_X); +} + +/* + * Immediate 3 bit data + * + * 0=8, anything else is itself + * + * Again, several ways to achieve this + * + * ECX contains data as 3 lowest bits + * + */ + +void ClearRegister(int regno) +{ +#ifdef QUICKZERO + fprintf(fp, "\t\t mov %s,0\n",regnameslong[regno]); +#else + fprintf(fp, "\t\t xor %s,%s\n",regnameslong[regno],regnameslong[regno]); +#endif +} + +void Immediate8(void) +{ + /* This takes 3 cycles, 5 bytes, no memory reads */ + + fprintf(fp, "\t\t dec ecx ; Move range down\n"); + fprintf(fp, "\t\t and ecx,byte 7 ; Mask out lower bits\n"); + fprintf(fp, "\t\t inc ecx ; correct range\n"); + + + /* This takes 2 cycles, 10 bytes but has a memory read */ + /* I don't know timing for the mov command - assumed 1 */ + +#if 0 + fprintf(fp, "\t\t and ecx,byte 7\n"); + fprintf(fp, "\t\t mov ecx,[ImmTable+ECX*4]\n"); +#endif +} + +/* + * This will check for bank changes before + * resorting to calling the C bank select code + * + * Most of the time it does not change! + * + */ + +/* forward used by MemoryBanking */ +void Exception(int Number, int BaseCode) ; + +void MemoryBanking(int BaseCode) +{ + /* check for odd address */ + fprintf(fp, "\t\t test esi, dword 1\n"); + fprintf(fp, "\t\t jz near OP%d_%5.5x\n",CPU,BaseCode); + + /* trying to run at an odd address */ + Exception(3,BaseCode); + + /* Keep Whole PC */ + + fprintf(fp, "OP%d_%5.5x:\n",CPU,BaseCode); + +/* ASG - always call to the changepc subroutine now, since the number of */ +/* bits varies based on the memory model */ +#ifdef KEEPHIGHPC + fprintf(fp, "\t\t mov [FullPC],ESI\n"); +#endif + + /* Mask to n bits */ + fprintf(fp, "\t\t and esi,[_mem_amask]\n"); + +#if 0 +#ifdef KEEPHIGHPC + fprintf(fp, "\t\t mov [FullPC],ESI\n"); +#endif + + /* Mask to 24 bits */ +// fprintf(fp, "\t\t and esi,0ffffffh\n"); + +#ifdef ASMBANK + /* Assembler bank switch - 64k granularity */ + + fprintf(fp, "\t\t mov eax,esi\n"); + fprintf(fp, "\t\t shr eax,16\n"); + fprintf(fp, "\t\t cmp [asmbank],eax\n"); + fprintf(fp, "\t\t je OP%d_%5.5x_Bank\n",CPU,BaseCode); + + fprintf(fp, "\t\t mov [asmbank],eax\n"); +#else + /* This code is same as macro used by C core */ + + fprintf(fp, "\t\t mov ecx,esi\n"); + fprintf(fp, "\t\t mov ebx,[_cur_mrhard]\n"); + fprintf(fp, "\t\t shr ecx,9\n"); + fprintf(fp, "\t\t mov al,byte [_opcode_entry]\n"); + fprintf(fp, "\t\t cmp al,[ecx+ebx]\n"); + fprintf(fp, "\t\t je OP%d_%5.5x_Bank\n",CPU,BaseCode); +#endif +#endif + + /* Call Banking Routine */ + + if (SavedRegs[ESI] == '-') + { + fprintf(fp, "\t\t mov [%s],ESI\n",REG_PC); + } + + if (SavedRegs[EDX] == '-') + { + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + } + +#ifdef FASTCALL + fprintf(fp, "\t\t mov %s,esi\n",FASTCALL_FIRST_REG); +#else + fprintf(fp, "\t\t push esi\n"); +#endif + + fprintf(fp, "\t\t call [_a68k_memory_intf+28]\n"); + +#ifndef FASTCALL + fprintf(fp, "\t\t lea esp,[esp+4]\n"); +#endif + + if (SavedRegs[EDX] == '-') + { + fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR); + } + + if (SavedRegs[ESI] == '-') + { + fprintf(fp, "\t\t mov esi,[%s]\n",REG_PC); + } + + /* Update our copy */ + + fprintf(fp, "\t\t mov ebp,dword [_OP_ROM]\n"); + + fprintf(fp, "OP%d_%5.5x_Bank:\n",CPU,BaseCode); +} + +/* + * Update Previous PC value + * + */ + +void SavePreviousPC(void) +{ +#ifdef SAVEPPC + fprintf(fp, "\t\t mov [R_PPC],esi\t\t\t ; Keep Previous PC\n"); +#endif +} + +/* + * Complete Opcode handling + * + * Any tidying up, end code + * + */ + +void Completed(void) +{ + + /* Flag Processing to be finished off ? */ + + AccessType = NORMAL; + + /* Use assembler timing routines */ + + if (TimingCycles != 0) + { + if (TimingCycles > 127) + fprintf(fp, "\t\t sub dword [%s],%d\n",ICOUNT,TimingCycles); + else + { + if (TimingCycles != -1) + fprintf(fp, "\t\t sub dword [%s],byte %d\n",ICOUNT,TimingCycles); + } + + if (FlagProcess > 0) + fprintf(fp, "\t\t pop EDX\n"); + if (FlagProcess == 2) + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + + fprintf(fp, "\t\t js near MainExit\n\n"); + } + else + { + fprintf(fp, "\t\t test dword [%s],0xffffffff\n",ICOUNT); + + if (FlagProcess > 0) + fprintf(fp, "\t\t pop EDX\n"); + if (FlagProcess == 2) + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + + fprintf(fp, "\t\t jle near MainExit\n\n"); + } + FlagProcess = 0; + +#ifdef MAME_DEBUG + + /* Check for Debug Active */ + + fprintf(fp, "\n\t\t test byte [_mame_debug],byte 0xff\n"); + fprintf(fp, "\t\t jnz near MainExit\n\n"); + +#endif + + if (CheckInterrupt) + { + fprintf(fp,"; Check for Interrupt waiting\n\n"); + fprintf(fp,"\t\t test byte [%s],07H\n",REG_IRQ); + fprintf(fp,"\t\t jne near interrupt\n\n"); + } + + if(CPU==2) + { + /* 32 bit memory version */ + fprintf(fp, "\t\t mov eax,2\n"); /* ASG */ + fprintf(fp, "\t\t xor eax,esi\n"); /* ASG */ + +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[eax+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [eax+ebp]\n"); +#endif + } + else + { + /* 16 bit memory */ +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[esi+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [esi+ebp]\n"); +#endif + } + + fprintf(fp, "\t\t jmp [%s_OPCODETABLE+ecx*4]\n\n", CPUtype); +} + +/* + * Flag Routines + * + * Size = B,W or L + * Sreg = Register to Test + * TestReg = Need to test register (false if flags already set up) + * SetX = if C needs to be copied across to X register + * Delayed = Delays final processing to end of routine (Completed()) + * + */ + +void TestFlags(char Size,int Sreg) +{ + char* Regname=""; + + switch (Size) + { + case 66: + Regname = regnamesshort[Sreg]; + break; + + case 87: + Regname = regnamesword[Sreg]; + break; + + case 76: + Regname = regnameslong[Sreg]; + break; + } + + /* Test does not update register */ + /* so cannot generate partial stall */ + + fprintf(fp, "\t\t test %s,%s\n",Regname,Regname); +} + +void SetFlags(char Size,int Sreg,int Testreg,int SetX,int Delayed) +{ + if (Testreg) TestFlags(Size,Sreg); + + fprintf(fp, "\t\t pushfd\n"); + + if (Delayed) + { + /* Rest of code done by Completed routine */ + + if (SetX) FlagProcess = 2; + else FlagProcess = 1; + } + else + { + fprintf(fp, "\t\t pop EDX\n"); + + if (SetX) fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + } +} + +/******************/ +/* Check CPU Type */ +/******************/ + +void CheckCPUtype(int Minimum) +{ + if(CPU==2) + { + /* Only check for > 020 */ + + if(Minimum>2) + { + fprintf(fp, "\t\t mov eax,[CPUversion]\n"); + + fprintf(fp, "\t\t cmp al,%d\n",Minimum); + fprintf(fp, "\t\t jb near ILLEGAL\n\n"); + } + } + else + { + fprintf(fp, "\t\t mov eax,[CPUversion]\n"); + + if (Minimum == 1) + { + fprintf(fp, "\t\t test eax,eax\n"); + fprintf(fp, "\t\t jz near ILLEGAL\n\n"); + } + else + { + fprintf(fp, "\t\t cmp al,%d\n",Minimum); + fprintf(fp, "\t\t jb near ILLEGAL\n\n"); + } + } +} + +/************************************/ +/* Pre-increment and Post-Decrement */ +/************************************/ + +void IncrementEDI(int Size,int Rreg) +{ + switch (Size) + { + case 66: + +#ifdef A7ROUTINE + + /* Always does Byte Increment - A7 uses special routine */ + + fprintf(fp, "\t\t inc dword [%s+%s*4]\n",REG_ADD,regnameslong[Rreg]); + +#else + + /* A7 uses same routines, so inc by 2 if A7 */ + + fprintf(fp, "\t\t cmp %s,7\n",regnamesshort[Rreg]); + fprintf(fp, "\t\t cmc\n"); + fprintf(fp, "\t\t adc dword [%s+%s*4],byte 1\n",REG_ADD,regnameslong[Rreg]); + +#endif + break; + + case 87: + + fprintf(fp, "\t\t add dword [%s+%s*4],byte 2\n",REG_ADD,regnameslong[Rreg]); + break; + + case 76: + + fprintf(fp, "\t\t add dword [%s+%s*4],byte 4\n",REG_ADD,regnameslong[Rreg]); + break; + } +} + +void DecrementEDI(int Size,int Rreg) +{ + switch (Size) + { + case 66: + +#ifdef A7ROUTINE + + /* Always does Byte Increment - A7 uses special routine */ + + fprintf(fp, "\t\t dec EDI\n"); + +#else + + /* A7 uses same routines, so dec by 2 if A7 */ + + fprintf(fp, "\t\t cmp %s,7\n",regnamesshort[Rreg]); + fprintf(fp, "\t\t cmc\n"); + fprintf(fp, "\t\t sbb dword edi,byte 1\n"); + +#endif + break; + + case 87: + + fprintf(fp, "\t\t sub EDI,byte 2\n"); + break; + + case 76: + fprintf(fp, "\t\t sub EDI,byte 4\n"); + break; + } +} + +/* + * Generate an exception + * + * if Number = -1 then assume value in AL already + * code must continue running afterwards + * + */ + +void Exception(int Number, int BaseCode) +{ + if (Number > -1) + { + fprintf(fp, "\t\t sub esi,byte 2\n"); + fprintf(fp, "\t\t mov al,%d\n",Number); + } + + fprintf(fp, "\t\t call Exception\n\n"); + + if (Number > -1) + Completed(); +} + + +/********************/ +/* Address Routines */ +/********************/ + +/* + * Decode Intel flags into AX as SR register + * + * Wreg = spare register to use (must not be EAX or EDX) + */ + +void ReadCCR(char Size, int Wreg) +{ + fprintf(fp, "\t\t mov eax,edx\n"); + fprintf(fp, "\t\t mov ah,byte [%s]\n",REG_X); + + /* Partial stall so .. switch to new bit of processing */ + + fprintf(fp, "\t\t mov %s,edx\n",regnameslong[Wreg]); + fprintf(fp, "\t\t and %s,byte 1\n",regnameslong[Wreg]); + + /* Finish what we started */ + + fprintf(fp, "\t\t shr eax,4\n"); + fprintf(fp, "\t\t and eax,byte 01Ch \t\t; X, N & Z\n\n"); + + /* and complete second task */ + + fprintf(fp, "\t\t or eax,%s \t\t\t\t; C\n\n",regnameslong[Wreg]); + + /* and Finally */ + + fprintf(fp, "\t\t mov %s,edx\n",regnameslong[Wreg]); + fprintf(fp, "\t\t shr %s,10\n",regnameslong[Wreg]); + fprintf(fp, "\t\t and %s,byte 2\n",regnameslong[Wreg]); + fprintf(fp, "\t\t or eax,%s\t\t\t\t; O\n\n",regnameslong[Wreg]); + + if (Size == 'W') + { + fprintf(fp, "\t\t mov ah,byte [%s] \t; T, S & I\n\n",REG_SRH); + +#ifdef MASKCCR + fprintf(fp, "\t\t and ax,0A71Fh\t; Mask unused bits\n"); +#endif + } +} + +/* + * Convert SR into Intel flags + * + * Also handles change of mode from Supervisor to User + * + * n.b. This is also called by EffectiveAddressWrite + */ + +void WriteCCR(char Size) +{ + if (Size == 'W') + { + /* Did we change from Supervisor to User mode ? */ + + char *Label = GenerateLabel(0,1); + + fprintf(fp, "\t\t test ah,20h \t\t\t; User Mode ?\n"); + fprintf(fp, "\t\t jne short %s\n\n",Label); + + /* Mode Switch - Update A7 */ + + fprintf(fp, "\t\t mov edx,[%s]\n",REG_A7); + fprintf(fp, "\t\t mov [%s],edx\n",REG_ISP); + fprintf(fp, "\t\t mov edx,[%s]\n",REG_USP); + fprintf(fp, "\t\t mov [%s],edx\n",REG_A7); + + fprintf(fp, "%s:\n",Label); + fprintf(fp, "\t\t mov byte [%s],ah \t;T, S & I\n",REG_SRH); + + /* Mask may now allow Interrupt */ + + CheckInterrupt += 1; + } + + /* Flags */ + + fprintf(fp, "\t\t and eax,byte 1Fh\n"); + fprintf(fp, "\t\t mov edx,[IntelFlag+eax*4]\n"); + fprintf(fp, "\t\t mov [%s],dh\n",REG_X); + fprintf(fp, "\t\t and edx,0EFFh\n"); +} + + +/* + * Interface to Mame memory commands + * + * Flags = "ABCDSDB" - set to '-' if not required to preserve + * (order EAX,EBX,ECX,EDX,ESI,EDI,EBP) + * + * AReg = Register containing Address + * + * Mask 0 : No Masking + * 1 : Mask top byte, but preserve register + * 2 : Mask top byte, preserve masked register + */ + +void Memory_Read(char Size,int AReg,char *Flags,int Mask) +{ + ExternalIO = 1; + + /* Save PC */ + + fprintf(fp, "\t\t mov [%s],ESI\n",REG_PC); + + /* Check for special mask condition */ + + /* ASG - no longer need to mask addresses here */ +/* if (Mask == 2) + fprintf(fp, "\t\t and %s,0FFFFFFh\n",regnameslong[AReg]);*/ + + /* Check to see if registers need saving */ + + if ((Flags[EDX] != '-') && (SavedRegs[EDX] == '-')) + { + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + } + + if ((Flags[EBX] != '-') && (SavedRegs[EBX] == '-')) + { + fprintf(fp, "\t\t push EBX\n"); + } + + if ((Flags[ECX] != '-') && (SavedRegs[ECX] == '-')) + { + fprintf(fp, "\t\t push ECX\n"); + } + + if ((Flags[EDI] != '-') && (SavedRegs[EDI] == '-')) + { + fprintf(fp, "\t\t push EDI\n"); + } + + /* Sort Address out */ + +#ifdef FASTCALL + + fprintf(fp, "\t\t mov %s,%s\n",FASTCALL_FIRST_REG,regnameslong[AReg]); + + /* ASG - no longer need to mask addresses here */ +/* if (Mask == 1) + fprintf(fp, "\t\t and %s,0FFFFFFh\n",FASTCALL_FIRST_REG);*/ + +#else + + if (Mask == 1) + { + if ((Flags[AReg] != '-') && (SavedRegs[AReg] != '-')) + { + /* Don't trash a wanted safe register */ + + fprintf(fp, "\t\t mov EAX,%s\n",regnameslong[AReg]); + /* ASG - no longer need to mask addresses here */ +/* fprintf(fp, "\t\t and EAX,0FFFFFFh\n");*/ + fprintf(fp, "\t\t push EAX\n"); + } + else + { + /* ASG - no longer need to mask addresses here */ +/* fprintf(fp, "\t\t and %s,0FFFFFFh\n",regnameslong[AReg]);*/ + fprintf(fp, "\t\t push %s\n",regnameslong[AReg]); + } + } + else + fprintf(fp, "\t\t push %s\n",regnameslong[AReg]); + +#endif + + + + /* Call Mame memory routine */ + + /* ASG - changed these to call through the function pointers */ + +#ifdef ENCRYPTED + switch (AccessType) + { + case NORMAL : + switch (Size) + { + case 66 : + fprintf(fp, "\t\t call [_a68k_memory_intf+4]\n"); + break; + + case 87 : + fprintf(fp, "\t\t call [_a68k_memory_intf+8]\n"); + break; + + case 76 : + fprintf(fp, "\t\t call [_a68k_memory_intf+12]\n"); + break; + } + break; + + case PCREL : + + switch (Size) + { + case 66 : + fprintf(fp, "\t\t call [_a68k_memory_intf+32]\n"); + break; + + case 87 : + fprintf(fp, "\t\t call [_a68k_memory_intf+36]\n"); + break; + + case 76 : + fprintf(fp, "\t\t call [_a68k_memory_intf+40]\n"); + break; + } + break; + } + +// AccessType = NORMAL; + +#else + + switch (Size) + { + case 66 : + fprintf(fp, "\t\t call [_a68k_memory_intf+4]\n"); + break; + + case 87 : + fprintf(fp, "\t\t call [_a68k_memory_intf+8]\n"); + break; + + case 76 : + fprintf(fp, "\t\t call [_a68k_memory_intf+12]\n"); + break; + } +#endif + + /* Correct Stack */ + +#ifndef FASTCALL + fprintf(fp, "\t\t lea esp,[esp+4]\n"); +#endif + + + + /* Restore registers */ + + /* Check to see if registers need restoring */ + + if ((Flags[EDI] != '-') && (SavedRegs[EDI] == '-')) + { + fprintf(fp, "\t\t pop EDI\n"); + } + + if ((Flags[ECX] != '-') && (SavedRegs[ECX] == '-')) + { + fprintf(fp, "\t\t pop ECX\n"); + } + + if ((Flags[EBX] != '-') && (SavedRegs[EBX] == '-')) + { + fprintf(fp, "\t\t pop EBX\n"); + } + + if ((Flags[ESI] != '-') && (SavedRegs[ESI] == '-')) + { + fprintf(fp, "\t\t mov ESI,[%s]\n",REG_PC); + } + + if ((Flags[EDX] != '-') && (SavedRegs[EDX] == '-')) + { + fprintf(fp, "\t\t mov EDX,[%s]\n",REG_CCR); + } + + if ((Flags[EBP] != '-') && (SavedRegs[EBP] == '-')) + { + fprintf(fp, "\t\t mov ebp,dword [_OP_ROM]\n"); + } +} + +void Memory_Write(char Size,int AReg,int DReg,char *Flags,int Mask) +{ + ExternalIO = 1; + + /* Save PC */ + + fprintf(fp, "\t\t mov [%s],ESI\n",REG_PC); + + /* Check for special mask condition */ + + /* ASG - no longer need to mask addresses here */ +/* if (Mask == 2) + fprintf(fp, "\t\t and %s,0FFFFFFh\n",regnameslong[AReg]);*/ + + /* Check to see if registers need saving */ + + if ((Flags[EDX] != '-') && (SavedRegs[EDX] == '-')) + { + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + } + + if ((Flags[EAX] != '-') && (SavedRegs[EAX] == '-')) + { + fprintf(fp, "\t\t push EAX\n"); + } + + if ((Flags[EBX] != '-') && (SavedRegs[EBX] == '-')) + { + fprintf(fp, "\t\t push EBX\n"); + } + + if ((Flags[ECX] != '-') && (SavedRegs[ECX] == '-')) + { + fprintf(fp, "\t\t push ECX\n"); + } + + if ((Flags[EDI] != '-') && (SavedRegs[EDI] == '-')) + { + fprintf(fp, "\t\t push EDI\n"); + } + +#ifdef FASTCALL + + fprintf(fp, "\t\t mov %s,%s\n",FASTCALL_SECOND_REG,regnameslong[DReg]); + fprintf(fp, "\t\t mov %s,%s\n",FASTCALL_FIRST_REG,regnameslong[AReg]); + + /* ASG - no longer need to mask addresses here */ +/* if (Mask == 1) + fprintf(fp, "\t\t and %s,0FFFFFFh\n",FASTCALL_FIRST_REG);*/ + +#else + + fprintf(fp, "\t\t push %s\n",regnameslong[DReg]); + + if (Mask == 1) + { + if ((Flags[AReg] != '-') && (SavedRegs[AReg] != '-')) + { + /* Don't trash a wanted safe register */ + + fprintf(fp, "\t\t mov EAX,%s\n",regnameslong[AReg]); + /* ASG - no longer need to mask addresses here */ +/* fprintf(fp, "\t\t and EAX,0FFFFFFh\n");*/ + fprintf(fp, "\t\t push EAX\n"); + } + else + { + /* ASG - no longer need to mask addresses here */ +/* fprintf(fp, "\t\t and %s,0FFFFFFh\n",regnameslong[AReg]);*/ + fprintf(fp, "\t\t push %s\n",regnameslong[AReg]); + } + } + else + fprintf(fp, "\t\t push %s\n",regnameslong[AReg]); + +#endif + + + + /* Call Mame Routine */ + + /* ASG - changed these to call through the function pointers */ + switch (Size) + { + case 66 : + fprintf(fp, "\t\t call [_a68k_memory_intf+16]\n"); + break; + + case 87 : + fprintf(fp, "\t\t call [_a68k_memory_intf+20]\n"); + break; + + case 76 : + fprintf(fp, "\t\t call [_a68k_memory_intf+24]\n"); + break; + } + + /* Correct Stack */ + +#ifndef FASTCALL + fprintf(fp, "\t\t lea esp,[esp+8]\n"); +#endif + + + + /* Restore registers */ + + /* Check to see if registers need restoring */ + + if ((Flags[EDI] != '-') && (SavedRegs[EDI] == '-')) + { + fprintf(fp, "\t\t pop EDI\n"); + } + + if ((Flags[ECX] != '-') && (SavedRegs[ECX] == '-')) + { + fprintf(fp, "\t\t pop ECX\n"); + } + + if ((Flags[EBX] != '-') && (SavedRegs[EBX] == '-')) + { + fprintf(fp, "\t\t pop EBX\n"); + } + + if ((Flags[EAX] != '-') && (SavedRegs[EAX] == '-')) + { + fprintf(fp, "\t\t pop EAX\n"); + } + + if ((Flags[EDX] != '-') && (SavedRegs[EDX] == '-')) + { + fprintf(fp, "\t\t mov EDX,[%s]\n",REG_CCR); + } + + if ((Flags[ESI] != '-') && (SavedRegs[ESI] == '-')) + { + fprintf(fp, "\t\t mov ESI,[%s]\n",REG_PC); + } + + if ((Flags[EBP] != '-') && (SavedRegs[EBP] == '-')) + { + fprintf(fp, "\t\t mov ebp,dword [_OP_ROM]\n"); + } +} + + +/* + * Fetch data from Code area + * + * Dreg = Destination Register + * Extend = Sign Extend Word to Long + * + */ + +void Memory_Fetch(char Size,int Dreg,int Extend) +{ + static int loopcount=0; + + /* Always goes via OP_ROM */ + + if(CPU!=2) + { + /* 16 Bit version */ + + if ((Extend == TRUE) & (Size == 'W')) + fprintf(fp, "\t\t movsx %s,word [esi+ebp]\n",regnameslong[Dreg]); + else if (Size == 'W') + fprintf(fp, "\t\t movzx %s,word [esi+ebp]\n",regnameslong[Dreg]); + else + fprintf(fp, "\t\t mov %s,dword [esi+ebp]\n",regnameslong[Dreg]); + + if (Size == 'L') + fprintf(fp, "\t\t rol %s,16\n",regnameslong[Dreg]); + } + else + { + /* 32 Bit version */ + + if (Size == 'W') + { + fprintf(fp, "\t\t mov %s,esi\n",regnameslong[Dreg]); + fprintf(fp, "\t\t xor %s,byte 2\n",regnameslong[Dreg]); + + if (Extend == TRUE) + fprintf(fp, "\t\t movsx %s,word [%s+ebp]\n",regnameslong[Dreg],regnameslong[Dreg]); + else + fprintf(fp, "\t\t movzx %s,word [%s+ebp]\n",regnameslong[Dreg],regnameslong[Dreg]); + } + else + { + // if address is exact multiple of 4, long read will work + // otherwise we need to get words address-2 and address+4 + + // Always read long + fprintf(fp, "\t\t test esi,2\n"); +#if (!ppro) + fprintf(fp, "\t\t mov %s,dword [esi+ebp]\n",regnameslong[Dreg]); + + // OK ? + fprintf(fp, "\t\t jz short FL%3.3d\n",loopcount+1); + + // no, so get high word + fprintf(fp, "\t\t mov %s,dword [esi+ebp-4]\n",regnameslong[Dreg]); + // and get low word + fprintf(fp, "\t\t mov %s,word [esi+ebp+4]\n",regnamesword[Dreg]); + + fprintf(fp, "FL%3.3d:\n",++loopcount); +#else + fprintf(fp, "\t\t cmovnz %s,dword [esi+ebp-4]\n",regnameslong[Dreg]); + fprintf(fp, "\t\t cmovz %s,dword [esi+ebp]\n",regnameslong[Dreg]); + fprintf(fp, "\t\t cmovnz %s,word [esi+ebp+4]\n",regnamesword[Dreg]); +#endif + } + } +} + +/**********************/ +/* Push PC onto Stack */ +/**********************/ + +void PushPC(int Wreg,int Wreg2,char *Flags, int Mask) +{ + + /* Wreg2 is only used when high byte is kept */ + /* If it is EBP then the register is restored */ + + fprintf(fp, "\t\t mov %s,[%s]\t ; Push onto Stack\n",regnameslong[Wreg],REG_A7); + fprintf(fp, "\t\t sub %s,byte 4\n",regnameslong[Wreg]); + fprintf(fp, "\t\t mov [%s],%s\n",REG_A7,regnameslong[Wreg]); + +#ifndef KEEPHIGHPC + + Memory_Write('L',Wreg,ESI,Flags,Mask); + +#else + + fprintf(fp, "\t\t mov %s,[FullPC]\n",regnameslong[Wreg2]); + fprintf(fp, "\t\t and %s,0xff000000\n",regnameslong[Wreg2]); + fprintf(fp, "\t\t or %s,ESI\n",regnameslong[Wreg2]); + + Memory_Write('L',Wreg,Wreg2,Flags,Mask); + + if (Wreg2 == EBP) + { + fprintf(fp, "\t\t mov ebp,dword [_OP_ROM]\n"); + } + +#endif +} + +void ExtensionDecode(int SaveEDX) +{ + char *Label = GenerateLabel(0,1); + + if (SaveEDX) + fprintf(fp, "\t\t push edx\n"); + + Memory_Fetch('W',EAX,FALSE); + fprintf(fp, "\t\t add esi,byte 2\n"); + + if(CPU!=2) + { + /* 68000 Extension */ + + fprintf(fp, "\t\t mov edx,eax\n"); + fprintf(fp, "\t\t shr eax,12\n"); + fprintf(fp, "\t\t test edx,0x0800\n"); + fprintf(fp, "\t\t mov eax,[%s+eax*4]\n",REG_DAT); + fprintf(fp, "\t\t jnz short %s\n",Label); + fprintf(fp, "\t\t cwde\n"); + fprintf(fp, "%s:\n",Label); + fprintf(fp, "\t\t lea edi,[edi+eax]\n"); + fprintf(fp, "\t\t movsx edx,dl\n"); + fprintf(fp, "\t\t lea edi,[edi+edx]\n"); + } + else + { + /* 68020 Extension */ + + // eax holds scaled index + + // might be faster just to push all regs + fprintf(fp, "\t\t push ebx\n"); + fprintf(fp, "\t\t push ecx\n"); + + // copies for later use + fprintf(fp, "\t\t mov ecx,eax\n"); + fprintf(fp, "\t\t mov edx,eax\n"); + + // check E bit to see if displacement or full format + fprintf(fp, "\t\t test edx,0x0100\n"); + fprintf(fp, "\t\t jz short %s_a\n",Label); + // full mode so check IS (index supress) + fprintf(fp, "\t\t test edx,0x0040\n"); + fprintf(fp, "\t\t jz short %s_b\n",Label); + // set index to 0, it's not added + ClearRegister(EAX); + fprintf(fp, "\t\t jmp short %s_d\n",Label); // near + + // add displacement + fprintf(fp, "%s_a:\n",Label); + fprintf(fp, "\t\t movsx eax,al\n"); + fprintf(fp, "\t\t lea edi,[edi+eax]\n"); + + fprintf(fp, "%s_b:\n",Label); + // calc index always scale (68k will scale by 1) + fprintf(fp, "\t\t mov eax,edx\n"); + fprintf(fp, "\t\t shr eax,12\n"); + fprintf(fp, "\t\t test edx,0x0800\n"); + fprintf(fp, "\t\t mov eax,[%s+eax*4]\n",REG_DAT); + fprintf(fp, "\t\t jnz short %s_c\n",Label); + fprintf(fp, "\t\t cwde\n"); + + fprintf(fp, "%s_c:\n",Label); + fprintf(fp, "\t\t shr ecx,byte 9\n"); + fprintf(fp, "\t\t and ecx,byte 3\n"); + fprintf(fp, "\t\t shl eax,cl\n"); + + // if brief mode we can add index and exit + fprintf(fp, "\t\t test edx,0x0100\n"); + fprintf(fp, "\t\t jz near %s_i2\n",Label); + + fprintf(fp, "%s_d:\n",Label); + // check BS (base supress) + // if BS is 1 then set edi to 0 + fprintf(fp, "\t\t test edx,0x0080\n"); + fprintf(fp, "\t\t jz short %s_4a\n",Label); + ClearRegister(EDI); + // if null displacement skip over + fprintf(fp, "%s_4a:\n",Label); + fprintf(fp, "\t\t test edx,0x0020\n"); + fprintf(fp, "\t\t jz short %s_f\n",Label); + + // **** calc base displacement **** + // is it long + fprintf(fp, "\t\t test edx,0x0010\n"); + fprintf(fp, "\t\t jz short %s_e\n",Label); + // fetch long base + Memory_Fetch('L',EBX,FALSE); + fprintf(fp, "\t\t lea edi,[edi+ebx]\n"); + fprintf(fp, "\t\t add esi,byte 4\n"); + fprintf(fp, "\t\t jmp short %s_f\n",Label); + + // fetch word base + fprintf(fp, "%s_e:\n",Label); + Memory_Fetch('W',EBX,TRUE); + fprintf(fp, "\t\t lea edi,[edi+ebx]\n"); + fprintf(fp, "\t\t add esi,byte 2\n"); + + // **** indirect? **** + fprintf(fp, "%s_f:\n",Label); + fprintf(fp, "\t\t test edx,0x0003\n"); + fprintf(fp, "\t\t jz near %s_7a\n",Label); + // pre or post indirect + fprintf(fp, "\t\t test edx,0x0004\n"); + fprintf(fp, "\t\t jnz short %s_g\n",Label); + // do pre + fprintf(fp, "\t\t lea edi,[edi+eax]\n"); + Memory_Read('L',EDI,"ABCDSDB",2); + fprintf(fp, "\t\t mov edi,eax\n"); + fprintf(fp, "\t\t jmp short %s_h\n",Label); + + // do post + fprintf(fp, "%s_g:\n",Label); + fprintf(fp, "\t\t push eax\n"); + Memory_Read('L',EDI,"-B-DS-B",2); + fprintf(fp, "\t\t pop edi\n"); + + fprintf(fp, "%s_7a:\n",Label); + fprintf(fp, "\t\t lea edi,[edi+eax]\n"); + + // **** outer displacement **** + // if null displacement skip over + fprintf(fp, "%s_h:\n",Label); + fprintf(fp, "\t\t test edx,0x0002\n"); + fprintf(fp, "\t\t jz short %s_j\n",Label); + // word or long? + fprintf(fp, "\t\t test edx,0x0001\n"); + fprintf(fp, "\t\t jz short %s_i\n",Label); + // fetch long + Memory_Fetch('L',EAX,FALSE); + fprintf(fp, "\t\t add esi,byte 4\n"); + fprintf(fp, "\t\t jmp short %s_i2\n",Label); + // fetch word + fprintf(fp, "%s_i:\n",Label); + Memory_Fetch('W',EAX,TRUE); + fprintf(fp, "\t\t add esi,byte 2\n"); + fprintf(fp, "%s_i2:\n",Label); + fprintf(fp, "\t\t lea edi,[edi+eax]\n"); + + // **** exit **** + fprintf(fp, "%s_j:\n",Label); + fprintf(fp, "\t\t pop ecx\n"); + fprintf(fp, "\t\t pop ebx\n"); + } + + if (SaveEDX) + fprintf(fp, "\t\t pop edx\n"); +} + +/* Calculate Effective Address - Return address in EDI + * + * mode = Effective Address from Instruction + * Size = Byte,Word or Long + * Rreg = Register with Register Number in + * + * Only for modes 2 - 10 (5-10 clobber EAX) + */ + +void EffectiveAddressCalculate(int mode,char Size,int Rreg,int SaveEDX) +{ + /* timing */ + + if ((TimingCycles > 0) && (AddEACycles!=0)) + { + switch (mode) + { + case 2: /* (An) */ + case 3: /* (An)+ */ + case 11: /* #x,SR,CCR */ + case 19: /* (A7)+ */ + TimingCycles += 4 ; + break ; + + case 4: /* -(An) */ + case 20: /* -(A7) */ + TimingCycles += (CPU==2) ? 5 : 6 ; + break ; + + case 5: /* x(An) */ + case 9: /* x(PC) */ + TimingCycles += (CPU==2) ? 5 : 8 ; + break ; + + case 7: /* x.w */ + TimingCycles += (CPU==2) ? 4 : 8 ; + break ; + + case 6: /* x(An,xr.s) */ + case 10: /* x(PC,xr.s) */ + TimingCycles += (CPU==2) ? 7 : 10 ; + break ; + + case 8: /* x.l */ + TimingCycles += (CPU==2) ? 4 : 12 ; + break ; + } + + /* long w/r adds 4 cycles */ + + if ((mode>1) && (Size == 'L') && (CPU != 2)) + TimingCycles += 4 ; + } + + AccessType = NORMAL; + + switch (mode) + { + + case 2: + fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]); + break; + + case 3: + fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]); + IncrementEDI(Size,Rreg); + break; + + case 4: + fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]); + DecrementEDI(Size,Rreg); + fprintf(fp, "\t\t mov [%s+%s*4],EDI\n",REG_ADD,regnameslong[Rreg]); + break; + + case 5: + Memory_Fetch('W',EAX,TRUE); + fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]); + fprintf(fp, "\t\t add esi,byte 2\n"); + fprintf(fp, "\t\t add edi,eax\n"); + break; + + case 6: + + /* Get Address register Value */ + + fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]); + + /* Add Extension Details */ + + ExtensionDecode(SaveEDX); + break; + + case 7: + + /* Get Word */ + + Memory_Fetch('W',EDI,TRUE); +// fprintf(fp, "\t\t movsx edi,di\n"); + fprintf(fp, "\t\t add esi,byte 2\n"); + break; + + case 8: + + /* Get Long */ + + Memory_Fetch('L',EDI,FALSE); + fprintf(fp, "\t\t add esi,byte 4\n"); + break; + + case 9: + + AccessType = PCREL; + + Memory_Fetch('W',EAX,TRUE); +// fprintf(fp, "\t\t movsx eax,ax\n"); + fprintf(fp, "\t\t mov EDI,ESI ; Get PC\n"); + fprintf(fp, "\t\t add esi,byte 2\n"); + fprintf(fp, "\t\t add edi,eax ; Add Offset to PC\n"); + break; + + case 10: + + AccessType = PCREL; + + /* Get PC */ + + fprintf(fp, "\t\t mov edi,esi ; Get PC\n"); + + /* Add Extension Details */ + + ExtensionDecode(SaveEDX); + + break; + + case 19: + + /* (A7)+ */ + + fprintf(fp, "\t\t mov edi,[%s] ; Get A7\n",REG_A7); + fprintf(fp, "\t\t add dword [%s],byte 2\n",REG_A7); + break; + + case 20: + + /* -(A7) */ + + fprintf(fp, "\t\t mov edi,[%s] ; Get A7\n",REG_A7); + fprintf(fp, "\t\t sub edi,byte 2\n"); + fprintf(fp, "\t\t mov [%s],edi\n",REG_A7); + break; + + } +} + +/* Read from Effective Address + * + * mode = Effective Address from Instruction + * Size = Byte,Word or Long + * Rreg = Register with Register Number in + * Flag = Registers to preserve (EDX is handled by SaveEDX) + * + * Return + * Dreg = Register to return result in (EAX is usually most efficient) + * (modes 5 to 10) EDI = Address of data read (masked with FFFFFF) + */ + +void EffectiveAddressRead(int mode,char Size,int Rreg,int Dreg,const char *flags,int SaveEDX) +{ + char* Regname=""; + int MaskMode; + char Flags[8]; + + AccessType = NORMAL; + + strcpy(Flags,flags); + + /* Which Masking to Use */ + + if (Flags[5] != '-') + MaskMode = 2; + else + MaskMode = 1; + + if (SaveEDX) + Flags[3] = 'D'; + else + Flags[3] = '-'; + + switch (Size) + { + case 66: + Regname = regnamesshort[Dreg]; + break; + + case 87: + Regname = regnamesword[Dreg]; + break; + + case 76: + Regname = regnameslong[Dreg]; + break; + } + + switch (mode & 15) + { + + case 0: + + /* Read 32 bits - No prefix */ + + fprintf(fp, "\t\t mov %s,[%s+%s*4]\n",regnameslong[Dreg],REG_DAT,regnameslong[Rreg]); + break; + + case 1: + + /* Read 32 bits - No prefix */ + + fprintf(fp, "\t\t mov %s,[%s+%s*4]\n",regnameslong[Dreg],REG_ADD,regnameslong[Rreg]); + break; + + case 2: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 3: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 4: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + + case 5: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 6: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 7: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 8: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 9: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 10: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 11: + + /* Immediate - for SR or CCR see ReadCCR() */ + + if (Size == 'L') + { + Memory_Fetch('L',Dreg,FALSE); + fprintf(fp, "\t\t add esi,byte 4\n"); + } + else + { + Memory_Fetch('W',Dreg,FALSE); + fprintf(fp, "\t\t add esi,byte 2\n"); + }; + break; + } +} + +/* + * EA = Effective Address from Instruction + * Size = Byte,Word or Long + * Rreg = Register with Register Number in + * + * Writes from EAX + */ + +void EffectiveAddressWrite(int mode,char Size,int Rreg,int CalcAddress,const char *flags,int SaveEDX) +{ + int MaskMode; + char* Regname=""; + char Flags[8]; + + + strcpy(Flags,flags); + + /* Which Masking to Use ? */ + + if (CalcAddress) + { + if (Flags[5] != '-') + MaskMode = 2; + else + MaskMode = 1; + } + else + MaskMode = 0; + + if (SaveEDX) + Flags[3] = 'D'; + else + Flags[3] = '-'; + + switch (Size) + { + case 66: + Regname = regnamesshort[0]; + break; + + case 87: + Regname = regnamesword[0]; + break; + + case 76: + Regname = regnameslong[0]; + break; + } + + switch (mode & 15) + { + + case 0: + fprintf(fp, "\t\t mov [%s+%s*4],%s\n",REG_DAT,regnameslong[Rreg],Regname); + break; + + case 1: + if (Size == 66) + { + /* Not Allowed */ + + fprintf(fp, "DUFF CODE!\n"); + } + else + { + if (Size == 87) + { + fprintf(fp, "\t\t cwde\n"); + } + + fprintf(fp, "\t\t mov [%s+%s*4],%s\n",REG_ADD,regnameslong[Rreg],regnameslong[0]); + } + break; + + case 2: + if (CalcAddress) EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 3: + if (CalcAddress) EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 4: + if (CalcAddress) EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 5: + if (CalcAddress) + { + fprintf(fp, "\t\t push EAX\n"); + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + fprintf(fp, "\t\t pop EAX\n"); + } + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 6: + if (CalcAddress) + { + fprintf(fp, "\t\t push EAX\n"); + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + fprintf(fp, "\t\t pop EAX\n"); + } + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 7: + if (CalcAddress) + { + fprintf(fp, "\t\t push EAX\n"); + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + fprintf(fp, "\t\t pop EAX\n"); + } + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 8: + if (CalcAddress) + { + fprintf(fp, "\t\t push EAX\n"); + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + fprintf(fp, "\t\t pop EAX\n"); + } + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 9: + if (CalcAddress) + { + fprintf(fp, "\t\t push EAX\n"); + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + fprintf(fp, "\t\t pop EAX\n"); + } + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 10: + if (CalcAddress) + { + fprintf(fp, "\t\t push EAX\n"); + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + fprintf(fp, "\t\t pop EAX\n"); + } + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 11: + + /* SR, CCR - Chain to correct routine */ + + WriteCCR(Size); + } +} + +/* Condition Decode Routines */ + +/* + * mode = condition to check for + * + * Returns LABEL that is jumped to if condition is Condition + * + * Some conditions clobber AH + */ + +char *ConditionDecode(int mode, int Condition) +{ + char *Label = GenerateLabel(0,1); + + switch (mode) + { + + case 0: /* A - Always */ + if (Condition) + { + fprintf(fp, "\t\t jmp %s ;dave removed near\n",Label); + } + break; + + case 1: /* F - Never */ + if (!Condition) + { + fprintf(fp, "\t\t jmp near %s\n",Label); + } + break; + + case 2: /* Hi */ + fprintf(fp, "\t\t mov ah,dl\n"); + fprintf(fp, "\t\t sahf\n"); + + if (Condition) + { + fprintf(fp, "\t\t ja near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jbe near %s\n",Label); + } + break; + + case 3: /* Ls */ + fprintf(fp, "\t\t mov ah,dl\n"); + fprintf(fp, "\t\t sahf\n"); + + if (Condition) + { + fprintf(fp, "\t\t jbe near %s\n",Label); + } + else + { + fprintf(fp, "\t\t ja near %s\n",Label); + } + break; + + case 4: /* CC */ + fprintf(fp, "\t\t test dl,1H\t\t;check carry\n"); + + if (Condition) + { + fprintf(fp, "\t\t jz near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jnz near %s\n",Label); + } + break; + + case 5: /* CS */ + fprintf(fp, "\t\t test dl,1H\t\t;check carry\n"); + if (Condition) + { + fprintf(fp, "\t\t jnz near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jz near %s\n",Label); + } + break; + + case 6: /* NE */ + fprintf(fp, "\t\t test dl,40H\t\t;Check zero\n"); + if (Condition) + { + fprintf(fp, "\t\t jz near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jnz near %s\n",Label); + } + break; + + case 7: /* EQ */ + fprintf(fp, "\t\t test dl,40H\t\t;Check zero\n"); + if (Condition) + { + fprintf(fp, "\t\t jnz near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jz near %s\n",Label); + } + break; + + case 8: /* VC */ + fprintf(fp, "\t\t test dh,8H\t\t;Check Overflow\n"); + if (Condition) + { + fprintf(fp, "\t\t jz near %s\n", Label); + } + else + { + fprintf(fp, "\t\t jnz near %s\n", Label); + } + break; + + case 9: /* VS */ + fprintf(fp, "\t\t test dh,8H\t\t;Check Overflow\n"); + if (Condition) + { + fprintf(fp, "\t\t jnz near %s\n", Label); + } + else + { + fprintf(fp, "\t\t jz near %s\n", Label); + } + break; + + case 10: /* PL */ + fprintf(fp,"\t\t test dl,80H\t\t;Check Sign\n"); + if (Condition) + { + fprintf(fp, "\t\t jz near %s\n", Label); + } + else + { + fprintf(fp, "\t\t jnz near %s\n", Label); + } + break; + + case 11: /* MI */ + fprintf(fp,"\t\t test dl,80H\t\t;Check Sign\n"); + if (Condition) + { + fprintf(fp, "\t\t jnz near %s\n", Label); + } + else + { + fprintf(fp, "\t\t jz near %s\n", Label); + } + break; + + case 12: /* GE */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + if (Condition) + { + fprintf(fp, "\t\t jge near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jl near %s\n",Label); + } + break; + + case 13: /* LT */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + if (Condition) + { + fprintf(fp, "\t\t jl near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jge near %s\n",Label); + } + break; + + case 14: /* GT */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + if (Condition) + { + fprintf(fp, "\t\t jg near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jle near %s\n",Label); + } + break; + + case 15: /* LE */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + if (Condition) + { + fprintf(fp, "\t\t jle near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jg near %s\n",Label); + } + break; + } + + return Label; +} + +/* + * mode = condition to check for + * SetWhat = text for assembler command (usually AL or address descriptor) + * + * Some conditions clobber AH + */ + +void ConditionCheck(int mode, char *SetWhat) +{ + switch (mode) + { + + case 0: /* A - Always */ + fprintf(fp, "\t\t mov %s,byte 0ffh\n",SetWhat); + break; + + case 1: /* F - Never */ + if (SetWhat[1] == 'L') + { + ClearRegister(EAX); + } + else + { + fprintf(fp, "\t\t mov %s,byte 0h\n",SetWhat); + } + break; + + case 2: /* Hi */ + fprintf(fp, "\t\t mov ah,dl\n"); + fprintf(fp, "\t\t sahf\n"); + fprintf(fp, "\t\t seta %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 3: /* Ls */ + fprintf(fp, "\t\t mov ah,dl\n"); + fprintf(fp, "\t\t sahf\n"); + fprintf(fp, "\t\t setbe %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 4: /* CC */ + fprintf(fp, "\t\t test dl,1\t\t;Check Carry\n"); + fprintf(fp, "\t\t setz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 5: /* CS */ + fprintf(fp, "\t\t test dl,1\t\t;Check Carry\n"); + fprintf(fp, "\t\t setnz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 6: /* NE */ + fprintf(fp, "\t\t test dl,40H\t\t;Check Zero\n"); + fprintf(fp, "\t\t setz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 7: /* EQ */ + fprintf(fp, "\t\t test dl,40H\t\t;Check Zero\n"); + fprintf(fp, "\t\t setnz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 8: /* VC */ + fprintf(fp, "\t\t test dh,8H\t\t;Check Overflow\n"); + fprintf(fp, "\t\t setz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 9: /* VS */ + fprintf(fp, "\t\t test dh,8H\t\t;Check Overflow\n"); + fprintf(fp, "\t\t setnz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 10: /* PL */ + fprintf(fp, "\t\t test dl,80H\t\t;Check Sign\n"); + fprintf(fp, "\t\t setz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 11: /* MI */ + fprintf(fp, "\t\t test dl,80H\t\t;Check Sign\n"); + fprintf(fp, "\t\t setnz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 12: /* GE */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + fprintf(fp, "\t\t setge %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 13: /* LT */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + fprintf(fp, "\t\t setl %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 14: /* GT */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + fprintf(fp, "\t\t setg %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 15: /* LE */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + fprintf(fp, "\t\t setle %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + } +} + + +/**********************************************************************/ +/* Instructions - Each routine generates a range of instruction codes */ +/**********************************************************************/ + +/* + * Immediate Commands + * + * ORI 00xx + * ANDI 02xx + * SUBI 04xx + * ADDI 06xx + * EORI 0axx + * CMPI 0cxx + * + */ + +void dump_imm( int type, int leng, int mode, int sreg ) +{ + int Opcode,BaseCode ; + char Size=' ' ; + char * RegnameEBX="" ; + char * Regname="" ; + char * OpcodeName[16] = {"or ", "and", "sub", "add",0,"xor","cmp",0} ; + int allow[] = {1,0,1,1, 1,1,1,1, 1,0,0,0, 0,0,0,0, 0,0,0,1, 1} ; + + Opcode = (type << 9) | ( leng << 6 ) | ( mode << 3 ) | sreg; + + BaseCode = Opcode & 0xfff8; + + if (mode == 7) BaseCode |= sreg ; + +#ifdef A7ROUTINE + if ((leng == 0) && (sreg == 7) && (mode > 2) && (mode < 5)) + { + BaseCode |= sreg ; + } +#endif + + if (type != 4) /* Not Valid (for this routine) */ + { + int Dest = EAtoAMN(Opcode, FALSE); + int SetX; + + /* ADDI & SUBI also set X flag */ + + SetX = ((type == 2) || (type == 3)); + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameEBX = regnamesshort[EBX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameEBX = regnamesword[EBX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameEBX = regnameslong[EBX]; + break; + } + + if (allow[Dest]) + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + /* Save Previous PC if Memory Access */ + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode < 2) + { + if (Size != 'L') + TimingCycles += (CPU==2) ? 4 : 8; + else + { + TimingCycles += (CPU==2) ? 8 : 14; + if ((type != 1) && (type!=6)) + TimingCycles += 2 ; + } + } + else + { + if (type != 6) + { + if (Size != 'L') + TimingCycles += (CPU==2) ? 4 : 12 ; + else + TimingCycles += (CPU==2) ? 4 : 20 ; + } + else + { + if (Size != 'L') + TimingCycles += (CPU==2) ? 4 : 8 ; + else + TimingCycles += (CPU==2) ? 4 : 12 ; + } + } + + fprintf(fp, "\t\t and ecx,byte 7\n"); + + /* Immediate Mode Data */ + EffectiveAddressRead(11,Size,EBX,EBX,"--C-S-B",FALSE); + + /* Source Data */ + EffectiveAddressRead(Dest,Size,ECX,EAX,"-BC-SDB",FALSE); + + /* The actual work */ + fprintf(fp, "\t\t %s %s,%s\n", OpcodeName[type], Regname, RegnameEBX ); + + SetFlags(Size,EAX,FALSE,SetX,TRUE); + + if (type != 6) /* CMP no update */ + EffectiveAddressWrite(Dest,Size,ECX,EAX,"---DS-B",FALSE); + + Completed(); + } + } + else + { + /* Logicals are allowed to alter SR/CCR */ + + if ((!SetX) && (Dest == 11) && (Size != 'L') && (type != 6)) + { + Align(); + + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + TimingCycles += 20 ; + + if (Size=='W') + { + /* If SR then must be in Supervisor Mode */ + + char *Label = GenerateLabel(0,1); + + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t jne near %s\n\n",Label); + + /* User Mode - Exception */ + + Exception(8,BaseCode); + + fprintf(fp, "%s:\n",Label); + } + + /* Immediate Mode Data */ + EffectiveAddressRead(11,Size,EBX,EBX,"---DS-B",TRUE); + + ReadCCR(Size,ECX); + + fprintf(fp, "\t\t %s %s,%s\n", OpcodeName[type], Regname, RegnameEBX ); + + WriteCCR(Size); + + Completed(); + } + else + { + + /* Illegal Opcode */ + + OpcodeArray[BaseCode] = -1; + BaseCode = -1; + } + } + } + else + { + BaseCode = -2; + } + + OpcodeArray[Opcode] = BaseCode; +} + +void immediate(void) +{ + int type, size, mode, sreg ; + + for (type = 0 ; type < 0x7; type++) + for (size = 0 ; size < 3 ; size++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dump_imm( type, size, mode, sreg ) ; +} + + +/* + * Bitwise Codes + * + */ + +void dump_bit_dynamic( int sreg, int type, int mode, int dreg ) +{ + int Opcode, BaseCode ; + char Size ; + char *EAXReg,*ECXReg, *Label ; + char allow[] = "0-2345678-------" ; + int Dest ; + + /* BTST allows x(PC) and x(PC,xr.s) - others do not */ + + if (type == 0) + { + allow[9] = '9'; + allow[10] = 'a'; + allow[11] = 'b'; // dave fix to nhl + } + + Opcode = 0x0100 | (sreg << 9) | (type<<6) | (mode<<3) | dreg ; + + BaseCode = Opcode & 0x01f8 ; + if (mode == 7) BaseCode |= dreg ; + + + // A7+, A7- + +#ifdef A7ROUTINE + if ((mode > 2) && (mode < 5)) + { + if (dreg == 7) BaseCode |= dreg; + } +#endif + + Dest = EAtoAMN(Opcode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (mode == 0) /* long*/ + { + /* Modify register memory directly */ + + Size = 'L' ; + EAXReg = REG_DAT_EBX; + ECXReg = regnameslong[ECX]; + } + else + { + Size = 'B' ; + EAXReg = regnamesshort[EAX]; + ECXReg = regnamesshort[ECX]; + } + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + /* Save Previous PC if Memory Access */ + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode<2) + { + switch (type) + { + case 0: + TimingCycles += 6 ; + break; + case 1: + case 3: + TimingCycles += 8 ; + break; + case 2: + TimingCycles += 10; + break; + } + } + else + { + if (type==0) + TimingCycles += 4; + else + TimingCycles += 8; + } + + /* Only need this sorted out if a register is involved */ + + if (Dest < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + } + + /* Get bit number and create mask in ECX */ + + fprintf(fp, "\t\t shr ecx, byte 9\n"); + fprintf(fp, "\t\t and ecx, byte 7\n"); + fprintf(fp, "\t\t mov ecx, [%s+ECX*4]\n",REG_DAT); + + if (Size == 'L') + fprintf(fp, "\t\t and ecx, byte 31\n"); + else + fprintf(fp, "\t\t and ecx, byte 7\n"); + + #ifdef QUICKZERO + fprintf(fp,"\t\t mov eax,1\n"); + #else + fprintf(fp,"\t\t xor eax,eax\n"); + fprintf(fp,"\t\t inc eax\n"); + #endif + + fprintf(fp,"\t\t shl eax,cl\n"); + fprintf(fp,"\t\t mov ecx,eax\n"); + + if (mode != 0) + EffectiveAddressRead(Dest,Size,EBX,EAX,"-BCDSDB",TRUE); + + + /* All commands copy existing bit to Zero Flag */ + + Label = GenerateLabel(0,1); + + fprintf(fp,"\t\t or edx,byte 40h\t; Set Zero Flag\n"); + fprintf(fp,"\t\t test %s,%s\n",EAXReg,ECXReg); + fprintf(fp,"\t\t jz short %s\n",Label); + fprintf(fp,"\t\t xor edx,byte 40h\t; Clear Zero Flag\n"); + fprintf(fp,"%s:\n",Label); + + /* Some then modify the data */ + + switch (type) + { + case 0: /* btst*/ + break; + + case 1: /* bchg*/ + fprintf(fp,"\t\t xor %s,%s\n",EAXReg,ECXReg); + break; + + case 2: /* bclr*/ + fprintf(fp,"\t\t not ecx\n"); + fprintf(fp,"\t\t and %s,%s\n",EAXReg,ECXReg); + break; + + case 3: /* bset*/ + fprintf(fp,"\t\t or %s,%s\n",EAXReg,ECXReg); + break; + } + + if ((mode !=0) && (type != 0)) + EffectiveAddressWrite(Dest,Size,EBX,FALSE,"---DS-B",TRUE); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void bitdynamic(void) /* dynamic non-immediate bit operations*/ +{ + int type, sreg, mode, dreg ; + + for (sreg = 0 ; sreg < 8 ; sreg++) + for (type = 0 ; type < 4 ; type++) + for (mode = 0 ; mode < 8 ;mode++) + for (dreg = 0 ; dreg < 8 ;dreg++) + dump_bit_dynamic( sreg, type, mode, dreg ) ; +} + +void dump_bit_static(int type, int mode, int dreg ) +{ + int Opcode, BaseCode ; + char Size ; + char *EAXReg,*ECXReg, *Label ; + char allow[] = "0-2345678-------" ; + int Dest ; + + /* BTST allows x(PC) and x(PC,xr.s) - others do not */ + + if (type == 0) + { + allow[9] = '9'; + allow[10] = 'a'; + } + + Opcode = 0x0800 | (type<<6) | (mode<<3) | dreg ; + BaseCode = Opcode & 0x08f8 ; + if (mode == 7) BaseCode |= dreg ; + + // A7+, A7- + +#ifdef A7ROUTINE + if ((mode > 2) && (mode < 5)) + { + if (dreg == 7) BaseCode |= dreg; + } +#endif + + Dest = EAtoAMN(Opcode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (mode == 0) /* long*/ + { + /* Modify register memory directly */ + + Size = 'L' ; + EAXReg = REG_DAT_EBX; + ECXReg = regnameslong[ECX]; + } + else + { + Size = 'B' ; + EAXReg = regnamesshort[EAX]; + ECXReg = regnamesshort[ECX]; + } + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + /* Save Previous PC if Memory Access */ + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode<2) + { + switch (type) + { + case 0: + TimingCycles += 10 ; + break ; + case 1: + case 3: + TimingCycles += 12 ; + break ; + case 2: + TimingCycles += 14 ; + break ; + } + } + else + { + if (type != 0) + TimingCycles += 12 ; + else + TimingCycles += 8 ; + } + + /* Only need this sorted out if a register is involved */ + + if (Dest < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx, byte 7\n"); + } + + /* Get bit number and create mask in ECX */ + + Memory_Fetch('W',ECX,FALSE); + fprintf(fp, "\t\t add esi,byte 2\n"); + + if (Size == 'L') + fprintf(fp, "\t\t and ecx, byte 31\n"); + else + fprintf(fp, "\t\t and ecx, byte 7\n"); + + #ifdef QUICKZERO + fprintf(fp,"\t\t mov eax,1\n"); + #else + fprintf(fp,"\t\t xor eax,eax\n"); + fprintf(fp,"\t\t inc eax\n"); + #endif + + fprintf(fp,"\t\t shl eax,cl\n"); + fprintf(fp,"\t\t mov ecx,eax\n"); + + if (mode != 0) + EffectiveAddressRead(Dest,Size,EBX,EAX,"-BCDSDB",TRUE); + + /* All commands copy existing bit to Zero Flag */ + + Label = GenerateLabel(0,1); + + fprintf(fp,"\t\t or edx,byte 40h\t; Set Zero Flag\n"); + fprintf(fp,"\t\t test %s,%s\n",EAXReg,ECXReg); + fprintf(fp,"\t\t jz short %s\n",Label); + fprintf(fp,"\t\t xor edx,byte 40h\t; Clear Zero Flag\n"); + fprintf(fp,"%s:\n",Label); + + /* Some then modify the data */ + + switch (type) + { + case 0: /* btst*/ + break; + + case 1: /* bchg*/ + fprintf(fp,"\t\t xor %s,%s\n",EAXReg,ECXReg); + break; + + case 2: /* bclr*/ + fprintf(fp,"\t\t not ecx\n"); + fprintf(fp,"\t\t and %s,%s\n",EAXReg,ECXReg); + break; + + case 3: /* bset*/ + fprintf(fp,"\t\t or %s,%s\n",EAXReg,ECXReg); + break; + } + + if ((mode !=0) && (type != 0)) + EffectiveAddressWrite(Dest,Size,EBX,FALSE,"---DS-B",TRUE); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + + +void bitstatic(void) /* static non-immediate bit operations*/ +{ + int type, mode, dreg ; + + for (type = 0 ; type < 4 ; type++) + for (mode = 0 ; mode < 8 ;mode++) + for (dreg = 0 ; dreg < 8 ;dreg++) + dump_bit_static( type, mode, dreg ) ; +} + +/* + * Move Peripheral + * + */ + +void movep(void) +{ + int sreg,dir,leng,dreg ; + int Opcode, BaseCode ; + + for (sreg = 0 ; sreg < 8 ; sreg++) + { + for (dir = 0 ; dir < 2 ; dir++) + { + for (leng = 0 ; leng < 2 ; leng++) + { + for (dreg = 0 ; dreg < 8 ; dreg++) + { + Opcode = 0x0108 | (sreg<<9) | (dir<<7) | (leng<<6) | dreg; + BaseCode = Opcode & 0x01c8 ; + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (leng == 0) /* word */ + TimingCycles += 16 ; + else + TimingCycles += 24 ; + + /* Save Flags Register (so we only do it once) */ + + fprintf(fp, "\t\t push edx\n"); + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + + /* Get Address to Read/Write in EDI */ + + EffectiveAddressCalculate(5,'L',EBX,FALSE); + + fprintf(fp, "\t\t shr ecx,byte 9\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); + + + if (dir == 0) /* from memory to register*/ + { + Memory_Read('B',EDI,"-BC-SDB",2); /* mask first call */ + fprintf(fp,"\t\t mov bh,al\n"); + fprintf(fp,"\t\t add edi,byte 2\n"); + Memory_Read('B',EDI,"-BC-SDB",0); /* not needed then */ + fprintf(fp,"\t\t mov bl,al\n"); + + if (leng == 0) /* word d(Ax) into Dx.W*/ + { + fprintf(fp,"\t\t mov [%s+ecx*4],bx\n",REG_DAT); + } + else /* long d(Ax) into Dx.L*/ + { + fprintf(fp,"\t\t add edi,byte 2\n"); + fprintf(fp,"\t\t shl ebx,16\n"); + Memory_Read('B',EDI,"-BC-SDB",0); + fprintf(fp,"\t\t mov bh,al\n"); + fprintf(fp,"\t\t add edi,byte 2\n"); + Memory_Read('B',EDI,"-BC-S-B",0); + fprintf(fp,"\t\t mov bl,al\n"); + fprintf(fp,"\t\t mov [%s+ecx*4],ebx\n",REG_DAT); + } + } + else /* Register to Memory*/ + { + fprintf(fp,"\t\t mov eax,[%s+ecx*4]\n",REG_DAT); + + /* Move bytes into Line */ + + if (leng == 1) + fprintf(fp,"\t\t rol eax,byte 8\n"); + else + fprintf(fp,"\t\t rol eax,byte 24\n"); + + Memory_Write('B',EDI,EAX,"A---SDB",2); /* Mask First */ + fprintf(fp,"\t\t add edi,byte 2\n"); + fprintf(fp,"\t\t rol eax,byte 8\n"); + + if (leng == 1) /* long*/ + { + Memory_Write('B',EDI,EAX,"A---SDB",0); + fprintf(fp,"\t\t add edi,byte 2\n"); + fprintf(fp,"\t\t rol eax,byte 8\n"); + Memory_Write('B',EDI,EAX,"A---SDB",0); + fprintf(fp,"\t\t add edi,byte 2\n"); + fprintf(fp,"\t\t rol eax,byte 8\n"); + } + Memory_Write('B',EDI,EAX,"A---S-B",0); + } + + fprintf(fp, "\t\t pop edx\n"); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } + } + } +} + +void movecodes(int allowfrom[],int allowto[],int Start,char Size) /* MJC */ +{ + int Opcode; + int Src,Dest; + int SaveEDX; + int BaseCode; + + for (Opcode=Start;Opcode> 6, TRUE); + + if ((allowfrom[(Src & 15)]) && (allowto[(Dest & 15)])) + { + /* If we are not going to calculate the flags */ + /* we need to preserve the existing ones */ + + SaveEDX = (Dest == 1); + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if (((Src >= 2) && (Src <= 10)) || ((Dest >= 2) && (Dest <=10))) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + + TimingCycles += 4 ; + + if (Src < 7) + { + if (Dest < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + + if ((Src == 0) && allowfrom[1]) + fprintf(fp, "\t\t and ebx,byte 15\n"); + else + fprintf(fp, "\t\t and ebx,byte 7\n"); + + EffectiveAddressRead(Src,Size,EBX,EAX,"--CDS-B",SaveEDX); + } + else + { + if ((Src == 0) && allowfrom[1]) + fprintf(fp, "\t\t and ecx,byte 15\n"); + else + fprintf(fp, "\t\t and ecx,byte 7\n"); + + EffectiveAddressRead(Src,Size,ECX,EAX,"---DS-B",SaveEDX); + } + } + else + { + if (Dest < 7) + EffectiveAddressRead(Src,Size,EBX,EAX,"--CDS-B",SaveEDX); + else + EffectiveAddressRead(Src,Size,EBX,EAX,"---DS-B",SaveEDX); + } + + /* No flags if Destination Ax */ + + if (!SaveEDX) + { + SetFlags(Size,EAX,TRUE,FALSE,TRUE); + } + + if (Dest < 7) + { + fprintf(fp, "\t\t shr ecx,9\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + EffectiveAddressWrite(Dest,Size,ECX,TRUE,"---DS-B",SaveEDX); + + Completed(); + } + else + { + BaseCode = -1; /* Invalid Code */ + } + } + else + { + BaseCode = OpcodeArray[BaseCode]; + } + + if (OpcodeArray[Opcode] < 0) + OpcodeArray[Opcode] = BaseCode; + } +} + +void moveinstructions(void) +{ + int allowfrom[] = {1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0}; + int allowto[] = {1,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0}; + + /* For Byte */ + + movecodes(allowfrom,allowto,0x1000,'B'); + + /* For Word & Long */ + + allowto[1] = 1; + movecodes(allowfrom,allowto,0x2000,'L'); + movecodes(allowfrom,allowto,0x3000,'W'); +} + +/* + * + * Opcodes 5### + * + * ADDQ,SUBQ,Scc and DBcc + * + */ + +void opcode5(void) +{ + /* ADDQ,SUBQ,Scc and DBcc */ + + int allowtoScc[] = {1,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0}; + int allowtoADDQ[] = {1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0}; + int Opcode,BaseCode; + char Label[32]; + char Label2[32]; + char Size=' '; + char* Regname=""; + char* RegnameECX=""; + + for (Opcode = 0x5000;Opcode < 0x6000;Opcode++) + { + if ((Opcode & 0xc0) == 0xc0) + { + /* Scc or DBcc */ + + BaseCode = Opcode & 0x5FF8; + if ((BaseCode & 0x38) == 0x38) BaseCode |= (Opcode & 7); + + /* If mode = 3 or 4 and register = A7 */ + /* then make it a separate code */ + +#ifdef A7ROUTINE + if (((Opcode & 0x3F) == 0x1F) || ((Opcode & 0x3F) == 0x27)) + { + BaseCode |= 0x07; + } +#endif + + if (OpcodeArray[BaseCode] == -2) + { + OpcodeArray[BaseCode] = BaseCode; + + if ((BaseCode & 0x38) == 0x8) + { + /* DBcc */ + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + TimingCycles += 10 ; + + + strcpy(Label,GenerateLabel(BaseCode,1)) ; + strcpy(Label2,ConditionDecode((Opcode >> 8) & 0x0F,TRUE)); + + /* False - Decrement Counter - Loop if not -1 */ + + fprintf(fp, "\t\t and ecx,byte 7\n"); + fprintf(fp, "\t\t mov ax,[%s+ecx*4]\n",REG_DAT); + fprintf(fp, "\t\t dec ax\n"); + fprintf(fp, "\t\t mov [%s+ecx*4],ax\n",REG_DAT); + fprintf(fp, "\t\t inc ax\t\t; Is it -1\n"); + fprintf(fp, "\t\t jz short %s\n",Label); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + Memory_Fetch('W',EAX,TRUE); + fprintf(fp, "\t\t add esi,eax\n"); + Completed(); + + /* True - Exit Loop */ + fprintf(fp, "%s:\n",Label); + + fprintf(fp, "%s:\n",Label2); + fprintf(fp, "\t\t add esi,byte 4\n"); + TimingCycles += 2 ; + + Completed(); + } + else + { + /* Scc */ + + int Dest = EAtoAMN(Opcode, FALSE); + + if (allowtoScc[(Dest & 15)]) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (Dest > 1) + TimingCycles += 8 ; + else + TimingCycles += 4 ; + + if (Dest < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + if (Dest > 1) + { + EffectiveAddressCalculate(Dest,'B',ECX,TRUE); + /* ASG - no longer need to mask addresses here */ +/* fprintf(fp,"\t\t and edi,0FFFFFFh\n");*/ + } + + ConditionCheck((Opcode >> 8) & 0x0F,"AL"); + + EffectiveAddressWrite(Dest,'B',ECX,FALSE,"---DS-B",TRUE); + + /* take advantage of AL being 0 for false, 0xff for true */ + /* need to add 2 cycles if register and condition is true */ + + if (Dest == 0) + { + fprintf(fp, "\t\t and eax,byte 2\n"); + fprintf(fp, "\t\t add eax,byte %d\n",TimingCycles); + fprintf(fp, "\t\t sub dword [%s],eax\n",ICOUNT); + + TimingCycles = -1; + } + Completed(); + } + else + { + OpcodeArray[BaseCode] = -1; + BaseCode = -1; + } + } + } + else + { + BaseCode = OpcodeArray[BaseCode]; + } + + OpcodeArray[Opcode] = BaseCode; + } + else + { + /* ADDQ or SUBQ */ + + BaseCode = Opcode & 0x51F8; + if ((BaseCode & 0x38) == 0x38) BaseCode |= (Opcode & 7); + + /* Special for Address Register Direct - Force LONG */ + + if ((Opcode & 0x38) == 0x8) BaseCode = ((BaseCode & 0xFF3F) | 0x80); + + + /* If mode = 3 or 4 and Size = byte and register = A7 */ + /* then make it a separate code */ + +#ifdef A7ROUTINE + if ((Opcode & 0xC0) == 0) + { + if (((Opcode & 0x3F) == 0x1F) || ((Opcode & 0x3F) == 0x27)) + { + BaseCode |= 0x07; + } + } +#endif + + if (OpcodeArray[BaseCode] == -2) + { + char *Operation; + int Dest = EAtoAMN(Opcode, FALSE); + int SaveEDX = (Dest == 1); + + if (allowtoADDQ[(Dest & 15)]) + { + switch (BaseCode & 0xC0) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + break; + + case 0x40: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + break; + + case 0x80: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + break; + } + + OpcodeArray[BaseCode] = BaseCode; + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (Dest == 0) /* write to Dx */ + { + if (Size != 'L') + TimingCycles += 4 ; + else + TimingCycles += 8 ; + } + + if (Dest == 1) + { + if ((Size == 'L') || (Opcode & 0x100)) /* if long or SUBQ */ + TimingCycles += 8 ; + else + TimingCycles += 4 ; + } + + if (Dest > 1) /* write to mem */ + { + if (Size != 'L') + TimingCycles += 8 ; + else + TimingCycles += 12 ; + } + + if (Dest < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + } + + if (Dest > 1) + { + EffectiveAddressRead(Dest,Size,EBX,EAX,"-BCDSDB",SaveEDX); + } + + /* Sub Immediate from Opcode */ + + fprintf(fp, "\t\t shr ecx,9\n"); + + Immediate8(); + + if (Opcode & 0x100) + { + /* SUBQ */ + Operation = "sub"; + } + else + { + /* ADDQ */ + Operation = "add"; + } + + /* For Data or Address register, operate directly */ + /* on the memory location. Don't load into EAX */ + + if (Dest < 2) + { + if (Dest == 0) + { + fprintf(fp, "\t\t %s [%s+ebx*4],%s\n",Operation,REG_DAT,RegnameECX); + } + else + { + fprintf(fp, "\t\t %s [%s+ebx*4],%s\n",Operation,REG_ADD,RegnameECX); + } + } + else + { + fprintf(fp, "\t\t %s %s,%s\n",Operation,Regname,RegnameECX); + } + + /* No Flags for Address Direct */ + + if (!SaveEDX) + { + /* Directly after ADD or SUB, so test not needed */ + + SetFlags(Size,EAX,FALSE,TRUE,TRUE); + } + + if (Dest > 1) + { + EffectiveAddressWrite(Dest,Size,EBX,FALSE,"---DS-B",FALSE); + } + + Completed(); + } + else + { + OpcodeArray[BaseCode] = -1; + BaseCode = -1; + } + } + else + { + BaseCode = OpcodeArray[BaseCode]; + } + + OpcodeArray[Opcode] = BaseCode; + } + } +} + +/* + * Branch Instructions + * + * BSR, Bcc + * + */ + +void branchinstructions(void) +{ + int Opcode,BaseCode; + int Counter; + char *Label; + char jmpLabel[40] ; + + for (Opcode = 0x60;Opcode < 0x70;Opcode++) + { + /* Displacement = 0 -> 16 Bit displacement */ + + BaseCode = Opcode * 0x100; + OpcodeArray[BaseCode] = BaseCode; + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 10 ; + + if (Opcode == 0x60) + { + Memory_Fetch('W',EAX,TRUE); + fprintf(fp, "\t\t add esi,eax\n"); + MemoryBanking(BaseCode); + Completed(); + } + else + { + if (Opcode != 0x61) + { + Label = ConditionDecode(Opcode & 0x0F,TRUE); + + /* Code for Failed branch */ + + fprintf(fp, "\t\t add esi,byte 2\n"); + + /* 2 less cycles for Failure */ + + TimingCycles -= 2; + Completed(); + TimingCycles += 2; + + /* Successful Branch */ + + Align(); + fprintf(fp, "%s:\n",Label); + + Memory_Fetch('W',EAX,TRUE); + fprintf(fp, "\t\t add esi,eax\n"); + MemoryBanking(BaseCode+2); + Completed(); + + } + else + { + /* BSR - Special Case */ + + TimingCycles += 8 ; + + Memory_Fetch('W',EBX,TRUE); + fprintf(fp, "\t\t add ebx,esi\n"); + + fprintf(fp, "\t\t add esi,byte 2\n"); + PushPC(ECX,EAX,"-B-DS-B",1); + + fprintf(fp, "\t\t mov esi,ebx\n"); + MemoryBanking(BaseCode+3); + Completed(); + } + } + + /* 8 Bit Displacement */ + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode+1,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 10 ; + + if (Opcode > 0x60) + { + if (Opcode != 0x61) + { + Label = ConditionDecode(Opcode & 0x0F,TRUE); + + /* Code for Failed branch */ + + TimingCycles -= 2; + Completed(); + TimingCycles += 2; + + /* Successful Branch */ + + Align(); + fprintf(fp, "%s:\n",Label); + } + else + { + /* BSR - Special Case */ + + TimingCycles += 8 ; + + PushPC(EDI,EBX,"--CDS-B",1); + } + } + + /* Common Ending */ + + fprintf(fp, "\t\t movsx eax,cl ; Sign Extend displacement\n"); + fprintf(fp, "\t\t add esi,eax\n"); + MemoryBanking(BaseCode+5); + Completed(); + + /* Fill up Opcode Array */ + + for (Counter=1;Counter<0x100;Counter++) + OpcodeArray[BaseCode+Counter] = BaseCode+1; + + if(CPU==2) + { + + /* 8 bit 0xff & 68020 instruction - 32 bit displacement */ + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode+0xff,0)); + sprintf( jmpLabel, GenerateLabel(BaseCode+0xff,1) ) ; + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 10 ; + + if (Opcode == 0x60) + { + /* bra - always branch */ + Memory_Fetch('L',EAX,FALSE); + fprintf(fp, "\t\t add esi,eax\n"); + MemoryBanking(BaseCode+6); + Completed(); + } + else + { + if (Opcode != 0x61) + { + Label = ConditionDecode(Opcode & 0x0F,TRUE); + + /* Code for Failed branch */ + fprintf(fp, "\t\t add esi,byte 4\n"); + + TimingCycles -= 2; + Completed(); + TimingCycles += 2; + + /* Successful Branch */ + Align(); + fprintf(fp, "%s:\n",Label); + + Memory_Fetch('L',EAX,FALSE); + fprintf(fp, "\t\t add esi,eax\n"); + MemoryBanking(BaseCode+8); + Completed(); + } + else + { + /* BSR - Special Case */ + + TimingCycles += 8 ; + + Memory_Fetch('L',EBX,TRUE); + fprintf(fp, "\t\t add ebx,esi\n"); + + fprintf(fp, "\t\t add esi,byte 4\n"); + PushPC(ECX,EAX,"-B-DS-B",1); + + fprintf(fp, "\t\t mov esi,ebx\n"); + MemoryBanking(BaseCode+9); + Completed(); + } + } + + OpcodeArray[BaseCode+0xff] = BaseCode+0xff; + } + } +} + +/* + * Move Quick Commands + * + * Fairly simple, as only allowed to Data Registers + * + */ + +void moveq(void) +{ + int Count; + + /* The Code */ + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(0x7000,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4 ; + + fprintf(fp, "\t\t movsx eax,cl\n"); + fprintf(fp, "\t\t shr ecx,9\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); + SetFlags('L',EAX,TRUE,FALSE,FALSE); + EffectiveAddressWrite(0,'L',ECX,TRUE,"---DS-B",FALSE); + Completed(); + + /* Set OpcodeArray (Not strictly correct, since some are illegal!) */ + + for (Count=0x7000;Count<0x8000;Count++) + { + OpcodeArray[Count] = 0x7000; + } +} + +/* + * Extended version of Add & Sub commands + * + */ + +void addx_subx(void) +{ + int Opcode, BaseCode ; + int regx,type,leng,rm,regy,mode ; + int ModeModX; + int ModeModY; + char Size=' ' ; + char * Regname="" ; + char * RegnameEBX="" ; + char * Operand=""; + char * Label; + + for (type = 0 ; type < 2 ; type ++) /* 0=subx, 1=addx */ + for (regx = 0 ; regx < 8 ; regx++) + for (leng = 0 ; leng < 3 ; leng++) + for (rm = 0 ; rm < 2 ; rm++) + for (regy = 0 ; regy < 8 ; regy++) + { + Opcode = 0x9100 | (type<<14) | (regx<<9) | (leng<<6) | (rm<<3) | regy ; + + BaseCode = Opcode & 0xd1c8 ; + + ModeModX = 0; + ModeModY = 0; + +#ifdef A7ROUTINE + if ((rm == 1) && (leng == 0)) + { + if (regx == 7) + { + BaseCode |= (regx << 9); + ModeModY = 16; + } + if (regy == 7) + { + BaseCode |= regy; + ModeModX = 16; + } + } +#endif + + if (rm == 0) + mode = 0 ; + else + mode = 4 ; + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameEBX = regnamesshort[EBX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameEBX = regnamesword[EBX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameEBX = regnameslong[EBX]; + break; + } + + if (OpcodeArray[BaseCode] == -2) + { + if (type == 0) + Operand = "sbb"; + else + Operand = "adc"; + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if (mode == 4) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + /* don't add in EA timing for ADDX,SUBX */ + + AddEACycles = 0 ; + + if (rm == 0) /* reg to reg */ + { + if (Size != 'L') + TimingCycles += 4 ; + else + TimingCycles += 8 ; + } + else + { + if (Size != 'L') + TimingCycles += 18 ; + else + TimingCycles += 30 ; + } + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx, byte 7\n"); + fprintf(fp, "\t\t shr ecx, byte 9\n"); + fprintf(fp, "\t\t and ecx, byte 7\n"); + + /* Get Source */ + + EffectiveAddressRead(mode+ModeModX,Size,EBX,EBX,"--CDS-B",FALSE); + + /* Get Destination (if needed) */ + + if (mode == 4) + EffectiveAddressRead(mode+ModeModY,Size,ECX,EAX,"-BCDSDB",FALSE); + + /* Copy the X flag into the Carry Flag */ + + CopyX(); + + /* Do the sums */ + + if (mode == 0) + fprintf(fp, "\t\t %s [%s+ecx*4],%s\n",Operand,REG_DAT,RegnameEBX); + else + fprintf(fp, "\t\t %s %s,%s\n",Operand,Regname,RegnameEBX); + + /* Preserve old Z flag */ + + fprintf(fp, "\t\t mov ebx,edx\n"); + + /* Set the Flags */ + + SetFlags(Size,EAX,FALSE,TRUE,FALSE); + + /* Handle the Z flag */ + + Label = GenerateLabel(0,1); + + fprintf(fp, "\t\t jnz short %s\n\n",Label); + + fprintf(fp, "\t\t and dl,0BFh ; Remove Z\n"); + fprintf(fp, "\t\t and bl,40h ; Mask out Old Z\n"); + fprintf(fp, "\t\t or dl,bl ; Copy across\n\n"); + fprintf(fp, "%s:\n",Label); + + /* Update the Data (if needed) */ + + if (mode == 4) + EffectiveAddressWrite(mode,Size,ECX,FALSE,"---DS-B",TRUE); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +/* + * Logicals / Simple Maths (+ and -) + * + * OR,AND,CMP,EOR,ADD and SUB + * + */ + +void dumpx( int start, int reg, int type, char * Op, int dir, int leng, int mode, int sreg ) +{ + int Opcode,BaseCode ; + char Size=' ' ; + char * RegnameECX="" ; + char * Regname="" ; + int Dest ; + int SaveEDX ; + int SaveDir; + char * allow="" ; + char * allowtypes[] = { "0-23456789ab----", "--2345678-------", + "0123456789ab----", "0-2345678-------"}; + + SaveDir = dir; + + switch (type) + { + case 0: /* or and*/ + if (dir == 0) + allow = allowtypes[0]; + else + allow = allowtypes[1]; + break ; + + case 1: /* cmp*/ + allow = allowtypes[2] ; + break ; + + case 2: /* eor*/ + allow = allowtypes[3] ; + break ; + + case 3: /* adda suba cmpa*/ + allow = allowtypes[2] ; + break ; + + case 4: /* sub add*/ + if (dir == 0) + allow = allowtypes[0] ; + else + allow = allowtypes[1] ; + break ; + } + + if ((type == 4) && (dir == 0) && (leng > 0)) + { + allow = allowtypes[2] ; /* word and long ok*/ + } + + Opcode = start | (reg << 9 ) | (dir<<8) | (leng<<6) | (mode<<3) | sreg; + + BaseCode = Opcode & 0xf1f8; + + if (mode == 7) BaseCode |= sreg ; + +#ifdef A7ROUTINE + if ((mode == 3 || mode == 4) && ( leng == 0 ) && (sreg == 7 )) + BaseCode |= sreg ; +#endif + + + + /* If Source = Data or Address register - combine into same routine */ + + if (((Opcode & 0x38) == 0x08) && (allow[1] != '-')) + { + BaseCode &= 0xfff7; + } + + Dest = EAtoAMN(Opcode, FALSE); + SaveEDX = (Dest == 1) || (type == 3); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + break; + + case 3: /* cmpa adda suba */ + if (dir == 0) + { + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + } + else + { + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + } + dir = 0 ; + break ; + } + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (dir==0) + { + if (Size != 'L') + TimingCycles += 4; + else + TimingCycles += 6; + } + else + { + if (Size != 'L') + TimingCycles += 8; + else + TimingCycles += 12; + } + + if ((mode == 0) && (dir==0) && (Size == 'L')) + TimingCycles += 2 ; + + if ((mode == 1) && (dir==0) && (Size != 'L')) + TimingCycles += 4 ; + + if (Dest < 7) /* Others do not need reg.no. */ + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + + if ((Dest == 0) & (allow[1] != '-')) + fprintf(fp, "\t\t and ebx,byte 15\n"); + else + fprintf(fp, "\t\t and ebx,byte 7\n"); + } + + fprintf(fp, "\t\t shr ecx,byte 9\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); + + EffectiveAddressRead(Dest,Size,EBX,EAX,"-BCDSDB",SaveEDX); + + if (dir == 0) + { + if (type != 3) + { + fprintf(fp, "\t\t %s [%s+ECX*4],%s\n",Op ,REG_DAT ,Regname ) ; + + if (type == 4) + SetFlags(Size,EAX,FALSE,TRUE,FALSE); + else + SetFlags(Size,EAX,FALSE,FALSE,FALSE); + } + else + { + if (Size == 'W') + fprintf(fp, "\t\t cwde\n"); + + fprintf(fp, "\t\t %s [%s+ECX*4],EAX\n",Op ,REG_ADD); + + if (Op[0] == 'c') + { + SetFlags('L',EAX,FALSE,FALSE,FALSE); + } + } + } + else + { + fprintf(fp, "\t\t %s %s,[%s+ECX*4]\n", Op, Regname ,REG_DAT ) ; + + if (type == 4) + SetFlags(Size,EAX,FALSE,TRUE,TRUE); + else + SetFlags(Size,EAX,FALSE,FALSE,TRUE); + + EffectiveAddressWrite(Dest,Size,EBX,FALSE,"---DS-B",FALSE); + } + Completed(); + } + + OpcodeArray[Opcode] = BaseCode; + } + + dir = SaveDir; +} + +void typelogicalmath(void) +{ + int dir, leng, mode, sreg ,reg ; + + for (reg = 0 ; reg < 8 ; reg++) + { + /* or */ + for (dir = 0 ; dir < 2 ; dir++) + for (leng = 0 ; leng < 3; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0x8000, reg, 0, "or ", dir, leng, mode, sreg ) ; + + /* sub */ + for (dir = 0 ; dir < 2 ; dir++) + for (leng = 0 ; leng < 3; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0x9000, reg, 4, "sub", dir, leng, mode, sreg ) ; + + /* suba */ + + for (dir = 0 ; dir < 2 ; dir++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0x9000, reg, 3, "sub", dir, 3, mode, sreg ) ; + + + /* cmp */ + for (leng = 0 ; leng < 3; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0xb000, reg, 1, "cmp", 0, leng, mode, sreg ) ; + + /* cmpa */ + + for (dir = 0 ; dir < 2 ; dir++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0xb000, reg, 3, "cmp", dir, 3, mode, sreg ) ; + + /* adda */ + + for (dir = 0 ; dir < 2 ; dir++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0xd000, reg, 3, "add", dir, 3, mode, sreg ) ; + + + /* eor */ + for (leng = 0 ; leng < 3; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0xb100, reg, 2, "xor", 1, leng, mode, sreg ) ; + + /* and */ + for (dir = 0 ; dir < 2 ; dir++) + for (leng = 0 ; leng < 3; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0xc000, reg, 0, "and", dir, leng, mode, sreg ) ; + + /* add */ + for (dir = 0 ; dir < 2 ; dir++) + for (leng = 0 ; leng < 3; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0xd000, reg, 4, "add", dir, leng, mode, sreg ) ; + } +} + +/* + * Single commands missed out by routines above + * + */ + +void mul(void) +{ + int dreg, type, mode, sreg ; + int Opcode, BaseCode ; + int Dest ; + char allow[] = "0-23456789ab-----" ; + + for (dreg = 0 ; dreg < 8 ; dreg++) + for (type = 0 ; type < 2 ; type++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xc0c0 | (dreg<<9) | (type<<8) | (mode<<3) | sreg ; + BaseCode = Opcode & 0xc1f8 ; + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 70 ; + + if (mode < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + } + + fprintf(fp, "\t\t shr ecx, byte 9\n"); + fprintf(fp, "\t\t and ecx, byte 7\n"); + + EffectiveAddressRead(Dest,'W',EBX,EAX,"ABCDSDB",FALSE); + + if (type == 0) + fprintf(fp, "\t\t mul word [%s+ECX*4]\n",REG_DAT); + else + fprintf(fp, "\t\t imul word [%s+ECX*4]\n",REG_DAT); + + fprintf(fp, "\t\t shl edx, byte 16\n"); + fprintf(fp, "\t\t mov dx,ax\n"); + fprintf(fp, "\t\t mov [%s+ECX*4],edx\n",REG_DAT); + SetFlags('L',EDX,TRUE,FALSE,FALSE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void mull(void) +{ + int mode, sreg ; + int Opcode, BaseCode ; + int Dest ; + char allow[] = "0-23456789ab-----" ; + char *Label = NULL ; + + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4c00 | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4c38 ; + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + TimingCycles += 70 ; + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s:\n",Label); + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + Memory_Fetch('W', EBX, FALSE ); // fetch the next word + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + EffectiveAddressRead(Dest,'L',ECX,EAX,"ABCDSDB",FALSE); // read from the EA + + fprintf(fp, "\t\t mov ecx,ebx\n"); // save 2nd word in ecx + fprintf(fp, "\t\t shr ebx,12\n"); // ebx = Dl register + fprintf(fp, "\t\t and ebx,7\n"); // 0-7 + + Label = GenerateLabel(BaseCode,1); + + fprintf(fp, "\t\t test ecx,0x0800\n"); // signed/unsigned? + fprintf(fp, "\t\t jz short %s\n",Label); // skip if unsigned + + fprintf(fp, "\t\t imul dword [%s+EBX*4]\n",REG_DAT); // signed 32x32->64 + fprintf(fp, "\t\t jmp short %s_1\n",Label); // skip + + fprintf(fp, "%s:\n",Label); + fprintf(fp, "\t\t mul dword [%s+EBX*4]\n",REG_DAT); // unsigned 32x32->64 + + fprintf(fp, "%s_1:\n",Label); + fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_DAT); // store Dl back + + fprintf(fp, "\t\t test ecx,0x0400\n"); // do we care? + fprintf(fp, "\t\t jz short %s_2\n",Label); // if not, skip + fprintf(fp, "\t\t and ecx,7\n"); // get Dh register + fprintf(fp, "\t\t mov [%s+ECX*4],edx\n",REG_DAT); // store upper 32 bits + SetFlags('L',EDX,TRUE,FALSE,FALSE); // set the flags + fprintf(fp, "\t\t and edx,~0x0800\n"); // clear the overflow + fprintf(fp, "\t\t jmp short %s_3\n",Label); // skip + + fprintf(fp, "%s_2:\n",Label); + fprintf(fp, "\t\t mov ebx,edx\n"); // save upper 32 in ebx + SetFlags('L',EAX,TRUE,FALSE,FALSE); // set the flags + fprintf(fp, "\t\t sar eax,31\n"); // eax = sign-extended + fprintf(fp, "\t\t test ecx,0x0800\n"); // signed/unsigned? + fprintf(fp, "\t\t jnz short %s_4\n",Label); // skip if signed + fprintf(fp, "\t\t xor eax,eax\n"); // always use 0 for unsigned + fprintf(fp, "%s_4:\n",Label); + fprintf(fp, "\t\t cmp eax,ebx\n"); // compare upper 32 against eax + fprintf(fp, "\t\t je short %s_3\n",Label); // if equal to sign extension, skip + fprintf(fp, "\t\t or edx,0x0800\n"); // set the overflow + + fprintf(fp, "%s_3:\n",Label); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void divl(void) +{ + int mode, sreg ; + int Opcode, BaseCode ; + int Dest ; + char allow[] = "0-23456789ab-----" ; + char *Label = NULL ; + + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4c40 | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4c78 ; + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + TimingCycles += 70 ; + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s:\n",Label); + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t push edx\n"); // save edx + fprintf(fp, "\t\t add esi,byte 2\n\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); // read from ea + + Memory_Fetch('W', EDX, FALSE ); // fetch 2nd word in ecx + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + EffectiveAddressRead(Dest,'L',ECX,EBX,"---DSDB",FALSE); + + fprintf(fp, "\t\t push esi\n"); // save and 0 esi + ClearRegister(ESI); + + Label = GenerateLabel(BaseCode,1); + + fprintf(fp, "\t\t test ebx,ebx\n"); // check divisor against 0 + fprintf(fp, "\t\t jz near %s_ZERO\n",Label); // handle divide-by-zero +// low part always used + fprintf(fp, "\t\t mov ecx,edx\n"); // ecx = extension word + fprintf(fp, "\t\t shr edx,12\n"); // edx = Dq register + fprintf(fp, "\t\t and edx,7\n"); // 0-7 + fprintf(fp, "\t\t mov eax,[%s+edx*4]\n",REG_DAT); // eax = Dq register value + + ClearRegister(EDX); // edx = 0 + fprintf(fp, "\t\t test ecx,0x0400\n"); // check size + fprintf(fp, "\t\t jz short %s_1\n",Label); // skip if 32-bit dividend +// high longword (64bit) + fprintf(fp, "\t\t mov edx,ecx\n"); // edx = extension word + fprintf(fp, "\t\t and edx,7\n"); // 0-7 + fprintf(fp, "\t\t mov edx,[%s+edx*4]\n",REG_DAT); // fetch upper 32-bits + + fprintf(fp, "\t\t test ecx,0x0800\n"); // signed? + fprintf(fp, "\t\t jz near %s_3\n",Label); // if not, skip to unsigned 64-bit + fprintf(fp, "\t\t jmp near %s_2\n",Label); // skip to signed 64-bit case + + fprintf(fp, "%s_1:\n",Label); // short case + ClearRegister(EDX); // clear edx + fprintf(fp, "\t\t test ecx,0x0800\n"); // signed? + fprintf(fp, "\t\t jz short %s_3\n",Label); // if not, don't convert + fprintf(fp, "\t\t cdq\n"); // sign extend into edx +// signed + fprintf(fp, "%s_2:\n",Label); // signed 32/64-bit case + fprintf(fp, "\t\t or esi,1\n"); // esi |= 1 to indicate signed + fprintf(fp, "\t\t test ebx,ebx\n"); // check divisor sign + fprintf(fp, "\t\t jge short %s_2b\n",Label); // if >= 0, don't set + fprintf(fp, "\t\t or esi,2\n"); // esi |= 2 to indicate negative divisor + fprintf(fp, "\t\t neg ebx\n"); // make positive + fprintf(fp, "%s_2b:\n",Label); + fprintf(fp, "\t\t test edx,edx\n"); // check dividend sign + fprintf(fp, "\t\t jge short %s_3\n",Label); // if >= 0, don't set + fprintf(fp, "\t\t push ebx\n"); // save ebx + fprintf(fp, "\t\t push ecx\n"); // save ecx + ClearRegister(EBX); // clear ebx + ClearRegister(ECX); // clear ecx + fprintf(fp, "\t\t sub ebx,eax\n"); // ebx = 0 - eax + fprintf(fp, "\t\t sbb ecx,edx\n"); // ecx = 0 - edx + fprintf(fp, "\t\t mov eax,ebx\n"); // eax = ebx + fprintf(fp, "\t\t mov edx,ecx\n"); // edx = ecx + fprintf(fp, "\t\t pop ecx\n"); // restore ecx + fprintf(fp, "\t\t pop ebx\n"); // restore ebx + fprintf(fp, "\t\t or esi,4\n"); // esi |= 4 to indicate negative dividend +// unsigned + fprintf(fp, "%s_3:\n",Label); // unsigned 32/64-bit case + fprintf(fp, "\t\t cmp ebx,edx\n"); // check ebx against upper 32 bits + fprintf(fp, "\t\t jbe near %s_OVERFLOW\n",Label); // generate overflow + fprintf(fp, "\t\t div ebx\n"); // do the divide + fprintf(fp, "\t\t test esi,esi\n"); // see if we need to post process + fprintf(fp, "\t\t jz short %s_4\n",Label); // if not, skip + fprintf(fp, "\t\t jpo short %s_4\n",Label); // if PO (pos*pos or neg*neg), leave the result + fprintf(fp, "\t\t neg eax\n"); // negate the result + +// store results + fprintf(fp, "%s_4:\n",Label); + fprintf(fp, "\t\t mov ebx,ecx\n"); // ebx = extension word + fprintf(fp, "\t\t and ebx,7\n"); // get Dr in ebx + fprintf(fp, "\t\t shr ecx,12\n"); // ecx = Dq + fprintf(fp, "\t\t and ecx,7\n"); // 0-7 + fprintf(fp, "\t\t mov [%s+ebx*4],edx\n",REG_DAT); // store remainder first + fprintf(fp, "\t\t mov [%s+ecx*4],eax\n",REG_DAT); // store quotient second + fprintf(fp, "\t\t pop esi\n"); // restore esi + fprintf(fp, "\t\t pop edx\n"); // restore edx + SetFlags('L',EAX,TRUE,FALSE,FALSE); // set the flags + fprintf(fp, "%s_5:\n",Label); + fprintf(fp, "\t\t and edx,~1\n"); // clear the carry + Completed(); + + fprintf(fp, "%s_ZERO:\t\t ;Do divide by zero trap\n", Label); + /* Correct cycle counter for error */ + fprintf(fp, "\t\t pop esi\n"); // restore esi + fprintf(fp, "\t\t pop edx\n"); // restore edx + fprintf(fp, "\t\t add dword [%s],byte %d\n",ICOUNT,95); + fprintf(fp,"\t\t jmp short %s_5\n",Label); + Exception(5,BaseCode); + + fprintf(fp, "%s_OVERFLOW:\n",Label); +//set overflow + fprintf(fp, "\t\t pop esi\n"); // restore esi + fprintf(fp, "\t\t pop edx\n"); // restore edx + fprintf(fp, "\t\t or edx,0x0800\n"); // set the overflow bit + fprintf(fp, "\t\t jmp near %s_5\n",Label); // done + + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void bfext(void) +{ +// just bfextu/bfexts for now + char allow[] = "0-2--56789a-----" ; + char *Label = NULL ; + int mode,dreg,sign,Opcode,BaseCode,Dest ; + for (mode=0; mode<8; mode++) + for (dreg=0; dreg<8; dreg++) + for (sign=0; sign<2; sign++) + { + Opcode = 0xe9c0 | (sign<<9) | (mode<<3) | dreg ; + BaseCode = Opcode & 0xebf8 ; + if (mode == 7) + BaseCode |= dreg ; + Dest = EAtoAMN(Opcode, FALSE); + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s:\n",Label); + Label = GenerateLabel(BaseCode,1); + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + Memory_Fetch('W', EAX, FALSE ) ; + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + EffectiveAddressRead(Dest,'L',ECX,EDX,"ABCDSDB",FALSE); // edx = dword + + fprintf(fp, "\t\t mov ecx,eax\n"); + fprintf(fp, "\t\t shr ecx,byte 6\n"); + fprintf(fp, "\t\t test eax,0x0800\n"); + fprintf(fp, "\t\t je short %s_1\n",Label); + //get offset from Dx + fprintf(fp, "\t\t and ecx,byte 7\n"); + fprintf(fp, "\t\t mov ecx,[%s+ECX*4]\n",REG_DAT); + //get offset from extension + fprintf(fp, "%s_1:\n",Label); + fprintf(fp, "\t\t and ecx,31\n"); // ecx = offset + fprintf(fp, "\t\t mov ebx,eax\n"); + fprintf(fp, "\t\t test eax,0x0020\n"); + fprintf(fp, "\t\t je short %s_2\n",Label); + //get width from Dy + fprintf(fp, "\t\t and ebx,byte 7\n"); + fprintf(fp, "\t\t mov ebx,[%s+EBX*4]\n",REG_DAT); + //get width from extension + fprintf(fp, "%s_2:\n",Label); + //fix 0=32 + fprintf(fp, "\t\t sub ebx,byte 1\n"); + fprintf(fp, "\t\t and ebx,byte 31\n"); + fprintf(fp, "\t\t add ebx,byte 1\n"); // ebx = width + fprintf(fp, "\t\t rol edx,cl\n"); + // check for N + fprintf(fp, "\t\t mov ecx,32\n"); + fprintf(fp, "\t\t sub ecx,ebx\n"); + fprintf(fp, "\t\t mov ebx,edx\n"); + SetFlags('L',EBX,TRUE,FALSE,FALSE); + if (sign) + fprintf(fp, "\t\t sar ebx,cl\n"); + else + fprintf(fp, "\t\t shr ebx,cl\n"); + fprintf(fp, "\t\t shr eax,12\n"); + fprintf(fp, "\t\t and eax,7\n"); + fprintf(fp, "\t\t mov [%s+EAX*4],ebx\n",REG_DAT); + fprintf(fp, "\t\t test ebx,ebx\n"); + fprintf(fp, "\t\t jnz short %s_3\n",Label); + //zero flag + fprintf(fp, "\t\t or edx,40h\n"); + fprintf(fp, "%s_3:\n",Label); + Completed(); + } + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * not + * clr + * neg + * negx + * + */ + +void not(void) +{ + int type,leng, mode, sreg ; + int Opcode, BaseCode ; + int Dest ; + int SaveEDX=0; + char Size=' ' ; + char * Regname="" ; + char * RegnameECX ; + char * Label; + + char allow[] = "0-2345678-------" ; + + for (type = 0 ; type < 4 ; type++) + for (leng = 0 ; leng < 3 ; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4000 | (type<<9) | (leng<<6) | (mode<<3) | sreg ; + BaseCode = Opcode & 0x46f8 ; + if (mode == 7) + { + BaseCode |= sreg ; + } + + // A7+, A7- + +#ifdef A7ROUTINE + if ((leng == 0) && (sreg == 7) && (mode > 2) && (mode < 5)) + { + BaseCode |= sreg ; + } +#endif + + Dest = EAtoAMN(Opcode, FALSE); + + if (allow[Dest&0x0f] != '-') + { + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + break; + } + + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (Size != 'L') + TimingCycles += 4; + else + TimingCycles += 6; + + if (Dest < 7) + fprintf(fp, "\t\t and ecx,byte 7\n"); + + if (type == 0) SaveEDX = TRUE; + else SaveEDX = FALSE; + + /* CLR does not need to read source (although it does on a real 68000) */ + + if (type != 1) + { + EffectiveAddressRead(Dest,Size,ECX,EAX,"A-CDS-B",SaveEDX); + } + + switch (type) + { + case 0: /* negx */ + + /* Preserve old Z flag */ + + fprintf(fp, "\t\t mov ebx,edx\n"); + + CopyX(); + fprintf(fp, "\t\t adc %s,byte 0\n", Regname ) ; + fprintf(fp, "\t\t neg %s\n", Regname ) ; + + /* Set the Flags */ + + SetFlags(Size,EAX,FALSE,TRUE,FALSE); + + /* Handle the Z flag */ + + Label = GenerateLabel(0,1); + + fprintf(fp, "\t\t jnz short %s\n\n",Label); + + fprintf(fp, "\t\t and edx,byte -65 ; Remove Z\n"); + fprintf(fp, "\t\t and ebx,byte 40h ; Mask out Old Z\n"); + fprintf(fp, "\t\t or edx,ebx ; Copy across\n\n"); + fprintf(fp, "%s:\n",Label); + + break; + + case 1: /* clr */ + ClearRegister(EAX); + EffectiveAddressWrite(Dest,Size,ECX,TRUE,"----S-B",FALSE); + fprintf(fp, "\t\t mov edx,40H\n"); + break; + + case 2: /* neg */ + fprintf(fp, "\t\t neg %s\n",Regname ) ; + SetFlags(Size,EAX,FALSE,TRUE,TRUE); + break; + + case 3: /* not */ + fprintf(fp, "\t\t xor %s,-1\n",Regname ) ; + SetFlags(Size,EAX,FALSE,FALSE,TRUE); + break; + } + + /* Update (unless CLR command) */ + + if (type != 1) + EffectiveAddressWrite(Dest,Size,ECX,FALSE,"---DS-B",TRUE); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Move to/from USP + * + */ + +void moveusp(void) +{ + int Opcode, BaseCode ; + int dir, sreg ; + char * Label; + + for (dir = 0 ; dir < 2 ; dir++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4e60 | ( dir << 3 ) | sreg ; + BaseCode = Opcode & 0x4e68 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s\n", Label ); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4; + + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t jz short OP%d_%4.4x_Trap\n",CPU,BaseCode); + + fprintf(fp, "\t\t and ecx,7\n"); + + if (dir == 0) /* reg 2 USP */ + { + fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_ADD); + fprintf(fp, "\t\t mov [%s],eax\n",REG_USP); + } + else + { + fprintf(fp, "\t\t mov eax,[%s]\n",REG_USP); + fprintf(fp, "\t\t mov [%s+ECX*4],eax\n",REG_ADD); + } + Completed(); + + fprintf(fp, "OP%d_%4.4x_Trap:\n",CPU,BaseCode); + Exception(8,BaseCode); + } + OpcodeArray[Opcode] = BaseCode ; + } +} + + +/* + * Check + * + */ + +void chk(void) +{ + int dreg,mode,sreg,size ; + int Opcode, BaseCode ; + int Dest ; + char * Label ; + + char *allow = "0-23456789ab----" ; + + for (size = 0 ; size < (CPU==2 ? 2 : 1); size++) + for (dreg = 0 ; dreg < 8; dreg++) + for (mode = 0 ; mode < 8; mode++) + for (sreg = 0 ; sreg < 8; sreg++) + { + if (size == 0) /* word */ + Opcode = 0x4180 | (dreg<<9) | (mode<<3) | sreg ; + else /* long */ + Opcode = 0x4100 | (dreg<<9) | (mode<<3) | sreg ; + BaseCode = Opcode & 0x41f8 ; + + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s:\n", Label ); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 10; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t shr ebx,byte 9\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + + if (Dest < 7) + fprintf(fp, "\t\t and ecx,byte 7\n"); + + EffectiveAddressRead(Dest,(size == 0) ? 'W' : 'L',ECX,EAX,"----S-B",FALSE); + + if (size == 0) /* word */ + { + fprintf(fp, "\t\t movsx ebx,word [%s+EBX*4]\n",REG_DAT); + fprintf(fp, "\t\t movsx eax,ax\n"); + } + else /* long */ + fprintf(fp, "\t\t mov ebx,[%s+EBX*4]\n",REG_DAT); + + fprintf(fp, "\t\t test ebx,ebx\n"); /* is word bx < 0 */ + fprintf(fp, "\t\t jl near OP%d_%4.4x_Trap_minus\n",CPU,BaseCode); + + fprintf(fp, "\t\t cmp ebx,eax\n"); + fprintf(fp, "\t\t jg near OP%d_%4.4x_Trap_over\n",CPU,BaseCode); + Completed(); + + /* N is set if data less than zero */ + + Align(); + fprintf(fp, "OP%d_%4.4x_Trap_minus:\n",CPU,BaseCode); + fprintf(fp, "\t\t or edx,0x0080\n"); /* N flag = 80H */ + fprintf(fp, "\t\t jmp short OP%d_%4.4x_Trap_Exception\n",CPU,BaseCode); + + /* N is cleared if greated than compared number */ + + Align(); + fprintf(fp, "OP%d_%4.4x_Trap_over:\n",CPU,BaseCode); + fprintf(fp, "\t\t and edx,0x007f\n"); /* N flag = 80H */ + + fprintf(fp, "OP%d_%4.4x_Trap_Exception:\n",CPU,BaseCode); + fprintf(fp, "\t\t mov al,6\n"); + Exception(-1,0x10000+BaseCode); + Completed(); + + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void chk2(void) +{ +#if 0 + int mode,sreg,size ; + int Opcode, BaseCode ; + int Dest ; + char * Label ; + + char *allow = "--2--56789a-----" ; + + for (size = 0 ; size < 2; size++) + for (mode = 0 ; mode < 8; mode++) + for (sreg = 0 ; sreg < 8; sreg++) + { + Opcode = 0x00c0 | (size<<9) | (mode<<3) | sreg; + BaseCode = Opcode & 0xfff8 ; + + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s:\n", Label ); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 10; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t shr ebx,byte 9\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + + if (Dest < 7) + fprintf(fp, "\t\t and ecx,byte 7\n"); + + EffectiveAddressRead(Dest,'W',ECX,EAX,"----S-B",FALSE); + + if (size == 0) /* word */ + { + fprintf(fp, "\t\t movsx ebx,word [%s+EBX*4]\n",REG_DAT); + fprintf(fp, "\t\t movsx eax,ax\n"); + } + else /* long */ + fprintf(fp, "\t\t mov ebx,[%s+EBX*4]\n",REG_DAT); + + fprintf(fp, "\t\t test ebx,ebx\n"); /* is word bx < 0 */ + fprintf(fp, "\t\t jl near OP%d_%4.4x_Trap_minus\n",CPU,BaseCode); + + fprintf(fp, "\t\t cmp ebx,eax\n"); + fprintf(fp, "\t\t jg near OP%d_%4.4x_Trap_over\n",CPU,BaseCode); + Completed(); + + /* N is set if data less than zero */ + + Align(); + fprintf(fp, "OP%d_%4.4x_Trap_minus:\n",CPU,BaseCode); + fprintf(fp, "\t\t or edx,0x0080\n"); /* N flag = 80H */ + fprintf(fp, "\t\t jmp short OP%d_%4.4x_Trap_Exception\n",CPU,BaseCode); + + /* N is cleared if greated than compared number */ + + Align(); + fprintf(fp, "OP%d_%4.4x_Trap_over:\n",CPU,BaseCode); + fprintf(fp, "\t\t and edx,0x007f\n"); /* N flag = 80H */ + + fprintf(fp, "OP%d_%4.4x_Trap_Exception:\n",CPU,BaseCode); + fprintf(fp, "\t\t mov al,6\n"); + Exception(-1,0x10000+BaseCode); + Completed(); + + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +#endif +} + +/* + * Load Effective Address + */ + +void LoadEffectiveAddress(void) +{ + int Opcode, BaseCode ; + int sreg,mode,dreg ; + int Dest ; + char allow[] = "--2--56789a-----" ; + + for (sreg = 0 ; sreg < 8 ; sreg++) + for (mode = 0 ; mode < 8 ; mode++) + for (dreg = 0 ; dreg < 8 ; dreg++) + { + Opcode = 0x41c0 | (sreg<<9) | (mode<<3) | dreg ; + + BaseCode = Opcode & 0x41f8 ; + + if (mode == 7) + BaseCode = BaseCode | dreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + switch (mode) + { + case 2: + TimingCycles += 4; + break; + case 5: + case 7: + case 9: + TimingCycles += 8; + break; + case 6: + case 8: + case 10: + TimingCycles += 12; + break; + } + + if (mode < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + } + + fprintf(fp, "\t\t shr ecx,byte 9\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); + + EffectiveAddressCalculate(Dest,'L',EBX,TRUE); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Negate BCD + * + */ + +void nbcd(void) +{ + int Opcode, BaseCode ; + int sreg,mode,Dest ; + char allow[] = "0-2345678-------" ; + + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4800 | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4838 ; + + if (mode == 7) + BaseCode |= sreg ; + + // A7+, A7- + +#ifdef A7ROUTINE + if ((sreg == 7) && (mode > 2) && (mode < 5)) + { + BaseCode |= sreg; + } +#endif + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode < 2) + TimingCycles += 6; + else + TimingCycles += 8; + + fprintf(fp, "\t\t and ecx, byte 7\n"); + + EffectiveAddressRead(Dest,'B',ECX,EBX,"--C-SDB",FALSE); + + ClearRegister(EAX); + CopyX(); + + fprintf(fp, "\t\t sbb al,bl\n"); + fprintf(fp, "\t\t das\n"); + + SetFlags('B',EAX,FALSE,TRUE,TRUE); + + EffectiveAddressWrite(Dest,'B',ECX,EAX,"----S-B",FALSE); + Completed(); + } + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void tas(void) +{ + int Opcode, BaseCode ; + int sreg,mode,Dest ; + char allow[] = "0-2345678-------" ; + + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4ac0 | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4af8 ; + + if (mode == 7) + BaseCode |= sreg ; + +#ifdef A7ROUTINE + if ((sreg == 7) && (mode > 2) && (mode < 5)) + { + BaseCode |= sreg ; + } +#endif + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode < 2) + TimingCycles += 4; + else + TimingCycles += 14; + + fprintf(fp, "\t\t and ecx, byte 7\n"); + + EffectiveAddressRead(Dest,'B',ECX,EAX,"--C-SDB",FALSE); + + SetFlags('B',EAX,TRUE,FALSE,TRUE); + fprintf(fp, "\t\t or al,128\n"); + + EffectiveAddressWrite(Dest,'B',ECX,EAX,"----S-B",FALSE); + Completed(); + } + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * push Effective Address + */ + +void PushEffectiveAddress(void) +{ + int Opcode, BaseCode ; + int mode,dreg ; + int Dest ; + char allow[] = "--2--56789a-----" ; + + for (mode = 0 ; mode < 8 ; mode++) + for (dreg = 0 ; dreg < 8 ; dreg++) + { + Opcode = 0x4840 | (mode<<3) | dreg ; + + BaseCode = Opcode & 0x4878 ; + + if (mode == 7) + BaseCode = BaseCode | dreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + switch (mode) + { + case 2: + TimingCycles += 12; + break; + case 5: + case 7: + case 9: + TimingCycles += 16; + break; + case 6: + case 8: + case 10: + TimingCycles += 20; + break; + } + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + EffectiveAddressCalculate(Dest,'L',ECX,TRUE); + + fprintf(fp, "\t\t mov ecx,[%s]\t ; Push onto Stack\n",REG_A7); + fprintf(fp, "\t\t sub ecx,byte 4\n"); + fprintf(fp, "\t\t mov [%s],ecx\n",REG_A7); + Memory_Write('L',ECX,EDI,"---DS-B",2); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Test + * + */ + +void tst(void) +{ + int leng, mode, sreg ; + int Opcode, BaseCode ; + int Dest ; + char Size=' ' ; + char * Regname ; + char * RegnameECX ; + + char allow[] = "0-2345678-------" ; + if (CPU==2) + allow[1] = '1'; + + for (leng = 0 ; leng < 3 ; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4a00 | (leng<<6) | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4af8 ; + if (mode == 7) + { + BaseCode |= sreg ; + } + + // A7+, A7- + +#ifdef A7ROUTINE + if ((leng == 0) && (sreg == 7) && (mode > 2) && (mode < 5)) + { + BaseCode |= sreg ; + } +#endif + + Dest = EAtoAMN(Opcode, FALSE); + + if ((allow[Dest&0x0f] != '-') || (( mode == 1 ) && (leng != 0))) + { + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + break; + } + + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4; + + if (Dest < 7) + fprintf(fp, "\t\t and ecx,byte 7\n"); + + EffectiveAddressRead(Dest,Size,ECX,EAX,"----S-B",FALSE); + + SetFlags(Size,EAX,TRUE,FALSE,FALSE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Move registers too / from memory + * + */ + +void movem_reg_ea(void) +{ + int leng,mode,sreg ; + int Opcode, BaseCode ; + int Dest ; + char Size ; + char * Label ; + + char *allow = "--2-45678-------" ; + + for (leng = 0 ; leng < 2; leng++) + for (mode = 0 ; mode < 8; mode++) + for (sreg = 0 ; sreg < 8; sreg++) + { + Opcode = 0x4880 | ( leng<<6) | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4cf8 ; + + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + + Size = "WL"[leng] ; + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == - 2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s:\n",Label ) ; + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + switch (mode) + { + case 2: + case 4: + TimingCycles += 8 ; + break; + case 5: + case 7: + TimingCycles += 12 ; + break; + case 6: + case 8: + TimingCycles += 14 ; + break; + } + + fprintf(fp, "\t\t push edx\n"); + + Memory_Fetch('W',EDX,FALSE); + fprintf(fp, "\t\t add esi,byte 2\n"); + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + if (mode == 4) + { + fprintf(fp, "\t\t push ecx\n"); + fprintf(fp, "\t\t mov edi,[%s+ECX*4]\n",REG_ADD); + } + else + EffectiveAddressCalculate(Dest,'L',ECX,TRUE); + + fprintf(fp, "\t\t mov ebx,1\n"); + + /* predecrement uses d0-d7..a0-a7 a7 first*/ + /* other modes use a7-a0..d7-d0 d0 first*/ + + if (Dest != 4) + ClearRegister(ECX); + else + fprintf(fp, "\t\t mov ecx,3Ch\n"); + + fprintf(fp, "OP%d_%4.4x_Again:\n",CPU,BaseCode); + fprintf(fp, "\t\t test edx,ebx\n"); + fprintf(fp, "\t\t je OP%d_%4.4x_Skip\n",CPU,BaseCode); + + fprintf(fp, "\t\t mov eax,[%s+ecx]\n",REG_DAT); /* load eax with current reg data */ + + if (Dest == 4) + { + if (Size == 'W') /* adjust pointer before write */ + fprintf(fp, "\t\t sub edi,byte 2\n"); + else + fprintf(fp, "\t\t sub edi,byte 4\n"); + } + + Memory_Write(Size,EDI,EAX,"-BCDSDB",1); + + if (Dest != 4) + { + if (Size == 'W') /* adjust pointer after write */ + fprintf(fp, "\t\t add edi,byte 2\n"); + else + fprintf(fp, "\t\t add edi,byte 4\n"); + } + + /* Update Cycle Count */ + + if (Size == 'W') + fprintf(fp, "\t\t sub dword [%s],byte 4\n",ICOUNT); + else + fprintf(fp, "\t\t sub dword [%s],byte 8\n",ICOUNT); + + fprintf(fp, "OP%d_%4.4x_Skip:\n",CPU,BaseCode); + + if (Dest != 4) + fprintf(fp, "\t\t add ecx,byte 4h\n"); + else + fprintf(fp, "\t\t sub ecx,byte 4h\n"); + + fprintf(fp, "\t\t add ebx,ebx\n"); /* faster than shl ebx,1 */ + fprintf(fp, "\t\t test bx,bx\n"); /* check low 16 bits */ + fprintf(fp, "\t\t jnz OP%d_%4.4x_Again\n",CPU,BaseCode); + + if (Dest == 4) + { + fprintf(fp, "\t\t pop ecx\n"); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD); + } + + fprintf(fp, "\t\t pop edx\n"); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void movem_ea_reg(void) +{ + int leng,mode,sreg ; + int Opcode, BaseCode ; + int Dest ; + char Size ; + char * Label ; + + char *allow = "--23-56789a-----" ; + + for (leng = 0 ; leng < 2; leng++) + for (mode = 0 ; mode < 8; mode++) + for (sreg = 0 ; sreg < 8; sreg++) + { + Opcode = 0x4c80 | ( leng<<6) | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4cf8 ; + + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + + Size = "WL"[leng] ; + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == - 2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + + fprintf(fp, "%s:\n",Label ) ; + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + switch (mode) + { + case 2: + case 4: + TimingCycles += 8 ; + break; + case 5: + case 7: + TimingCycles += 12 ; + break; + case 6: + case 8: + TimingCycles += 14 ; + break; + } + + fprintf(fp, "\t\t push edx\n"); /* save edx because sr is unaffected */ + + Memory_Fetch('W',EDX,FALSE); + fprintf(fp, "\t\t add esi,byte 2\n"); + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + if (mode == 3) + fprintf(fp, "\t\t push ecx\n"); /* if (An)+ then it needed later */ + + EffectiveAddressCalculate(Dest,'L',ECX,TRUE); + + fprintf(fp, "\t\t mov ebx,1\n"); /* setup register list mask */ + + /* predecrement uses d0-d7..a0-a7 a7 first*/ + /* other modes use a7-a0..d7-d0 d0 first*/ + + ClearRegister(ECX); /* always start with D0 */ + + fprintf(fp, "OP%d_%4.4x_Again:\n",CPU,BaseCode); + fprintf(fp, "\t\t test edx,ebx\n"); /* is bit set for this register? */ + fprintf(fp, "\t\t je OP%d_%4.4x_Skip\n",CPU,BaseCode); + + Memory_Read(Size,EDI,"-BCDSDB",1); + + if (Size == 'W') + fprintf(fp, "\t\t cwde\n"); /* word size must be sign extended */ + + fprintf(fp, "\t\t mov [%s+ecx],eax\n",REG_DAT); /* load current reg with eax */ + + if (Size == 'W') /* adjust pointer after write */ + fprintf(fp, "\t\t add edi,byte 2\n"); + else + fprintf(fp, "\t\t add edi,byte 4\n"); + + /* Update Cycle Count */ + + if (Size == 'W') + fprintf(fp, "\t\t sub dword [%s],byte 4\n",ICOUNT); + else + fprintf(fp, "\t\t sub dword [%s],byte 8\n",ICOUNT); + + fprintf(fp, "OP%d_%4.4x_Skip:\n",CPU,BaseCode); + fprintf(fp, "\t\t add ecx,byte 4\n"); /* adjust pointer to next reg */ + fprintf(fp, "\t\t add ebx,ebx\n"); /* Faster than shl ebx,1 */ + fprintf(fp, "\t\t test bx,bx\n"); /* check low 16 bits */ + fprintf(fp, "\t\t jnz OP%d_%4.4x_Again\n",CPU,BaseCode); + + if (mode == 3) + { + fprintf(fp, "\t\t pop ecx\n"); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD); /* reset Ax if mode = (Ax)+ */ + } + + fprintf(fp, "\t\t pop edx\n"); /* restore flags */ + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Link / Unlink + * + * Local stack space + * + */ + +void link(void) +{ + int sreg ; + int Opcode, BaseCode ; + + for (sreg = 0 ; sreg < 8; sreg++) + { + Opcode = 0x4e50 | sreg ; + BaseCode = 0x4e50 ; + + if (OpcodeArray[BaseCode] == - 2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 16; + + fprintf(fp, "\t\t sub dword [%s],byte 4\n",REG_A7); + + fprintf(fp, "\t\t and ecx, byte 7\n"); + fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_ADD); + fprintf(fp, "\t\t mov edi,[%s]\n",REG_A7); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD); + + Memory_Write('L',EDI,EAX,"---DS-B",1); + + Memory_Fetch('W',EAX,TRUE); + fprintf(fp, "\t\t add esi,byte 2\n"); + fprintf(fp, "\t\t add [%s],eax\n",REG_A7); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void unlinkasm(void) +{ + int sreg ; + int Opcode, BaseCode ; + + for (sreg = 0 ; sreg < 8; sreg++) + { + Opcode = 0x4e58 | sreg ; + BaseCode = 0x4e58 ; + + if (OpcodeArray[BaseCode] == - 2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 12; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx, byte 7\n"); + fprintf(fp, "\t\t mov edi,[%s+EBX*4]\n",REG_ADD); + + Memory_Read('L',EDI,"-B-DSDB",1); + + fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_ADD); + fprintf(fp, "\t\t add edi,byte 4\n"); + fprintf(fp, "\t\t mov dword [%s],EDI\n",REG_A7); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void trap(void) +{ + int Count; + int BaseCode = 0x4E40; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + fprintf(fp, "\t\t mov eax,ecx\n"); + fprintf(fp, "\t\t and eax,byte 15\n"); + fprintf(fp, "\t\t or eax,byte 32\n"); + Exception(-1,BaseCode); + Completed(); + } + + for (Count=0;Count<=15;Count++) + OpcodeArray[BaseCode+Count] = BaseCode; +} + +void reset(void) +{ + int BaseCode = 0x4E70; + char * Label; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + + TimingCycles += 132; + + fprintf(fp, "%s:\n", Label ); + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t jnz near OP%d_%4.4x_RESET\n",CPU,BaseCode); + Exception(8,BaseCode); + + fprintf(fp, "\nOP%d_%4.4x_RESET:\n",CPU,BaseCode); + + /* Prefetch next instruction */ + + if(CPU==2) + { + /* 32 bit memory version */ + + fprintf(fp, "\t\t xor esi,2\n"); /* ASG */ +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[esi+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [esi+ebp]\n"); +#endif + fprintf(fp, "\t\t xor esi,2\n"); /* ASG */ + } + else + { + /* 16 bit memory */ +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[esi+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [esi+ebp]\n"); +#endif + } + + fprintf(fp, "\t\t mov eax,dword [%s]\n", REG_RESET_CALLBACK); + fprintf(fp, "\t\t test eax,eax\n"); + fprintf(fp, "\t\t jz near OP%d_%4.4x_END\n",CPU,BaseCode); + + /* Callback for Reset */ + + fprintf(fp, "\t\t mov [%s],ESI,\n",REG_PC); + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + fprintf(fp, "\t\t push ECX\n"); + + fprintf(fp, "\t\t call [eax]\n"); + + fprintf(fp, "\t\t mov ESI,[%s]\n",REG_PC); + fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR); + fprintf(fp, "\t\t pop ECX\n"); + fprintf(fp, "\t\t mov ebp,dword [_OP_ROM]\n"); + + fprintf(fp, "OP%d_%4.4x_END:\n",CPU,BaseCode); + fprintf(fp, "\t\t sub dword [%s],%d\n",ICOUNT,TimingCycles); + fprintf(fp, "\t\t jmp [%s_OPCODETABLE+ecx*4]\n\n", CPUtype); + } + OpcodeArray[BaseCode] = BaseCode ; +} + +void nop(void) +{ + int BaseCode = 0x4e71 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4; + + Completed(); + OpcodeArray[BaseCode] = BaseCode ; + } +} + +void stop(void) +{ + char TrueLabel[16]; + int BaseCode = 0x4e72 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4; + + /* Must be in Supervisor Mode */ + + sprintf(TrueLabel,GenerateLabel(0,1)); + + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t je near %s\n\n",TrueLabel); + + /* Next WORD is new SR */ + + Memory_Fetch('W',EAX,FALSE); + fprintf(fp, "\t\t add esi,byte 2\n"); + + WriteCCR('W'); + + /* See if Valid interrupt waiting */ + + CheckInterrupt = 0; + + fprintf(fp, "\t\t mov eax,[%s]\n",REG_IRQ); + fprintf(fp, "\t\t and eax,byte 07H\n"); + + fprintf(fp, "\t\t cmp al,7\t\t ; Always take 7\n"); + fprintf(fp, "\t\t je near procint\n\n"); + + fprintf(fp, "\t\t mov ebx,[%s]\t\t; int mask\n",REG_SRH); + fprintf(fp, "\t\t and ebx,byte 07H\n"); + fprintf(fp, "\t\t cmp eax,ebx\n"); + fprintf(fp, "\t\t jg near procint\n\n"); + + /* No int waiting - clear count, set stop */ + + ClearRegister(ECX); + fprintf(fp, "\t\t mov [%s],ecx\n",ICOUNT); + fprintf(fp, "\t\t or byte [%s],80h\n",REG_IRQ); + Completed(); + + /* User Mode - Exception */ + + Align(); + fprintf(fp, "%s:\n",TrueLabel); + Exception(8,BaseCode); + + OpcodeArray[BaseCode] = BaseCode ; + } +} + +void ReturnFromException(void) +{ + char TrueLabel[16]; + + int BaseCode = 0x4e73; + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 20; + + /* Check in Supervisor Mode */ + + sprintf(TrueLabel,GenerateLabel(0,1)); + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t je near %s\n\n",TrueLabel); + + /* Get SR - Save in EBX */ + + fprintf(fp, "\t\t mov edi,[%s]\n",REG_A7); + fprintf(fp, "\t\t add dword [%s],byte 6\n",REG_A7); + Memory_Read('W',EDI,"-----DB",2); + fprintf(fp, "\t\t add edi,byte 2\n"); + fprintf(fp, "\t\t mov esi,eax\n"); + + /* Get PC */ + + Memory_Read('L',EDI,"----S-B",0); + fprintf(fp, "\t\t xchg esi,eax\n"); + + /* Update CCR (and A7) */ + + WriteCCR('W'); + + MemoryBanking(BaseCode); + Completed(); + + fprintf(fp, "%s:\n",TrueLabel); + Exception(8,0x10000+BaseCode); + + OpcodeArray[BaseCode] = BaseCode; +} + +void trapv(void) +{ + int BaseCode = 0x4E76; + char * Label; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s\n", Label ); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4; + + fprintf(fp, "\t\t test dh,08h\n"); + fprintf(fp, "\t\t jz near OP%d_%4.4x_Clear\n",CPU,BaseCode); + Exception(7,BaseCode); + + fprintf(fp, "OP%d_%4.4x_Clear:\n",CPU,BaseCode); + Completed(); + } + OpcodeArray[BaseCode] = BaseCode ; +} + +void illegal_opcode(void) +{ + Align(); + fprintf(fp, "ILLEGAL:\n"); + fprintf(fp, "\t\t mov [_illegal_op],ecx\n"); + fprintf(fp, "\t\t mov [_illegal_pc],esi\n"); + +#ifdef MAME_DEBUG + fprintf(fp, "\t\t jmp ecx\n"); + fprintf(fp, "\t\t pushad\n"); + fprintf(fp, "\t\t call _m68k_illegal_opcode\n"); + fprintf(fp, "\t\t popad\n"); +#endif + + Exception(4,0xFFFE); +} + +/* + * Return from subroutine + * restoring flags as well + * + */ + +void ReturnandRestore(void) +{ + int BaseCode = 0x4e77; + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 20; + + /* Get SR into ESI */ + + fprintf(fp, "\t\t mov edi,[%s]\n",REG_A7); + fprintf(fp, "\t\t add dword [%s],byte 6\n",REG_A7); + + Memory_Read('W',EDI,"-----DB",2); + fprintf(fp, "\t\t add edi,byte 2\n"); + fprintf(fp, "\t\t mov esi,eax\n"); + + /* Get PC */ + + Memory_Read('L',EDI,"----SDB",0); + fprintf(fp, "\t\t xchg esi,eax\n"); + + /* Update flags */ + + WriteCCR('B'); + + MemoryBanking(BaseCode); + Completed(); + + OpcodeArray[BaseCode] = BaseCode; +} + +/* + * Return from Subroutine + * + */ + +void rts(void) +{ + int BaseCode = 0x4e75 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + + TimingCycles += 16; + + OpcodeArray[BaseCode] = BaseCode ; + + fprintf(fp, "\t\t mov eax,[%s]\n",REG_A7); + fprintf(fp, "\t\t add dword [%s],byte 4\n",REG_A7); + Memory_Read('L',EAX,"---D--B",1); + fprintf(fp, "\t\t mov esi,eax\n"); + MemoryBanking(BaseCode); + Completed(); + } +} + +void jmp_jsr(void) +{ + int Opcode, BaseCode ; + int dreg,mode,type ; + int Dest ; + char allow[] = "--2--56789a-----" ; + + for (type = 0 ; type < 2 ; type++) + for (mode = 0 ; mode < 8 ; mode++) + for (dreg = 0 ; dreg < 8 ; dreg++) + { + Opcode = 0x4e80 | (type<<6) | (mode<<3) | dreg ; + BaseCode = Opcode & 0x4ef8 ; + if (mode == 7) + BaseCode = BaseCode | dreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + switch (mode) + { + case 2: + TimingCycles += 8; + break; + case 5: + case 7: + case 9: + TimingCycles += 10; + break; + case 8: + TimingCycles += 12; + break; + case 6: + case 10: + TimingCycles += 14; + break; + } + + if (type == 0) /* jsr takes 8 more than jmp */ + TimingCycles += 8; + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + EffectiveAddressCalculate(Dest,'L',ECX,TRUE); + + /* jsr needs to push PC onto stack */ + + if (type == 0) + { + PushPC(EBX,EAX,"---D-DB",1); + } + + fprintf(fp, "\t\t mov esi,edi\n"); + MemoryBanking(BaseCode); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void cmpm(void) +{ + int Opcode, BaseCode ; + int regx,leng,regy ; + int ModeModX, ModeModY; + char Size=' ' ; + char * Regname="" ; + char * RegnameEBX="" ; + + for (regx = 0 ; regx < 8 ; regx++) + for (leng = 0 ; leng < 3 ; leng++) + for (regy = 0 ; regy < 8 ; regy++) + { + Opcode = 0xb108 | (regx<<9) | (leng<<6) | regy ; + BaseCode = Opcode & 0xb1c8 ; + + ModeModX = 0; + ModeModY = 0; + +#ifdef A7ROUTINE + if (leng==0) + { + if (regx==7) + { + BaseCode |= (regx<<9); + ModeModX = 16; + } + + if (regy==7) + { + BaseCode |= regy; + ModeModY = 16; + } + } +#endif + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[EAX]; + RegnameEBX = regnamesshort[EBX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[EAX]; + RegnameEBX = regnamesword[EBX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[EAX]; + RegnameEBX = regnameslong[EBX]; + break; + } + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + AddEACycles = 0 ; + + if (Size != 'L') + TimingCycles += 12 ; + else + TimingCycles += 20 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx, byte 7\n"); + fprintf(fp, "\t\t shr ecx, byte 9\n"); + fprintf(fp, "\t\t and ecx, byte 7\n"); + + EffectiveAddressRead(3+ModeModY,Size,EBX,EBX,"--C-S-B",FALSE); + EffectiveAddressRead(3+ModeModX,Size,ECX,EAX,"-B--S-B",FALSE); + + fprintf(fp, "\t\t cmp %s,%s\n",Regname,RegnameEBX); + SetFlags(Size,EAX,FALSE,FALSE,FALSE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void exg(void) +{ + int Opcode, BaseCode ; + int regx,type,regy ; + int opmask[3] = { 0x08, 0x09, 0x11} ; + + for (regx = 0 ; regx < 8 ; regx++) + for (type = 0 ; type < 3 ; type++) + for (regy = 0 ; regy < 8 ; regy++) + { + Opcode = 0xc100 | (regx<<9) | (opmask[type]<<3) | regy ; + BaseCode = Opcode & 0xc1c8 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 6 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + fprintf(fp, "\t\t shr ecx,byte 9\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); + + if (type == 0) + { + fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_DAT); + fprintf(fp, "\t\t mov edi,[%s+EBX*4]\n",REG_DAT); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_DAT); + fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_DAT); + } + if (type == 1) + { + fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_ADD); + fprintf(fp, "\t\t mov edi,[%s+EBX*4]\n",REG_ADD); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD); + fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_ADD); + } + if (type == 2) + { + fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_DAT); + fprintf(fp, "\t\t mov edi,[%s+EBX*4]\n",REG_ADD); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_DAT); + fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_ADD); + } + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void ext(void) +{ + int Opcode, BaseCode ; + int type,regy ; + + for (type = 2 ; type < 8 ; type++) + for (regy = 0 ; regy < 8 ; regy++) + { + if (type > 3 && type < 7) + continue ; + Opcode = 0x4800 | (type<<6) | regy ; + BaseCode = Opcode & 0x48c0 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4 ; + + fprintf(fp, "\t\t and ecx, byte 7\n"); + + if (type == 2) /* byte to word */ + { + fprintf(fp, "\t\t movsx eax,byte [%s+ECX*4]\n",REG_DAT); + fprintf(fp, "\t\t mov [%s+ECX*4],ax\n",REG_DAT); + SetFlags('W',EAX,TRUE,FALSE,FALSE); + } + if (type == 3) /* word to long */ + { + fprintf(fp, "\t\t movsx eax,word [%s+ECX*4]\n",REG_DAT); + fprintf(fp, "\t\t mov [%s+ECX*4],eax\n",REG_DAT); + SetFlags('L',EAX,TRUE,FALSE,FALSE); + } + if (type == 7) /* byte to long */ + { + fprintf(fp, "\t\t movsx eax,byte [%s+ECX*4]\n",REG_DAT); + fprintf(fp, "\t\t mov [%s+ECX*4],eax\n",REG_DAT); + SetFlags('L',EAX,TRUE,FALSE,FALSE); + } + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void swap(void) +{ + int Opcode, BaseCode ; + int sreg ; + + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4840 | sreg ; + BaseCode = Opcode & 0x4840; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4 ; + + fprintf(fp, "\t\t and ecx, byte 7\n"); + fprintf(fp, "\t\t mov eax, dword [%s+ECX*4]\n",REG_DAT); + fprintf(fp, "\t\t ror eax, 16\n"); + fprintf(fp, "\t\t test eax,eax\n"); + fprintf(fp, "\t\t mov dword [%s+ECX*4],eax\n",REG_DAT); + SetFlags('L',EAX,FALSE,FALSE,FALSE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +/* + * Line A and Line F commands + * + */ + +void LineA(void) +{ + int Count; + + /* Line A */ + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(0xA000,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + Exception(0x0A,0xA000); + + for (Count=0xA000;Count<0xB000;Count++) + { + OpcodeArray[Count] = 0xA000; + } +} + +void LineF(void) +{ + int Count; + + /* Line F */ + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(0xF000,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + Exception(0x0B,0xF000); + + for (Count=0xF000;Count<0x10000;Count++) + { + OpcodeArray[Count] = 0xF000; + } +} + +/* + * Moves To/From CCR and SR + * + * (Move from CCR is 68010 command) + * + */ + +void movesr(void) +{ + int Opcode, BaseCode ; + int type, mode, sreg ; + int Dest ; + char allow[] = "0-2345678-------" ; + char Size; + + for (type = 0 ; type < 4 ; type++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x40c0 | (type << 9) | ( mode << 3 ) | sreg ; + + /* To has extra modes */ + + if (type > 1) + { + allow[0x9] = '9'; + allow[0xa] = 'a'; + allow[0xb] = 'b' ; + } + + if ((type == 0) | (type == 3)) + Size = 'W'; /* SR */ + else + Size = 'B'; /* CCR */ + + BaseCode = Opcode & 0x46f8 ; + + if (mode == 7) + BaseCode |= sreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + char TrueLabel[16]; + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (type > 1) /* move to */ + TimingCycles += 12 ; + else + { + if (mode < 2) + TimingCycles += 6 ; + else + TimingCycles += 8 ; + } + + /* If Move to SR then must be in Supervisor Mode */ + + if (type == 3) + { + sprintf(TrueLabel,GenerateLabel(0,1)); + + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t je near %s\n\n",TrueLabel); + } + + /* 68010 Command ? */ + if (type==1) CheckCPUtype(1); + + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + /* Always read/write word 2 bytes */ + if (type < 2) + { + ReadCCR(Size,EBX); + EffectiveAddressWrite(Dest & 15,'W',ECX,TRUE,"---DS-B",TRUE); + } + else + { + EffectiveAddressRead(Dest & 15,'W',ECX,EAX,"----S-B",FALSE); + WriteCCR(Size); + } + Completed(); + + /* Exception if not Supervisor Mode */ + + if (type == 3) + { + /* Was in User Mode - Exception */ + + fprintf(fp, "%s:\n",TrueLabel); + Exception(8,BaseCode); + } + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Decimal mode Add / Subtracts + * + */ + +void abcd_sbcd(void) +{ + int Opcode, BaseCode ; + int regx,type,rm,regy,mode ; + int ModeModX; + int ModeModY; + char *Label; + + for (type = 0 ; type < 2 ; type ++) /* 0=sbcd, 1=abcd */ + for (regx = 0 ; regx < 8 ; regx++) + for (rm = 0 ; rm < 2 ; rm++) + for (regy = 0 ; regy < 8 ; regy++) + { + Opcode = 0x8100 | (type<<14) | (regx<<9) | (rm<<3) | regy ; + BaseCode = Opcode & 0xc108 ; + + ModeModX = 0; + ModeModY = 0; + + if (rm == 0) + mode = 0 ; + else + { + mode = 4 ; + +#ifdef A7ROUTINE + + if (regx == 7) + { + BaseCode |= (regx << 9); + ModeModY = 16; + } + if (regy == 7) + { + BaseCode |= regy; + ModeModX = 16; + } + +#endif + } + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if (mode == 4) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + AddEACycles = 0 ; + + if (rm == 0) + TimingCycles += 6 ; + else + TimingCycles += 18 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx, byte 7\n"); + fprintf(fp, "\t\t shr ecx, byte 9\n"); + fprintf(fp, "\t\t and ecx, byte 7\n"); + + EffectiveAddressRead(mode+ModeModX,'B',EBX,EBX,"--C-S-B",TRUE); + EffectiveAddressRead(mode+ModeModY,'B',ECX,EAX,"-BC-SDB",TRUE); + + CopyX(); + + if (type == 0) + { + fprintf(fp, "\t\t sbb al,bl\n"); + fprintf(fp, "\t\t das\n"); + } + else + { + fprintf(fp, "\t\t adc al,bl\n"); + fprintf(fp, "\t\t daa\n"); + } + + /* Should only clear Zero flag if not zero */ + + Label = GenerateLabel(0,1); + + fprintf(fp, "\t\t mov ebx,edx\n"); + fprintf(fp, "\t\t setc dl\n"); + + fprintf(fp, "\t\t jnz short %s\n\n",Label); + + /* Keep original Zero flag */ + fprintf(fp, "\t\t and bl,40h ; Mask out Old Z\n"); + fprintf(fp, "\t\t or dl,bl ; Copy across\n\n"); + + fprintf(fp, "%s:\n",Label); + + fprintf(fp, "\t\t mov bl,dl\n"); /* copy carry into sign */ + fprintf(fp, "\t\t and bl,1\n"); + fprintf(fp, "\t\t shl bl,7\n"); + fprintf(fp, "\t\t and dl,7Fh\n"); + fprintf(fp, "\t\t or dl,bl\n"); + + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + + EffectiveAddressWrite(mode,'B',ECX,EAX,"---DS-B",TRUE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +/* + * Rotate Left / Right + * + */ + +void rol_ror(void) +{ + int Opcode, BaseCode ; + int dreg, dr, leng, ir, sreg ; + char Size=' '; + char * Label ; + char * Regname="" ; + char * RegnameECX ; + + for (dreg = 0 ; dreg < 8 ; dreg++) + for (dr = 0 ; dr < 2 ; dr++) + for (leng = 0 ; leng < 3 ; leng++) + for (ir = 0 ; ir < 2 ; ir++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe018 | (dreg<<9) | (dr<<8) | (leng<<6) | (ir<<5) | sreg ; + BaseCode = Opcode & 0xe1f8 ; + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + break; + } + + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (Size != 'L') + TimingCycles += 6 ; + else + TimingCycles += 8 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + fprintf(fp, "\t\t shr ecx,byte 9\n"); + + if (ir == 0) + { + Immediate8(); + } + else + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(0,'L',ECX,ECX,"-B--S-B",FALSE); + fprintf(fp, "\t\t and ecx,byte 63\n"); + } + + EffectiveAddressRead(0,Size,EBX,EAX,"-BC-S-B",FALSE); + + /* shift 0 - no time, no shift and clear carry */ + + Label = GenerateLabel(0,1); + fprintf(fp, "\t\t jecxz %s\n",Label); + + /* allow 2 cycles per shift */ + + fprintf(fp, "\t\t mov edx,ecx\n"); + fprintf(fp, "\t\t add edx,edx\n"); + fprintf(fp, "\t\t sub dword [%s],edx\n",ICOUNT); + + if (dr == 0) + fprintf(fp, "\t\t ror %s,cl\n",Regname); + else + fprintf(fp, "\t\t rol %s,cl\n",Regname); + + fprintf(fp, "\t\t setc ch\n"); + + fprintf(fp, "%s:\n",Label); + + SetFlags(Size,EAX,TRUE,FALSE,FALSE); +/* fprintf(fp, "\t\t and dl,254\n"); Test clears Carry */ + fprintf(fp, "\t\t or dl,ch\n"); + + EffectiveAddressWrite(0,Size,EBX,EAX,"--C-S-B",TRUE); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void rol_ror_ea(void) +{ + int Opcode, BaseCode ; + int dr, mode, sreg ; + int Dest ; + char allow[] = "--2345678-------" ; + + for (dr = 0 ; dr < 2 ; dr++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe6c0 | (dr<<8) | (mode<<3) | sreg ; + BaseCode = Opcode & 0xfff8 ; + + if (mode == 7) + BaseCode |= sreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 8 ; + + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(Dest&0xf,'W',ECX,EAX,"--C-SDB",FALSE); + + if (dr == 0) + fprintf(fp, "\t\t ror ax,1\n"); + else + fprintf(fp, "\t\t rol ax,1\n"); + + fprintf(fp, "\t\t setc bl\n"); + SetFlags('W',EAX,TRUE,FALSE,FALSE); +/* fprintf(fp, "\t\t and dl,254\n"); Test clears Carry */ + fprintf(fp, "\t\t or dl,bl\n"); + + EffectiveAddressWrite(Dest&0xf,'W',ECX,EAX,"---DS-B",TRUE); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Logical Shift Left / Right + * + */ + +void lsl_lsr(void) +{ + int Opcode, BaseCode ; + int dreg, dr, leng, ir, sreg ; + char Size=' '; + char * Regname="" ; + char * RegnameECX="" ; + char * RegnameEDX="" ; + char * Label ; + + for (dreg = 0 ; dreg < 8 ; dreg++) + for (dr = 0 ; dr < 2 ; dr++) + for (leng = 0 ; leng < 3 ; leng++) + for (ir = 0 ; ir < 2 ; ir++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe008 | (dreg<<9) | (dr<<8) | (leng<<6) | (ir<<5) | sreg ; + BaseCode = Opcode & 0xe1f8 ; + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + RegnameEDX = regnamesshort[EDX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + RegnameEDX = regnamesword[EDX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + RegnameEDX = regnameslong[EDX]; + break; + } + + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (Size != 'L') + TimingCycles += 6 ; + else + TimingCycles += 8 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + fprintf(fp, "\t\t shr ecx,byte 9\n"); + + if (ir == 0) + { + Immediate8(); + } + else + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(0,'L',ECX,ECX,"-B--S-B",FALSE); + fprintf(fp, "\t\t and ecx,byte 63\n"); + } + + /* and 2 cycles per shift */ + + fprintf(fp, "\t\t mov edx,ecx\n"); + fprintf(fp, "\t\t add edx,edx\n"); + fprintf(fp, "\t\t sub dword [%s],edx\n",ICOUNT); + + EffectiveAddressRead(0,Size,EBX,EAX,"-BC-S-B",FALSE); + + /* ASG: on the 68k, the shift count is mod 64; on the x86, the */ + /* shift count is mod 32; we need to check for shifts of 32-63 */ + /* and produce zero */ + Label = GenerateLabel(0,1); + fprintf(fp, "\t\t test cl,0x20\n"); + fprintf(fp, "\t\t jnz %s_BigShift\n",Label); + + fprintf(fp, "%s_Continue:\n",Label); + if (dr == 0) + fprintf(fp, "\t\t shr %s,cl\n",Regname); + else + fprintf(fp, "\t\t shl %s,cl\n",Regname); + + SetFlags(Size,EAX,FALSE,FALSE,FALSE); + + /* Clear Overflow flag */ + fprintf(fp, "\t\t xor dh,dh\n"); + + EffectiveAddressWrite(0,Size,EBX,EAX,"--CDS-B",TRUE); + + /* if shift count is zero clear carry */ + + fprintf(fp, "\t\t jecxz %s\n",Label); + + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + Completed(); + + Align(); + fprintf(fp, "%s:\n",Label); + fprintf(fp, "\t\t and dl,254\t\t;clear C flag\n"); + Completed(); + + fprintf(fp, "%s_BigShift:\n",Label); + if (dr == 0) + { + fprintf(fp, "\t\t shr %s,16\n",Regname); + fprintf(fp, "\t\t shr %s,16\n",Regname); + } + else + { + fprintf(fp, "\t\t shl %s,16\n",Regname); + fprintf(fp, "\t\t shl %s,16\n",Regname); + } + fprintf(fp, "\t\t jmp %s_Continue\n",Label); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void lsl_lsr_ea(void) +{ + int Opcode, BaseCode ; + int dr, mode, sreg ; + int Dest ; + char allow[] = "--2345678-------" ; + + for (dr = 0 ; dr < 2 ; dr++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe2c0 | (dr<<8) | (mode<<3) | sreg ; + BaseCode = Opcode & 0xfff8 ; + + if (mode == 7) + BaseCode |= sreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 8 ; + + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(Dest&0xf,'W',ECX,EAX,"--C-SDB",FALSE); + + if (dr == 0) + fprintf(fp, "\t\t shr ax,1\n"); + else + fprintf(fp, "\t\t shl ax,1\n"); + + SetFlags('W',EAX,FALSE,TRUE,FALSE); + + /* Clear Overflow flag */ + + fprintf(fp, "\t\t xor dh,dh\n"); + + EffectiveAddressWrite(Dest&0xf,'W',ECX,EAX,"---DS-B",TRUE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Rotate Left / Right though Extend + * + */ + +void roxl_roxr(void) +{ + int Opcode, BaseCode ; + int dreg, dr, leng, ir, sreg ; + char Size=' ' ; + char * Regname="" ; + char * RegnameECX="" ; + char * Label ; + + for (dreg = 0 ; dreg < 8 ; dreg++) + for (dr = 0 ; dr < 2 ; dr++) + for (leng = 0 ; leng < 3 ; leng++) + for (ir = 0 ; ir < 2 ; ir++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe010 | (dreg<<9) | (dr<<8) | (leng<<6) | (ir<<5) | sreg ; + BaseCode = Opcode & 0xe1f8 ; + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + break; + } + + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (Size != 'L') + TimingCycles += 6 ; + else + TimingCycles += 8 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + fprintf(fp, "\t\t shr ecx,byte 9\n"); + + if (ir == 0) + { + Immediate8(); + } + else + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(0,'L',ECX,ECX,"-B--S-B",FALSE); + fprintf(fp, "\t\t and ecx,byte 63\n"); + } + + /* allow 2 cycles per shift */ + + fprintf(fp, "\t\t mov edx,ecx\n"); + fprintf(fp, "\t\t add edx,edx\n"); + fprintf(fp, "\t\t sub dword [%s],edx\n",ICOUNT); + + EffectiveAddressRead(0,Size,EBX,EAX,"-BC-SDB",FALSE); + + /* move X into C so RCR & RCL can be used */ + /* RCR & RCL only set the carry flag */ + + CopyX(); + + if (dr == 0) + fprintf(fp, "\t\t rcr %s,cl\n",Regname); + else + fprintf(fp, "\t\t rcl %s,cl\n",Regname); + + fprintf(fp, "\t\t setc ch\n"); + SetFlags(Size,EAX,TRUE,FALSE,FALSE); +/* fprintf(fp, "\t\t and dl,254\n"); Test Clears Carry */ + + EffectiveAddressWrite(0,Size,EBX,EAX,"--CDS-B",TRUE); + + /* if shift count is zero clear carry */ + + Label = GenerateLabel(0,1); + fprintf(fp, "\t\t test cl,cl\n"); + fprintf(fp, "\t\t jz %s\n",Label); + + /* Add in Carry Flag */ + + fprintf(fp, "\t\t or dl,ch\n"); + fprintf(fp, "\t\t mov [%s],dl\n",REG_X); + Completed(); + + + /* copy X onto C when shift is zero */ + + Align(); + fprintf(fp, "%s:\n",Label); + fprintf(fp, "\t\t mov ecx,[%s]\n",REG_X); + fprintf(fp, "\t\t and ecx,byte 1\n"); + fprintf(fp, "\t\t or edx,ecx\n"); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void roxl_roxr_ea(void) +{ + int Opcode, BaseCode ; + int dr, mode, sreg ; + int Dest ; + char allow[] = "--2345678-------" ; + + for (dr = 0 ; dr < 2 ; dr++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe4c0 | (dr<<8) | (mode<<3) | sreg ; + BaseCode = Opcode & 0xfff8 ; + + if (mode == 7) + BaseCode |= sreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 8 ; + + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(Dest&0xf,'W',ECX,EAX,"--C-SDB",FALSE); + + /* move X into C so RCR & RCL can be used */ + /* RCR & RCL only set the carry flag */ + + CopyX(); + + if (dr == 0) + fprintf(fp, "\t\t rcr ax,1\n"); + else + fprintf(fp, "\t\t rcl ax,1\n"); + + fprintf(fp, "\t\t setc bl\n"); + SetFlags('W',EAX,TRUE,FALSE,FALSE); +/* fprintf(fp, "\t\t and dl,254\n"); - Intel Clears on Test */ + fprintf(fp, "\t\t or dl,bl\n"); + + EffectiveAddressWrite(Dest&0xf,'W',ECX,EAX,"---DS-B",TRUE); + + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Arithmetic Shift Left / Right + * + */ + +void asl_asr(void) +{ + int Opcode, BaseCode ; + int dreg, dr, leng, ir, sreg ; + char Size=' '; + char * Sizename="" ; + char * Regname="" ; + char * RegnameEDX="" ; + char * RegnameECX="" ; + char * Label; + + /* Normal routines for codes */ + + for (dreg = 0 ; dreg < 8 ; dreg++) + for (dr = 0 ; dr < 2 ; dr++) + for (leng = 0 ; leng < 3 ; leng++) + for (ir = 0 ; ir < 2 ; ir++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe000 | (dreg<<9) | (dr<<8) | (leng<<6) | (ir<<5) | sreg ; + BaseCode = Opcode & 0xe1f8 ; + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + RegnameEDX = regnamesshort[EDX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + RegnameEDX = regnamesword[EDX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + RegnameEDX = regnameslong[EDX]; + break; + } + + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + Label = GenerateLabel(0,1); + + if (Size != 'L') + TimingCycles += 6 ; + else + TimingCycles += 8 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + fprintf(fp, "\t\t shr ecx,byte 9\n"); + + EffectiveAddressRead(0,Size,EBX,EAX,"-BC-S-B",FALSE); + + if (ir == 0) + { + Immediate8(); + } + else + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(0,'L',ECX,ECX,"-B--S-B",FALSE); + fprintf(fp, "\t\t and ecx,byte 63\n"); + fprintf(fp, "\t\t jz short %s\n",Label); + } + + /* allow 2 cycles per shift */ + + fprintf(fp, "\t\t mov edx,ecx\n"); + fprintf(fp, "\t\t add edx,edx\n"); + fprintf(fp, "\t\t sub dword [%s],edx\n",ICOUNT); + + if (dr == 0) + { + /* ASR */ + + /* ASG: on the 68k, the shift count is mod 64; on the x86, the */ + /* shift count is mod 32; we need to check for shifts of 32-63 */ + /* and effectively shift 31 */ + fprintf(fp, "\t\t shrd edx,ecx,6\n"); + fprintf(fp, "\t\t sar edx,31\n"); + fprintf(fp, "\t\t and edx,31\n"); + fprintf(fp, "\t\t or ecx,edx\n"); + + fprintf(fp, "\t\t sar %s,cl\n",Regname); + + /* Mode 0 write does not affect Flags */ + EffectiveAddressWrite(0,Size,EBX,EAX,"---DS-B",TRUE); + + /* Update Flags */ + fprintf(fp, "\t\t lahf\n"); + +#ifdef STALLCHECK + ClearRegister(EDX); + fprintf(fp, "\t\t mov dl,ah\n"); +#else + fprintf(fp, "\t\t movzx edx,ah\n"); +#endif + + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + } + else + { + /* ASL */ + + /* Check to see if Overflow should be set */ + + fprintf(fp,"\t\t mov edi,eax\t\t; Save It\n"); + + ClearRegister(EDX); + fprintf(fp,"\t\t stc\n"); + fprintf(fp,"\t\t rcr %s,1\t\t; d=1xxxx\n",RegnameEDX); + fprintf(fp,"\t\t sar %s,cl\t\t; d=1CCxx\n",RegnameEDX); + fprintf(fp,"\t\t and eax,edx\n"); + fprintf(fp,"\t\t jz short %s_V\t\t; No Overflow\n",Label); + fprintf(fp,"\t\t cmp eax,edx\n"); + fprintf(fp,"\t\t je short %s_V\t\t; No Overflow\n",Label); + + /* Set Overflow */ + fprintf(fp,"\t\t mov edx,0x800\n"); + fprintf(fp,"\t\t jmp short %s_OV\n",Label); + + fprintf(fp,"%s_V:\n",Label); + ClearRegister(EDX); + + fprintf(fp,"%s_OV:\n",Label); + + /* more than 31 shifts and long */ + + if ((ir==1) && (leng==2)) + { + fprintf(fp,"\t\t test cl,0x20\n"); + fprintf(fp,"\t\t jnz short %s_32\n\n",Label); + } + + fprintf(fp,"\t\t mov eax,edi\t\t; Restore It\n"); + + fprintf(fp, "\t\t sal %s,cl\n",Regname); + + EffectiveAddressWrite(0,Size,EBX,EAX,"---DS-B",TRUE); + fprintf(fp, "\t\t lahf\n"); + fprintf(fp, "\t\t mov dl,ah\n"); + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + } + Completed(); + + if (ir != 0) + { + Align(); + fprintf(fp, "%s:\n",Label); + + + if (dr == 0) + { + /* ASR - Test clears V and C */ + SetFlags(Size,EAX,TRUE,FALSE,FALSE); + } + else + { + /* ASL - Keep existing Carry flag, Clear V */ + fprintf(fp, "\t\t mov ebx,edx\n"); + fprintf(fp, "\t\t and ebx,byte 1\n"); + SetFlags(Size,EAX,TRUE,FALSE,FALSE); + fprintf(fp, "\t\t or edx,ebx\n"); + + if (leng==2) + { + Completed(); + + /* > 31 Shifts */ + + fprintf(fp, "%s_32:\n",Label); + fprintf(fp, "\t\t mov dl,40h\n"); // Zero flag + ClearRegister(EAX); + EffectiveAddressWrite(0,Size,EBX,EAX,"----S-B",TRUE); + } + } + + Completed(); + } + } + + OpcodeArray[Opcode] = BaseCode ; + } + + /* End with special routines for ASL.x #1,Dx */ + /* To do correct V setting, ASL needs quite a */ + /* bit of additional code. A Shift of one has */ + /* correct flags on Intel, and is very common */ + /* in 68000 programs. */ + + for (leng = 0 ; leng < 3 ; leng++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe300 | (leng<<6) | sreg ; + BaseCode = Opcode & 0xe3c8 ; + + switch (leng) + { + case 0: + Sizename = "byte"; + break; + case 1: + Sizename = "word"; + break; + case 2: + Sizename = "long"; + break; + } + + if (sreg == 0) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + Label = GenerateLabel(0,1); + + if (Size != 'L') + TimingCycles += 6 ; + else + TimingCycles += 8 ; + + fprintf(fp, "\t\t and ecx,byte 7\n"); + fprintf(fp, "\t\t sal %s [%s+ecx*4],1\n",Sizename,REG_DAT); + SetFlags('L',EAX,FALSE,TRUE,FALSE); + Completed(); + + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void asl_asr_ea(void) +{ + int Opcode, BaseCode ; + int dr, mode, sreg ; + int Dest ; + char allow[] = "--2345678-------" ; + + for (dr = 0 ; dr < 2 ; dr++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe0c0 | (dr<<8) | (mode<<3) | sreg ; + BaseCode = Opcode & 0xfff8 ; + + if (mode == 7) + BaseCode |= sreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 8 ; + + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(Dest&0xf,'W',ECX,EAX,"--C-SDB",FALSE); + + if (dr == 0) + fprintf(fp, "\t\t sar ax,1\n"); + else + fprintf(fp, "\t\t sal ax,1\n"); + + SetFlags('W',EAX,FALSE,TRUE,TRUE); + + EffectiveAddressWrite(Dest&0xf,'W',ECX,EAX,"----S-B",FALSE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Divide Commands + */ + +void divides(void) +{ + int dreg, type, mode, sreg ; + int Opcode, BaseCode ; + int Dest ; + char allow[] = "0-23456789ab-----" ; + char TrapLabel[16]; + int Cycles; + + int divide_cycles[12] = + { + 38,0,42,42,44,46,50,46,50,46,48,42 + }; + + for (dreg = 0 ; dreg < 8 ; dreg++) + for (type = 0 ; type < 2 ; type++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x80c0 | (dreg<<9) | (type<<8) | (mode<<3) | sreg ; + BaseCode = Opcode & 0x81f8 ; + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + + /* Save EDX (in case of overflow) */ + + fprintf(fp, "\t\t and edx,byte -2\n"); + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + + + /* Cycle Timing (if succeeds OK) */ + + Cycles = divide_cycles[Dest & 0x0f] + 95 + (type * 17); + + if (Cycles > 127) + fprintf(fp, "\t\t sub dword [%s],%d\n",ICOUNT,Cycles); + else + fprintf(fp, "\t\t sub dword [%s],byte %d\n",ICOUNT,Cycles); + + if (mode < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + } + + fprintf(fp, "\t\t shr ecx, byte 9\n"); + fprintf(fp, "\t\t and ecx, byte 7\n"); + + sprintf(TrapLabel, "%s", GenerateLabel(0,1) ) ; + + EffectiveAddressRead(Dest,'W',EBX,EAX,"A-C-SDB",FALSE); /* source */ + + fprintf(fp, "\t\t test ax,ax\n"); + fprintf(fp, "\t\t je near %s_ZERO\t\t;do div by zero trap\n", TrapLabel); + + if (type == 1) /* signed */ + { + fprintf(fp, "\t\t movsx ebx,ax\n"); + } + else + { + fprintf(fp, "\t\t movzx ebx,ax\n"); + } + + EffectiveAddressRead(0,'L',ECX,EAX,"ABC-SDB",FALSE); /* dest */ + + if (type == 1) /* signed */ + { + fprintf(fp, "\t\t cdq\n"); /* EDX:EAX = 64 bit signed */ + fprintf(fp, "\t\t idiv ebx\n"); /* EBX = 32 bit */ + + /* Check for Overflow */ + + fprintf(fp, "\t\t movsx ebx,ax\n"); + fprintf(fp, "\t\t cmp eax,ebx\n"); + fprintf(fp, "\t\t jne short %s_OVER\n",TrapLabel); + } + else + { + ClearRegister(EDX); + fprintf(fp, "\t\t div ebx\n"); + + /* Check for Overflow */ + + fprintf(fp, "\t\t test eax, 0FFFF0000H\n"); + fprintf(fp, "\t\t jnz short %s_OVER\n",TrapLabel); + } + + /* Sort out Result */ + + fprintf(fp, "\t\t shl edx, byte 16\n"); + fprintf(fp, "\t\t mov dx,ax\n"); + fprintf(fp, "\t\t mov [%s+ECX*4],edx\n",REG_DAT); + SetFlags('W',EDX,TRUE,FALSE,FALSE); + + Completed(); + + + /* Overflow */ + + Align(); + fprintf(fp, "%s_OVER:\n",TrapLabel); + fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR); + fprintf(fp, "\t\t or edx,0x0800\t\t;V flag\n"); + Completed(); + + + /* Division by Zero */ + + Align(); + fprintf(fp, "%s_ZERO:\t\t ;Do divide by zero trap\n", TrapLabel); + + /* Correct cycle counter for error */ + + fprintf(fp, "\t\t add dword [%s],byte %d\n",ICOUNT,95 + (type * 17)); + fprintf(fp, "\t\t mov al,5\n"); + Exception(-1,BaseCode); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + + +/* + * 68010 Extra Opcodes + * + * move from CCR is done above + * + */ + +void ReturnandDeallocate(void) +{ + int BaseCode = 0x4e74 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + CheckCPUtype(1); + + SavePreviousPC(); + + TimingCycles += 16; + + OpcodeArray[BaseCode] = BaseCode ; + + /* Get Return Address */ + + fprintf(fp, "\t\t mov eax,[%s]\n",REG_A7); + Memory_Read('L',EAX,"---D--B",1); + + + /* Get Displacement */ + + Memory_Fetch('W',EBX,TRUE); + + + /* Set PC = New Address */ + + fprintf(fp, "\t\t mov esi,eax\n"); + + + /* Correct Stack for Return Address and Displacement */ + + fprintf(fp, "\t\t add ebx,byte 4\n"); + fprintf(fp, "\t\t add dword [%s],ebx\n",REG_A7); + + MemoryBanking(BaseCode); + Completed(); + } +} + +void MoveControlRegister(void) +{ + int Direction; + int BaseCode = 0x4e7a ; + + for (Direction=0;Direction<2;Direction++) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode+Direction,0)); + + TimingCycles += 4; /* Assume same as move usp */ + + CheckCPUtype(1); + + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t jz short OP%d_%4.4x_Trap\n",CPU,BaseCode+Direction); + + fprintf(fp, "\t\t add esi,byte 2\n"); + if (CPU==2) + fprintf(fp, "\t\t xor esi,2\n"); /* ASG */ +#ifdef STALLCHECK + ClearRegister(EBX); + fprintf(fp, "\t\t mov bx,[esi+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ebx,word [esi+ebp]\n"); +#endif + if (CPU==2) + fprintf(fp, "\t\t xor esi,2\n"); /* ASG */ + + fprintf(fp, "\t\t add esi,byte 2\n"); + fprintf(fp, "\t\t mov eax,ebx\n"); + fprintf(fp, "\t\t mov ecx,ebx\n"); + + /* Sort out Register */ + + fprintf(fp, "\t\t shr ebx,12\n"); + + /* Sort out Control Register ID */ + + fprintf(fp, "\t\t and eax,byte 1\n"); + fprintf(fp, "\t\t shr ecx,10\n"); + fprintf(fp, "\t\t and ecx,2\n"); + fprintf(fp, "\t\t or ecx,eax\n"); + + if (Direction==0) + { + /* from Control */ + + fprintf(fp, "\t\t mov eax,[%s+ecx*4]\n",REG_SFC); + fprintf(fp, "\t\t mov %s,eax\n",REG_DAT_EBX); + } + else + { + /* To Control */ + + fprintf(fp, "\t\t mov eax,%s\n",REG_DAT_EBX); + + /* Mask out for SFC & DFC */ + + fprintf(fp, "\t\t test cl,2\n"); + fprintf(fp, "\t\t jne short OP%d_%4.4x_Mask\n",CPU,BaseCode+Direction); + fprintf(fp, "\t\t and eax,byte 7\n"); + fprintf(fp, "OP%d_%4.4x_Mask:\n",CPU,BaseCode+Direction); + + /* Write to control */ + + fprintf(fp, "\t\t mov [%s+ecx*4],eax\n",REG_SFC); + } + + Completed(); + + /* Not Supervisor Mode */ + + Align(); + fprintf(fp, "OP%d_%4.4x_Trap:\n",CPU,BaseCode+Direction); + Exception(8,BaseCode+Direction); + + OpcodeArray[BaseCode+Direction] = BaseCode+Direction; + } +} + +void MoveAddressSpace(void) +{ +} + +/* + * Generate Jump Table + * + */ + +void JumpTable(void) +{ + int Opcode,l,op; + + fprintf(fp, "DD OP%d_1000\n",CPU); + + l = 0 ; + for (Opcode=0x0;Opcode<0x10000;) + { + + op = OpcodeArray[Opcode]; + + fprintf(fp, "DD "); + + l = 1 ; + while (op == OpcodeArray[Opcode+l] && ((Opcode+l) & 0xfff) != 0) + { + l++ ; + } + + Opcode += l ; + + if (l > 255) + { + if (op > -1) + fprintf(fp, "OP%d_%4.4x - OP%d_1000\n",CPU,op,CPU); + else + fprintf(fp, "ILLEGAL - OP%d_1000\n",CPU); + + fprintf(fp, "DW %d\n", l); + } + else + { + if (op > -1) + fprintf(fp, "(OP%d_%4.4x - OP%d_1000) + (%d * 1000000h)\n",CPU,op,CPU,l); + else + fprintf(fp, "(ILLEGAL - OP%d_1000) + (%d * 1000000h)\n",CPU,l); + } + } +} + +void CodeSegmentBegin(void) +{ + +/* Messages */ + + fprintf(fp, "; Make68K - V%s - Copyright 1998, Mike Coates (mame@btinternet.com)\n", VERSION); + fprintf(fp, "; & Darren Olafson (deo@mail.island.net)\n\n"); + +/* Needed code to make it work! */ + + fprintf(fp, "\t\t BITS 32\n\n"); + + fprintf(fp, "\t\t GLOBAL %s_RUN\n",CPUtype); + fprintf(fp, "\t\t GLOBAL %s_RESET\n",CPUtype); + fprintf(fp, "\t\t GLOBAL %s_regs\n",CPUtype); + fprintf(fp, "\t\t GLOBAL %s_COMPTABLE\n",CPUtype); + fprintf(fp, "\t\t GLOBAL %s_OPCODETABLE\n",CPUtype); + + /* ASG - only one interface to memory now */ + fprintf(fp, "\t\t EXTERN _m68k_ICount\n"); + fprintf(fp, "\t\t EXTERN _a68k_memory_intf\n"); + fprintf(fp, "\t\t EXTERN _mem_amask\n"); + + fprintf(fp, "; Vars Mame declares / needs access to\n\n"); + + fprintf(fp, "\t\t EXTERN _mame_debug\n"); + fprintf(fp, "\t\t EXTERN _illegal_op\n"); + fprintf(fp, "\t\t EXTERN _illegal_pc\n"); + + fprintf(fp, "\t\t EXTERN _OP_ROM\n"); + fprintf(fp, "\t\t EXTERN _OP_RAM\n"); + + fprintf(fp, "\t\t EXTERN _opcode_entry\n"); + fprintf(fp, "\t\t EXTERN _cur_mrhard\n"); + +//#ifdef MAME_DEBUG + fprintf(fp, "\t\t EXTERN _m68k_illegal_opcode\n"); +//#endif + +#ifdef OS2 + fprintf(fp, "\t\t SECTION maincode USE32 FLAT CLASS=CODE\n\n"); +#else + fprintf(fp, "\t\t SECTION .text\n\n"); +#endif + + + +/* Reset routine */ + + fprintf(fp, "%s_RESET:\n",CPUtype); + + fprintf(fp, "\t\t pushad\n\n"); + + fprintf(fp, "; Build Jump Table (not optimised!)\n\n"); + + fprintf(fp, "\t\t lea edi,[%s_OPCODETABLE]\t\t; Jump Table\n", CPUtype); + fprintf(fp, "\t\t lea esi,[%s_COMPTABLE]\t\t; RLE Compressed Table\n", CPUtype); + + /* Reference Point in EBP */ + + fprintf(fp, "\t\t mov ebp,[esi]\n"); + fprintf(fp, "\t\t add esi,byte 4\n"); + + fprintf(fp, "RESET0:\n"); + fprintf(fp, "\t\t mov eax,[esi]\n"); + fprintf(fp, "\t\t mov ecx,eax\n"); + fprintf(fp, "\t\t and eax,0xffffff\n"); + fprintf(fp, "\t\t add eax,ebp\n"); + fprintf(fp, "\t\t add esi,byte 4\n"); + + /* if count is zero, then it's a word RLE length */ + + fprintf(fp, "\t\t shr ecx,24\n"); + fprintf(fp, "\t\t jne short RESET1\n"); + +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[esi]\t\t; Repeats\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [esi]\t\t; Repeats\n"); +#endif + + fprintf(fp, "\t\t add esi,byte 2\n"); + fprintf(fp, "\t\t jecxz RESET2\t\t; Finished!\n"); + + fprintf(fp, "RESET1:\n"); + fprintf(fp, "\t\t mov [edi],eax\n"); + fprintf(fp, "\t\t add edi,byte 4\n"); + fprintf(fp, "\t\t dec ecx\n"); + fprintf(fp, "\t\t jnz short RESET1\n"); + fprintf(fp, "\t\t jmp short RESET0\n"); + + fprintf(fp, "RESET2:\n"); + fprintf(fp, "\t\t popad\n"); + fprintf(fp, "\t\t ret\n\n"); + +/* Emulation Entry Point */ + + Align(); + + fprintf(fp, "%s_RUN:\n",CPUtype); + + fprintf(fp, "\t\t pushad\n"); + fprintf(fp, "\t\t mov esi,[%s]\n",REG_PC); + fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR); + fprintf(fp, "\t\t mov ebp,dword [_OP_ROM]\n"); + + fprintf(fp,"; Check for Interrupt waiting\n\n"); + fprintf(fp,"\t\t test [%s],byte 07H\n",REG_IRQ); + fprintf(fp,"\t\t jne near interrupt\n\n"); + + fprintf(fp, "IntCont:\n"); + + /* See if was only called to check for Interrupt */ + + fprintf(fp, "\t\t test dword [%s],-1\n",ICOUNT); + fprintf(fp, "\t\t js short MainExit\n\n"); + + if(CPU==2) + { + /* 32 Bit */ + fprintf(fp, "\t\t mov eax,2\n"); /* ASG */ + fprintf(fp, "\t\t xor eax,esi\n"); /* ASG */ +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[eax+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [eax+ebp]\n"); +#endif + } + else + { + /* 16 Bit Fetch */ +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[esi+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [esi+ebp]\n"); +#endif + } + fprintf(fp, "\t\t jmp [%s_OPCODETABLE+ecx*4]\n", CPUtype); + + Align(); + + fprintf(fp, "MainExit:\n"); + fprintf(fp, "\t\t mov [%s],esi\t\t; Save PC\n",REG_PC); + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + fprintf(fp, "\t\t test byte [%s],20H\n",REG_SRH); + fprintf(fp, "\t\t mov eax,[%s]\t\t; Get A7\n",REG_A7); + fprintf(fp, "\t\t jne short ME1\t\t; Mode ?\n"); + fprintf(fp, "\t\t mov [%s],eax\t\t;Save in USP\n",REG_USP); + fprintf(fp, "\t\t jmp short MC68Kexit\n"); + fprintf(fp, "ME1:\n"); + fprintf(fp, "\t\t mov [%s],eax\n",REG_ISP); + fprintf(fp, "MC68Kexit:\n"); + + /* If in Debug mode make normal SR register */ + +#ifdef MAME_DEBUG + + ReadCCR('W', ECX); + fprintf(fp, "\t\t mov [%s],eax\n\n",REG_S); + +#endif + + fprintf(fp, "\t\t popad\n"); + fprintf(fp, "\t\t ret\n"); + +/* Check for Pending Interrupts */ + + Align(); + fprintf(fp, "; Interrupt check\n\n"); + + fprintf(fp, "interrupt:\n"); + + /* check to exclude interrupts */ + + fprintf(fp, "\t\t mov eax,[%s]\n",REG_IRQ); + fprintf(fp, "\t\t and eax,byte 07H\n"); + + fprintf(fp, "\t\t cmp al,7\t\t ; Always take 7\n"); + fprintf(fp, "\t\t je short procint\n\n"); + + fprintf(fp, "\t\t mov ebx,[%s]\t\t; int mask\n",REG_SRH); + fprintf(fp, "\t\t and ebx,byte 07H\n"); + fprintf(fp, "\t\t cmp eax,ebx\n"); + fprintf(fp, "\t\t jle near IntCont\n\n"); + + /* Take pending Interrupt */ + + Align(); + fprintf(fp, "procint:\n"); + fprintf(fp, "\t\t and byte [%s],78h\t\t; remove interrupt & stop\n\n",REG_IRQ); + + /* Get Interrupt Vector from callback */ + + fprintf(fp, "\t\t push eax\t\t; save level\n\n"); + + if (SavedRegs[EBX] == '-') + { + fprintf(fp, "\t\t push EBX\n"); + } + else + { + fprintf(fp, "\t\t mov ebx,eax\n"); + } + + if (SavedRegs[ESI] == '-') + { + fprintf(fp, "\t\t mov [%s],ESI\n",REG_PC); + } + + if (SavedRegs[EDX] == '-') + { + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + } + +/* ----- Win32 uses FASTCALL (By Kenjo)----- */ + +#ifdef FASTCALL + fprintf(fp, "\t\t mov %s, eax\t\t; irq line #\n",FASTCALL_FIRST_REG); + fprintf(fp, "\t\t call dword [%s]\t; get the IRQ level\n", REG_IRQ_CALLBACK); +#else + fprintf(fp, "\t\t push eax\t\t; irq line #\n"); + fprintf(fp, "\t\t call dword [%s]\t; get the IRQ level\n", REG_IRQ_CALLBACK); + fprintf(fp, "\t\t lea esp,[esp+4]\n"); +#endif + + if (SavedRegs[EDX] == '-') + { + fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR); + } + + if (SavedRegs[ESI] == '-') + { + fprintf(fp, "\t\t mov esi,[%s]\n",REG_PC); + } + + /* Do we want to use normal vector number ? */ + + + fprintf(fp, "\t\t test eax,eax\n"); + fprintf(fp, "\t\t jns short AUTOVECTOR\n"); + + /* Only need EBX restored if default vector to be used */ + + if (SavedRegs[EBX] == '-') + { + fprintf(fp, "\t\t pop EBX\n"); + } + + /* Just get default vector */ + + fprintf(fp, "\t\t mov eax,ebx\n"); + + fprintf(fp, "\t\t add eax,byte 24\t\t; Vector\n\n"); + + fprintf(fp, "AUTOVECTOR:\n\n"); + + Exception(-1,0xFFFF); + + fprintf(fp, "\t\t pop eax\t\t; set Int mask\n"); + fprintf(fp, "\t\t mov bl,byte [%s]\n",REG_SRH); + fprintf(fp, "\t\t and bl,0F8h\n"); + fprintf(fp, "\t\t or bl,al\n"); + fprintf(fp, "\t\t mov byte [%s],bl\n\n",REG_SRH); + fprintf(fp, "\t\t jmp IntCont\n\n"); + +/* Exception Routine */ + + Align(); + fprintf(fp, "Exception:\n"); + fprintf(fp, "\t\t push edx\t\t; Save flags\n"); + fprintf(fp, "\t\t and eax,0FFH\t\t; Zero Extend IRQ Vector\n"); + + fprintf(fp, "\t\t push eax\t\t; Save for Later\n"); + + /* Update Cycle Count */ + + fprintf(fp, "\t\t mov al,[exception_cycles+eax]\t\t; Get Cycles\n"); + fprintf(fp, "\t\t sub [%s],eax\t\t; Decrement ICount\n",ICOUNT); + + ReadCCR('W',ECX); + + fprintf(fp, "\t\t mov edi,[%s]\t\t; Get A7\n",REG_A7); + + fprintf(fp, "\t\t test ah,20H\t; Which Mode ?\n"); + fprintf(fp, "\t\t jne short ExSuperMode\t\t; Supervisor\n"); + + fprintf(fp, "\t\t or byte [%s],20H\t; Set Supervisor Mode\n",REG_SRH); + fprintf(fp, "\t\t mov [%s],edi\t\t; Save in USP\n",REG_USP); + fprintf(fp, "\t\t mov edi,[%s]\t\t; Get ISP\n",REG_ISP); + + /* Write SR first (since it's in a register) */ + + fprintf(fp, "ExSuperMode:\n"); + fprintf(fp, "\t\t sub edi,byte 6\n"); + fprintf(fp, "\t\t mov [%s],edi\t\t; Put in A7\n",REG_A7); + Memory_Write('W',EDI,EAX,"----S-B",2); + + /* Then write PC */ + + fprintf(fp, "\t\t add edi,byte 2\n"); + Memory_Write('L',EDI,ESI,"------B",0); + + /* Get new PC */ + + fprintf(fp, "\t\t pop eax\t\t;Level\n"); + fprintf(fp, "\t\t shl eax,2\n"); + fprintf(fp, "\t\t add eax,[%s]\n",REG_VBR); /* 68010+ Vector Base */ + + /* Direct Read */ + + Memory_Read('L',EAX,"------B",0); + + fprintf(fp, "\t\t mov esi,eax\t\t;Set PC\n"); + fprintf(fp, "\t\t pop edx\t\t; Restore flags\n"); + + /* Sort out any bank changes */ + MemoryBanking(1); + + fprintf(fp, "\t\t ret\n"); +} + +void CodeSegmentEnd(void) +{ +#ifdef OS2 + fprintf(fp, "\t\t SECTION maindata USE32 FLAT CLASS=DATA\n\n"); +#else + fprintf(fp, "\t\t SECTION .data\n"); +#endif + + fprintf(fp, "\n\t\t align 16\n"); + fprintf(fp, "%s_ICount\n",CPUtype); + fprintf(fp, "asm_count\t DD 0\n\n"); + + /* Memory structure for 68000 registers */ + /* Same layout as structure in CPUDEFS.H */ + + fprintf(fp, "\n\n; Register Structure\n\n"); + fprintf(fp, "%s_regs\n",CPUtype); + + fprintf(fp, "R_D0\t DD 0\t\t\t ; Data Registers\n"); + fprintf(fp, "R_D1\t DD 0\n"); + fprintf(fp, "R_D2\t DD 0\n"); + fprintf(fp, "R_D3\t DD 0\n"); + fprintf(fp, "R_D4\t DD 0\n"); + fprintf(fp, "R_D5\t DD 0\n"); + fprintf(fp, "R_D6\t DD 0\n"); + fprintf(fp, "R_D7\t DD 0\n\n"); + + fprintf(fp, "R_A0\t DD 0\t\t\t ; Address Registers\n"); + fprintf(fp, "R_A1\t DD 0\n"); + fprintf(fp, "R_A2\t DD 0\n"); + fprintf(fp, "R_A3\t DD 0\n"); + fprintf(fp, "R_A4\t DD 0\n"); + fprintf(fp, "R_A5\t DD 0\n"); + fprintf(fp, "R_A6\t DD 0\n"); + fprintf(fp, "R_A7\t DD 0\n\n"); + + fprintf(fp, "R_ISP\t DD 0\t\t\t ; Supervisor Stack\n"); + fprintf(fp, "R_SR_H\t DD 0\t\t\t ; Status Register High TuSuuIII\n"); + fprintf(fp, "R_CCR\t DD 0\t\t\t ; CCR Register in Intel Format\n"); + fprintf(fp, "R_XC\t DD 0\t\t\t ; Extended Carry uuuuuuuX\n"); + + fprintf(fp, "R_PC\t DD 0\t\t\t ; Program Counter\n"); + fprintf(fp, "R_IRQ\t DD 0\t\t\t ; IRQ Request Level\n\n"); + fprintf(fp, "R_SR\t DD 0\t\t\t ; Motorola Format SR\n\n"); + + fprintf(fp, "R_IRQ_CALLBACK\t DD 0\t\t\t ; irq callback (get vector)\n\n"); + + fprintf(fp, "R_PPC\t DD 0\t\t\t ; Previous Program Counter\n"); + + fprintf(fp, "R_RESET_CALLBACK\t DD 0\t\t\t ; Reset Callback\n"); + + fprintf(fp, "R_SFC\t DD 0\t\t\t ; Source Function Call\n"); + fprintf(fp, "R_DFC\t DD 0\t\t\t ; Destination Function Call\n"); + fprintf(fp, "R_USP\t DD 0\t\t\t ; User Stack\n"); + fprintf(fp, "R_VBR\t DD 0\t\t\t ; Vector Base\n"); + + fprintf(fp, "asmbank\t DD 0\n\n"); + fprintf(fp, "CPUversion\t DD 0\n\n"); + fprintf(fp, "FullPC\t DD 0\n\n"); + + /* Extra space for variables mame uses for debugger */ + + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n\n"); + + /* Safe Memory Locations */ + + fprintf(fp, "\t\t ALIGN 16\n"); + + fprintf(fp, "\n\nIntelFlag\t\t\t\t; Intel Flag Lookup Table\n"); + fprintf(fp, "\t\t DD 0000h,0001h,0800h,0801h,0040h,0041h,0840h,0841h\n"); + fprintf(fp, "\t\t DD 0080h,0081h,0880h,0881h,00C0h,00C1h,08C0h,08C1h\n"); + fprintf(fp, "\t\t DD 0100h,0101h,0900h,0901h,0140h,0141h,0940h,0941h\n"); + fprintf(fp, "\t\t DD 0180h,0181h,0980h,0981h,01C0h,01C1h,09C0h,09C1h\n"); + +#if 0 + fprintf(fp, "\n\nImmTable\n"); + fprintf(fp, "\t\t DD 8,1,2,3,4,5,6,7\n\n"); +#endif + + + + /* Exception Timing Table */ + + fprintf(fp, "exception_cycles\n"); + fprintf(fp, "\t\t DB 0, 0, 0, 0, 38, 42, 44, 38, 38, 0, 38, 38, 0, 0, 0, 0\n"); + fprintf(fp, "\t\t DB 0, 0, 0, 0, 0, 0, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46\n"); + fprintf(fp, "\t\t DB 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38\n\n"); + + fprintf(fp, "; RLE Compressed Jump Table\n\n"); + + fprintf(fp, "%s_COMPTABLE\n\n", CPUtype); + + fprintf(fp, "%cinclude '%s'\n\n",'%', comptab); + + fprintf(fp, "\t\tDW 0,0,0\n\n"); + + +/* If Win32, put the table area in .data section (Kenjo) */ + +#ifdef WIN32 + + fprintf(fp, "%s_OPCODETABLE\tTIMES 65536 DD 0\n\n", CPUtype); + +#else + +#ifdef OS2 + fprintf(fp, "\t\t SECTION tempdata USE32 FLAT CLASS=BSS\n\n"); +#else + fprintf(fp, "\t\t SECTION .bss\n"); +#endif + + fprintf(fp, "%s_OPCODETABLE\tRESD 65536\n\n", CPUtype); + +#endif + +} + +void EmitCode(void) +{ + CodeSegmentBegin(); + + /* Instructions */ + + moveinstructions(); /* 1000 to 3FFF MOVE.X */ + immediate(); /* 0### XXX.I */ + bitdynamic(); /* 0### dynamic bit operations */ + movep(); /* 0### Move Peripheral */ + bitstatic(); /* 08## static bit operations */ + LoadEffectiveAddress(); /* 4### */ + PushEffectiveAddress(); /* ???? */ + movesr(); /* 4#C# */ + opcode5(); /* 5000 to 5FFF ADDQ,SUBQ,Scc and DBcc */ + branchinstructions(); /* 6000 to 6FFF Bcc,BSR */ + moveq(); /* 7000 to 7FFF MOVEQ */ + abcd_sbcd(); /* 8### Decimal Add/Sub */ + typelogicalmath(); /* Various ranges */ + addx_subx(); + divides(); + swap(); + not(); /* also neg negx clr */ + moveusp(); + chk(); + exg(); + cmpm(); + mul(); + ReturnandRestore(); + rts(); + jmp_jsr(); + nbcd(); + tas(); + trap(); + trapv(); + reset(); + nop(); + stop(); + ext(); + ReturnFromException(); + tst(); + movem_reg_ea(); + movem_ea_reg(); + link(); + unlinkasm(); + asl_asr(); /* E### Shift Commands */ + asl_asr_ea(); + roxl_roxr(); + roxl_roxr_ea(); + lsl_lsr(); + lsl_lsr_ea(); + rol_ror(); + rol_ror_ea(); + LineA(); /* A000 to AFFF Line A */ + LineF(); /* F000 to FFFF Line F */ + illegal_opcode(); + + ReturnandDeallocate(); /* 68010 Commands */ + MoveControlRegister(); + MoveAddressSpace(); + + if(CPU==2) /* 68020 Commands */ + { + divl(); + mull(); + bfext(); + } + + CodeSegmentEnd(); +} + +int main(int argc, char **argv) +{ + int dwLoop; + + printf("\nMake68K - V%s - Copyright 1998, Mike Coates (mame@btinternet.com)\n", VERSION); + printf(" 1999, & Darren Olafson (deo@mail.island.net)\n"); + printf(" 2000\n"); + + if (argc != 4 && argc != 5) + { + printf("Usage: %s outfile jumptable-outfile type [ppro]\n", argv[0]); + exit(1); + } + + printf("Building 680%s 2001\n\n",argv[3]); + + for (dwLoop=0;dwLoop<65536;) OpcodeArray[dwLoop++] = -2; + + codebuf=malloc(64); + if (!codebuf) + { + printf ("Memory allocation error\n"); + exit(3); + } + + /* Emit the code */ + fp = fopen(argv[1], "w"); + if (!fp) + { + fprintf(stderr, "Can't open %s for writing\n", argv[1]); + exit(1); + } + + comptab = argv[2]; + + + CPUtype = malloc(64); +#ifdef OS2 + sprintf(CPUtype,"M680%s",argv[3]); +#else + sprintf(CPUtype,"_M680%s",argv[3]); +#endif + + if(argv[3][0]=='2') CPU = 2; + if(argc > 4 && !stricmp(argv[4], "ppro")) + { + ppro = 1; + printf("Generating ppro opcodes\n"); + } + + EmitCode(); + + fclose(fp); + + printf("\n%d Unique Opcodes\n",Opcount); + + /* output Jump table to separate file */ + fp = fopen(argv[2], "w"); + if (!fp) + { + fprintf(stderr, "Can't open %s for writing\n", argv[2]); + exit(1); + } + + JumpTable(); + + fclose(fp); + + exit(0); +}