mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 07:17:45 -04:00
8192 lines
189 KiB
C
8192 lines
189 KiB
C
/*---------------------------------------------------------------
|
|
* 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
/* 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<Start+0x1000;Opcode++)
|
|
{
|
|
/* Mask our Registers */
|
|
|
|
BaseCode = Opcode & (Start + 0x1f8);
|
|
|
|
/* Unless Mode = 7 */
|
|
|
|
if ((BaseCode & 0x38) == 0x38) BaseCode |= (Opcode & 7);
|
|
if ((BaseCode & 0x1c0) == 0x1c0) BaseCode |= (Opcode & 0xE00);
|
|
|
|
/* If mode = 3 or 4 and Size = byte and register = A7 */
|
|
/* then make it a separate code */
|
|
|
|
#ifdef A7ROUTINE
|
|
if (Size == 'B')
|
|
{
|
|
if (((Opcode & 0x3F) == 0x1F) || ((Opcode & 0x3F) == 0x27))
|
|
{
|
|
BaseCode |= 0x07;
|
|
}
|
|
|
|
if (((Opcode & 0xFC0) == 0xEC0) || ((Opcode & 0xFC0) == 0xF00))
|
|
{
|
|
BaseCode |= 0x0E00;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* If Source = Data or Address register - combine into same routine */
|
|
|
|
if (((Opcode & 0x38) == 0x08) && (allowfrom[1]))
|
|
{
|
|
BaseCode &= 0xfff7;
|
|
}
|
|
|
|
if (OpcodeArray[BaseCode] == -2)
|
|
{
|
|
Src = EAtoAMN(Opcode, FALSE);
|
|
Dest = EAtoAMN(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);
|
|
}
|