Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1528 lines
41 KiB

/* Intermediate 68000 Assembly Language Builder Functions
This file contains the functions necessary to build the intermediate 68000
assembly language instructions from a 68000 instruction stream.
The public function is
unsigned CbBuildIasm(piasm, pc, pbInstr)
This function builds an intermediate 68000 assembly language
instruction from the bytes starting at pbInstr assuming that pc is the
program counter.
piasm pointer to the IASM structure being built
pc starting virtual program counter
pbInstr pointer to the instruction stream
returns the number of bytes read to construct the IASM structure
*/
#include <stdio.h>
#include "iasm68.h"
#include "opd.h"
// This macro retrieves cbits bits from the word w starting at the position lsb
#define GETBITS(w, cbits, lsb) \
((unsigned short)((w) & ~((short)0x8000 >> (15 - cbits)) << lsb) >> lsb)
// Internal constants
#define FALSE 0
#define TRUE (!FALSE)
#define iopEXTW 0
#define iopEXTL 1
#define iopEXTB 2
#define iopSWAP 3
#define iopUNLK 4
#define grpopTOCCR 0
#define grpopFROMCCR 1
#define grpopTOSR 2
#define grpopFROMSR 3
#define opONEOPERBASE opJMP
#define opSHROBASE opASR
#define opBITBASE opBTST
#define opFPBASE opFMOVE
// Prototypes for internal functions
unsigned short WFetch(void);
void SetIasmHeader(IASM *, unsigned, unsigned, unsigned);
void SetEa(OPER *, unsigned, unsigned, unsigned);
void SetEaImmed(OPER *, unsigned, long);
void SetEaLabel(OPER *, long);
void SetEaRegPair(OPER *, unsigned, unsigned, unsigned);
unsigned short WReverse(unsigned short);
// Prototypes for builder functions
void BuildMove(IASM *, unsigned short, unsigned short);
void BuildMovea(IASM *, unsigned short, unsigned short);
void BuildBranch(IASM *, unsigned short, unsigned short);
void BuildDbcc(IASM *, unsigned short, unsigned short);
void BuildScc(IASM *, unsigned short, unsigned short);
void BuildBitOp(IASM *, unsigned short, unsigned short);
void BuildMovep(IASM *, unsigned short, unsigned short);
void BuildOpmode(IASM *, unsigned short, unsigned short);
void BuildOpmodeA(IASM *, unsigned short, unsigned short);
void BuildShroOp(IASM *, unsigned short, unsigned short);
void BuildImmed(IASM *, unsigned short, unsigned short) ;
void BuildMoveUSP(IASM *, unsigned short, unsigned short);
void BuildReg(IASM *, unsigned short, unsigned short);
void BuildExtend(IASM *, unsigned short, unsigned short);
void BuildLink(IASM *, unsigned short, unsigned short);
void BuildTrap(IASM *, unsigned short, unsigned short);
void BuildToolbox(IASM *, unsigned short, unsigned short);
void BuildSreg(IASM *, unsigned short, unsigned short);
void BuildOneOper(IASM *, unsigned short, unsigned short);
void BuildMovem(IASM *, unsigned short, unsigned short);
void BuildChk(IASM *, unsigned short, unsigned short);
void BuildOneOperS(IASM *, unsigned short, unsigned short);
void BuildQuick(IASM *, unsigned short, unsigned short);
void BuildMoveq(IASM *, unsigned short, unsigned short);
void BuildNoOper(IASM *, unsigned short, unsigned short);
void BuildWExt(IASM *, unsigned short, unsigned short);
void BuildFP(IASM *, unsigned short, unsigned short);
void BuildFDbcc(IASM *, unsigned short, unsigned short);
void BuildFTrapcc(IASM *, unsigned short, unsigned short);
void BuildFScc(IASM *, unsigned short, unsigned short);
void BuildFBcc(IASM *, unsigned short, unsigned short);
void BuildFNop(IASM *, unsigned short, unsigned short);
void BuildFMoveFPcr(IASM *, unsigned short, unsigned short);
void BuildFMovem(IASM *, unsigned short, unsigned short);
void BuildLongMath(IASM *, unsigned short, unsigned short);
#ifdef TRAP_NAMES
int ItrpdFromTrp(unsigned short trp);
#endif
// Global data
unsigned long pc; // Current program counter
unsigned long pcInit; // Initial program counter
const unsigned char *pb; // Current position in the instruction stream
// Opcode descriptor table
const OPD rgopd[] = { // order is important below
0xFF00, 0x0000, BuildImmed, opORI, // 0000 0000 xxxx xxxx
0xFF00, 0x0200, BuildImmed, opANDI, // 0000 0010 xxxx xxxx
0xFF00, 0x0400, BuildImmed, opSUBI, // 0000 0100 xxxx xxxx
0xFF00, 0x0600, BuildImmed, opADDI, // 0000 0110 xxxx xxxx
0xFF00, 0x0800, BuildBitOp, 0, // 0000 1000 xxxx xxxx
0xFF00, 0x0A00, BuildImmed, opEORI, // 0000 1010 xxxx xxxx
0xFF00, 0x0C00, BuildImmed, opCMPI, // 0000 1100 xxxx xxxx
0xF138, 0x0108, BuildMovep, 0, // 0000 xxx1 xx00 1xxx
0xF100, 0x0100, BuildBitOp, 0, // 0000 xxx1 xxxx xxxx
0xF000, 0x1000, BuildMove, sizeBYTE, // 0001 xxxx xxxx xxxx
0xF1C0, 0x2040, BuildMovea, sizeLONG, // 0010 xxx0 01xx xxxx
0xF000, 0x2000, BuildMove, sizeLONG, // 0010 xxxx xxxx xxxx
0xF1C0, 0x3040, BuildMovea, sizeWORD, // 0011 xxx0 01xx xxxx
0xF000, 0x3000, BuildMove, sizeWORD, // 0011 xxxx xxxx xxxx
0xFFC0, 0x40C0, BuildSreg, grpopFROMSR, // 0100 0000 11xx xxxx
0xFF00, 0x4000, BuildOneOperS, opNEGX, // 0100 0000 xxxx xxxx
0xFFC0, 0x42C0, BuildSreg, grpopFROMCCR, // 0100 0010 11xx xxxx
0xFF00, 0x4200, BuildOneOperS, opCLR, // 0100 0010 xxxx xxxx
0xFFC0, 0x44C0, BuildSreg, grpopTOCCR, // 0100 0100 11xx xxxx
0xFF00, 0x4400, BuildOneOperS, opNEG, // 0100 0100 xxxx xxxx
0xFFC0, 0x46C0, BuildSreg, grpopTOSR, // 0100 0110 11xx xxxx
0xFF00, 0x4600, BuildOneOperS, opNOT, // 0100 0110 xxxx xxxx
0xFFC0, 0x4800, BuildOneOper, opNBCD, // 0100 1000 00xx xxxx
0xFFF8, 0x4840, BuildReg, iopSWAP, // 0100 1000 0100 0xxx
0xFFC0, 0x4840, BuildOneOper, opPEA, // 0100 1000 01xx xxxx
0xFFF8, 0x4880, BuildReg, iopEXTW, // 0100 1000 1000 0xxx
0xFFF8, 0x48C0, BuildReg, iopEXTL, // 0100 1000 1100 0xxx
0xFFF8, 0x49C0, BuildReg, iopEXTB, // 0100 1001 1100 0xxx
0xFB80, 0x4880, BuildMovem, 0, // 0100 1x00 1xxx xxxx
0xFFFF, 0x4AFC, BuildNoOper, opILLEGAL, // 0100 1010 1111 1100
0xFFC0, 0x4AC0, BuildOneOper, opTAS, // 0100 1010 11xx xxxx
0xFF00, 0x4A00, BuildOneOperS, opTST, // 0100 1010 xxxx xxxx
0xFF80, 0x4C00, BuildLongMath, 0, // 0100 1100 0xxx xxxx
0xFFF0, 0x4E40, BuildTrap, 0, // 0100 1110 0100 xxxx
0xFFF8, 0x4E50, BuildLink, 0, // 0100 1110 0101 0xxx
0xFFF8, 0x4E58, BuildReg, iopUNLK, // 0100 1110 0101 1xxx
0xFFF0, 0x4E60, BuildMoveUSP, 0, // 0100 1110 0110 xxxx
0xFFFF, 0x4E70, BuildNoOper, opRESET, // 0100 1110 0111 0000
0xFFFF, 0x4E71, BuildNoOper, opNOP, // 0100 1110 0111 0001
0xFFFF, 0x4E72, BuildWExt, opSTOP, // 0100 1110 0111 0010
0xFFFF, 0x4E73, BuildNoOper, opRTE, // 0100 1110 0111 0011
0xFFFF, 0x4E74, BuildWExt, opRTD, // 0100 1110 0111 0100
0xFFFF, 0x4E75, BuildNoOper, opRTS, // 0100 1110 0111 0101
0xFFFF, 0x4E76, BuildNoOper, opTRAPV, // 0100 1110 0111 0110
0xFFFF, 0x4E77, BuildNoOper, opRTR, // 0100 1110 0111 0111
0xFFC0, 0x4E80, BuildOneOper, opJSR, // 0100 1110 10xx xxxx
0xFFC0, 0x4EC0, BuildOneOper, opJMP, // 0100 1110 11xx xxxx
0xF1C0, 0x4180, BuildChk, opCHK, // 0100 xxx1 10xx xxxx
0xF1C0, 0x41C0, BuildChk, opLEA, // 0100 xxx1 11xx xxxx
0xF0F8, 0x50C8, BuildDbcc, 0, // 0101 xxxx 1100 1xxx
0xF0C0, 0x50C0, BuildScc, 0, // 0101 xxxx 11xx xxxx
0xF100, 0x5000, BuildQuick, opADDQ, // 0101 xxx0 xxxx xxxx
0xF100, 0x5100, BuildQuick, opSUBQ, // 0101 xxx1 xxxx xxxx
0xF000, 0x6000, BuildBranch, 0, // 0110 xxxx xxxx xxxx
0xF000, 0x7000, BuildMoveq, 0, // 0111 xxxx xxxx xxxx
0xF1C0, 0x80C0, BuildChk, opDIVU, // 1000 xxx0 11xx xxxx
0xF1C0, 0x81C0, BuildChk, opDIVS, // 1000 xxx1 11xx xxxx
0xF1F0, 0x8100, BuildExtend, opSBCD, // 1000 xxx1 0000 xxxx
0xF000, 0x8000, BuildOpmode, opOR, // 1000 xxxx xxxx xxxx
0xF1F0, 0x91C0, BuildOpmodeA, opSUBA, // 1001 xxx1 1100 xxxx
0xF130, 0x9100, BuildExtend, opSUBX, // 1001 xxx1 xx00 xxxx
0xF0C0, 0x90C0, BuildOpmodeA, opSUBA, // 1001 xxxx 11xx xxxx
0xF000, 0x9000, BuildOpmode, opSUB, // 1001 xxxx xxxx xxxx
0xF000, 0xa000, BuildToolbox, 0, // 1010 xxxx xxxx xxxx
/* This next OPD entry is unusual; it is designed to catch the CMPA
instructions that might otherwise look like CMPM instructions. */
0xF1F8, 0xB1C8, BuildOpmodeA, opCMPA, // 1011 xxx1 1100 1xxx
0xF138, 0xB108, BuildExtend, opCMPM, // 1011 xxx1 xx00 1xxx
0xF0C0, 0xB0C0, BuildOpmodeA, opCMPA, // 1011 xxxx 11xx xxxx
0xF100, 0xB000, BuildOpmode, opCMP, // 1011 xxx0 xxxx xxxx
0xF100, 0xB100, BuildOpmode, opEOR, // 1011 xxx1 xxxx xxxx
0xF1C0, 0xC0C0, BuildChk, opMULU, // 1100 xxx0 11xx xxxx
0xF1F0, 0xC100, BuildExtend, opABCD, // 1100 xxx1 0000 xxxx
0xF1F8, 0xC140, BuildExtend, opEXG, // 1100 xxx1 0100 0xxx
0xF1F8, 0xC148, BuildExtend, opEXG, // 1100 xxx1 0100 1xxx
0xF1F8, 0xC188, BuildExtend, opEXG, // 1100 xxx1 1000 1xxx
0xF1C0, 0xC1C0, BuildChk, opMULS, // 1100 xxx1 11xx xxxx
0xF000, 0xC000, BuildOpmode, opAND, // 1100 xxxx xxxx xxxx
0xF1F0, 0xD1C0, BuildOpmodeA, opADDA, // 1101 xxx1 1100 xxxx
0xF130, 0xD100, BuildExtend, opADDX, // 1101 xxx1 xx00 xxxx
0xF0C0, 0xD0C0, BuildOpmodeA, opADDA, // 1101 xxxx 11xx xxxx
0xF000, 0xD000, BuildOpmode, opADD, // 1101 xxxx xxxx xxxx
0xF000, 0xE000, BuildShroOp, 0, // 1110 xxxx xxxx xxxx
0xFFC0, 0xF200, BuildFP, 0, // 1111 0010 00xx xxxx
0xFFF8, 0xF248, BuildFDbcc, 0, // 1111 0010 0100 1xxx
0xFFF8, 0xF278, BuildFTrapcc, 0, // 1111 0010 0111 1xxx
0xFFC0, 0xF240, BuildFScc, 0, // 1111 0010 01xx xxxx
0xFF80, 0xF280, BuildFBcc, 0, // 1111 0010 1xxx xxxx
0xFFC0, 0xF300, BuildOneOper, opFSAVE, // 1111 0011 00xx xxxx
0xFFC0, 0xF340, BuildOneOper, opFRESTORE // 1111 0011 01xx xxxx
};
const unsigned copd = sizeof(rgopd) / sizeof(OPD);
unsigned
CbBuildIasm(
IASM *piasm,
unsigned long pcStart,
const unsigned char *pbStart)
{
/* This function builds an intermediate 68000 assembly language instruction
from the bytes starting at pbStart assuming that pcStart is the starting
program counter. The number of bytes used to construct the instruction is
returned. */
const OPD *popd;
const OPD *popdEnd;
unsigned short wInstr;
/* Save the starting location and program counter in global variables so
that the builder functions can access them if need be. */
pcInit = pc = pcStart;
pb = pbStart;
/* Read the first word from memory. */
wInstr = WFetch();
/* Attempt to match the bit pattern in the word read to valid 68000
instruction bit patterns. */
for (popd = &rgopd[0], popdEnd = &rgopd[sizeof(rgopd) / sizeof(OPD)];
popd != popdEnd; popd++) {
/* If we have identified this instruction, call the builder function
and return the number of bytes read. */
if ((wInstr & popd->mask) == popd->match) {
(*popd->pfn)(piasm, wInstr, popd->arg);
return (unsigned)(pb - pbStart);
}
}
/* We have been unable to identify this instruction. Mark it as a NULL
instruction and return. */
SetIasmHeader(piasm, opNULL, 0, sizeNULL);
return 2;
}
unsigned short
WFetch()
{
/* This function reads a word out of memory in big-endian format (high-byte
first). */
unsigned short w;
w = (unsigned short)(*pb++ << 8);
w |= (unsigned short)(*pb++);
/* Update the virtual program counter. */
pc += 2L;
return w;
}
void
SetIasmHeader(
IASM *piasm,
unsigned op,
unsigned coper,
unsigned size)
{
/* This function sets the header of the intermediate 68000 assembly language
instruction. */
piasm->op = op;
piasm->coper = coper;
piasm->size = size;
}
void
SetEa(
OPER *poper,
unsigned mode,
unsigned reg,
unsigned size)
{
/* This functions sets the effective addressing mode of the specified
operand based on the addressing mode, the register, and the size of the
operation. This function will read words from the instruction stream if it
is necessary to compute the effective addressing mode. */
unsigned short wExt;
#if 0
unsigned short *pw;
#endif
/* If the mode is not one of the special modes, then the mode is the
effective addressing mode and the register is the register we will use in
calculating the operand. */
if (mode != modeSPECIAL) {
poper->ea = mode;
poper->reg = reg;
/* If the register is a valid special register to use with the special
mode, then the effective addressing mode is the sum of the mode and the
special register. */
} else if (reg < regMAX) {
poper->ea = mode + reg;
/* If this is an immediate value, we must add in the size of the value.
*/
if (reg == regIMMED) {
poper->ea += size;
}
/* Otherwise, we do not recognize this effective addressing. */
} else {
poper->ea = eaNULL;
}
/* Initial the displacement so we can cleverly combine the effective
addressing modes (see fall throughs). */
poper->disp = 0L;
/* Is there and extension word associated with this effective addressing? */
switch (poper->ea) {
case eaPCDISP:
/* Save the program counter. */
poper->val.pc = pcInit;
poper->disp = pc - pcInit;
/* Fall through */
case eaDISP:
/* This extenstion word is the displacement. */
poper->disp += (long)(short)WFetch();
poper->szLabel = (char *)NULL;
break;
case eaPCINDEX:
/* Save the program counter. */
poper->val.pc = pcInit;
poper->disp = pc - pcInit;
/* Fall through */
case eaINDEX:
/* The extension word describes the index register. */
wExt = WFetch();
poper->fARegIndex = GETBITS(wExt, 1, 15);
poper->reg2 = GETBITS(wExt, 3, 12);
poper->fLongIndex = GETBITS(wExt, 1, 11);
// REVIEW: Special casing 32-bit displacment addressing. Need to have
// general support for all 68020 addressing modes.
if (GETBITS(wExt, 11, 0) == 0x170) {
poper->ea = poper->ea == eaINDEX ? eaDISP : eaPCDISP;
wExt = WFetch();
poper->disp += (long)(((long)wExt << 16) | (unsigned long)WFetch());
} else {
poper->disp += (long)(char)GETBITS(wExt, 8, 0);
}
poper->szLabel = (char *)NULL;
break;
case eaSHORTADDR:
case eaWORDIMMED:
/* The extenstion word is an immediate word value. */
poper->val.w = WFetch();
break;
case eaBYTEIMMED:
/* The extenstion word is an immediate byte value. */
poper->val.b = (char)GETBITS(WFetch(), 8, 0);
break;
case eaLONGADDR:
case eaLONGIMMED:
/* The extenstion words are an immediate long value. Convert them to
big-endian format (high-order word first). */
wExt = WFetch();
poper->val.l = (long)(((long)wExt << 16) | (unsigned long)WFetch());
break;
#if 0
case eaSINGLEIMMED:
/* The extenstion words are an immediate single precision value. */
pw = (unsigned short *)&poper->val.s;
*pw++ = WFetch();
*pw = WFetch();
break;
case eaDOUBLEIMMED:
/* The extenstion words are an immediate double precision value. */
pw = (unsigned short *)&poper->val.d;
*pw++ = WFetch();
*pw++ = WFetch();
*pw++ = WFetch();
*pw = WFetch();
break;
case eaEXTENDEDIMMED:
/* The extenstion words are an immediate extended precision value. */
pw = (unsigned short *)&poper->val.d;
*pw++ = WFetch();
WFetch(); // Skip the zero word in the 68k format
*pw++ = WFetch();
*pw++ = WFetch();
*pw++ = WFetch();
*pw = WFetch();
break;
#endif
}
}
void
SetEaImmed(
OPER *poper,
unsigned ea,
long val)
{
/* This function sets the effective addressing mode of an operand when the
mode is an immediate mode and the value is already known (i.e. not read from
the instruction stream). */
switch (poper->ea = ea) {
case eaBYTEIMMED:
poper->val.b = (char)val;
break;
case eaWORDIMMED:
poper->val.w = (short)val;
break;
case eaLONGIMMED:
poper->val.l = val;
break;
case eaREGLIST:
poper->val.rl = val;
break;
}
}
void
SetEaLabel(
OPER *poper,
long disp)
{
/* This function sets the effective addressing mode of an operand to that
of a label. */
poper->ea = eaLABEL;
poper->val.pc = pcInit;
poper->disp = disp;
poper->szLabel = (char *)NULL;
}
void
SetEaRegPair(
OPER *poper,
unsigned ea,
unsigned reg1,
unsigned reg2)
{
/* This function sets the effective addressing mode of an operand to that
of a register pair. */
poper->ea = ea;
poper->reg = reg1;
poper->reg2 = reg2;
}
unsigned short
WReverse(
unsigned short w)
{
static const unsigned short rgrev[] = {
0x0, /* 0000b => 0000b */
0x8, /* 0001b => 1000b */
0x4, /* 0010b => 0100b */
0xC, /* 0011b => 1100b */
0x2, /* 0100b => 0010b */
0xA, /* 0101b => 1010b */
0x6, /* 0110b => 0110b */
0xE, /* 0111b => 1110b */
0x1, /* 1000b => 0001b */
0x9, /* 1001b => 1001b */
0x5, /* 1010b => 0101b */
0xD, /* 1011b => 1101b */
0x3, /* 1100b => 0011b */
0xB, /* 1101b => 1011b */
0x7, /* 1110b => 0111b */
0xF /* 1111b => 1111b */
};
unsigned short wrev;
int shift;
/* Reverse the bits in the word nibble by nibble. */
for (wrev = 0, shift = 12; w != 0; w >>= 4, shift -= 4) {
wrev |= rgrev[w & 0x000F] << shift;
}
return wrev;
}
void
BuildMove(
IASM *piasm,
unsigned short wInstr,
unsigned short size)
{
/* This function build the intermediate 68000 assembly language instruction
for the MOVE instruction. */
SetIasmHeader(piasm, opMOVE, 2, size);
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0), size);
SetEa(&piasm->oper2, GETBITS(wInstr, 3, 6), GETBITS(wInstr, 3, 9), size);
}
void
BuildMovea(
IASM *piasm,
unsigned short wInstr,
unsigned short size)
{
/* This function build the intermediate 68000 assembly language instruction
for the MOVEA instruction. */
SetIasmHeader(piasm, opMOVEA, 2, size);
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0), size);
SetEa(&piasm->oper2, modeAREG, GETBITS(wInstr, 3, 9), size);
}
void
BuildBranch(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the BRA, BSR, and Bcc instructions. */
unsigned size;
long disp;
/* Read the displacment for the branch. */
switch (disp = (long)(char)GETBITS(wInstr, 8, 0)) {
case 0L:
size = sizeWORD;
disp = (long)(short)WFetch();
break;
case -1L:
size = sizeLONG;
disp = (long)((unsigned long)WFetch() << 16) | (unsigned long)WFetch();
break;
default:
size = sizeBYTE;
break;
}
/* Build the intermediate instruction. */
SetIasmHeader(piasm, opBcc + GETBITS(wInstr, 4, 8), 1, size);
SetEaLabel(&piasm->oper1, disp + 2L);
}
void
BuildDbcc(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the DBcc instructions. */
SetIasmHeader(piasm, opDBcc + GETBITS(wInstr, 4, 8), 2, sizeWORD);
SetEa(&piasm->oper1, modeDREG, GETBITS(wInstr, 3, 0), sizeWORD);
SetEaLabel(&piasm->oper2, (long)(short)WFetch() + 2L);
}
void
BuildScc(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the Scc instructions. */
SetIasmHeader(piasm, opScc + GETBITS(wInstr, 4, 8), 1, sizeBYTE);
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
sizeBYTE);
}
void
BuildBitOp(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the BTST, BCHG, BSET, and BCLR instructions. */
unsigned size;
/* Is this a register or immediate instruction? */
if (GETBITS(wInstr, 1, 8) != 0) {
SetEa(&piasm->oper1, modeDREG, GETBITS(wInstr, 3, 9), size = sizeLONG);
} else {
SetEa(&piasm->oper1, modeSPECIAL, regIMMED, size = sizeBYTE);
}
SetIasmHeader(piasm, opBITBASE + GETBITS(wInstr, 2, 6), 2, size);
SetEa(&piasm->oper2, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0), size);
}
void
BuildMovep(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the MOVEP instruction. */
unsigned size;
SetIasmHeader(piasm, opMOVEP, 2, size = GETBITS(wInstr, 1, 6) != 0 ?
sizeLONG : sizeWORD);
/* Is this a move to or from memory? */
if (GETBITS(wInstr, 1, 7) != 0) {
SetEa(&piasm->oper1, modeDREG, GETBITS(wInstr, 3, 9), size);
SetEa(&piasm->oper2, modeDISP, GETBITS(wInstr, 3, 0), size);
} else {
SetEa(&piasm->oper1, modeDISP, GETBITS(wInstr, 3, 0), size);
SetEa(&piasm->oper2, modeDREG, GETBITS(wInstr, 3, 9), size);
}
}
void
BuildOpmode(
IASM *piasm,
unsigned short wInstr,
unsigned short op)
{
/* This function build the intermediate 68000 assembly language instruction
for the ADD, AND, CMP, EOR, OR, and SUB instructions. */
unsigned size;
if ((size = GETBITS(wInstr, 2, 6)) == sizeNULL) {
SetIasmHeader(piasm, opNULL, 0, sizeNULL);
} else {
SetIasmHeader(piasm, op, 2, size);
/* Is the destination or source operand a register? */
if (GETBITS(wInstr, 1, 8) != 0) {
SetEa(&piasm->oper1, modeDREG, GETBITS(wInstr, 3, 9), size);
SetEa(&piasm->oper2, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
size);
} else {
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
size);
SetEa(&piasm->oper2, modeDREG, GETBITS(wInstr, 3, 9), size);
}
}
}
void
BuildOpmodeA(
IASM *piasm,
unsigned short wInstr,
unsigned short op)
{
/* This function build the intermediate 68000 assembly language instruction
for the ADDA and SUBA instructions. */
unsigned size;
SetIasmHeader(piasm, op, 2, size = GETBITS(wInstr, 1, 8) != 0 ? sizeLONG :
sizeWORD);
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0), size);
SetEa(&piasm->oper2, modeAREG, GETBITS(wInstr, 3, 9), size);
}
void
BuildShroOp(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the ASL, ASR, LSL, LSR, ROL, ROR, ROXL, and ROXR instructions. */
unsigned size;
unsigned cbits;
/* Is this instruction shifting or rotating memory on place? */
if (GETBITS(wInstr, 2, 6) == 0x3) {
SetIasmHeader(piasm, opSHROBASE + (GETBITS(wInstr, 2, 9) << 1) +
GETBITS(wInstr, 1, 8), 1, sizeWORD);
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
sizeWORD);
/* This instuction is operating on a data register. */
} else if ((size = GETBITS(wInstr, 2, 6)) == sizeNULL) {
SetIasmHeader(piasm, opNULL, 0, sizeNULL);
} else {
SetIasmHeader(piasm, opSHROBASE + (GETBITS(wInstr, 2, 3) << 1) +
GETBITS(wInstr, 1, 8), 2, size);
SetEa(&piasm->oper2, modeDREG, GETBITS(wInstr, 3, 0), size);
/* Is the count in a register? */
if (GETBITS(wInstr, 1, 5) != 0) {
SetEa(&piasm->oper1, modeDREG, GETBITS(wInstr, 3, 9), size);
/* The count is an immediate value. */
} else {
cbits = GETBITS(wInstr, 3, 9);
SetEaImmed(&piasm->oper1, eaBYTEIMMED, (long)(cbits == 0 ? 8 :
cbits));
}
}
}
void
BuildImmed(
IASM *piasm,
unsigned short wInstr,
unsigned short op)
{
/* This function build the intermediate 68000 assembly language instruction
for the ADDI, ANDI, CMPI, EORI, ORI, and SUBI instructions. */
unsigned size;
unsigned mode;
unsigned reg;
if ((size = GETBITS(wInstr, 2, 6)) == sizeNULL) {
SetIasmHeader(piasm, opNULL, 0, sizeNULL);
} else {
SetIasmHeader(piasm, op, 2, size);
SetEa(&piasm->oper1, modeSPECIAL, regIMMED, size);
/* Get the effective addressing mode and register for the second
operand. */
mode = GETBITS(wInstr, 3, 3);
reg = GETBITS(wInstr, 3, 0);
/* Is this instruction operating on a special register? */
if (mode == modeSPECIAL && reg == regIMMED) {
mode = modeSREG;
reg = size == sizeBYTE ? regCCR : regSR;
}
SetEa(&piasm->oper2, mode, reg, size);
}
}
void
BuildMoveUSP(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the MOVE USP to An and MOVE An to USP instructions. */
SetIasmHeader(piasm, opMOVE, 2, sizeLONG);
/* Is this instruction moving from the USP? */
if (GETBITS(wInstr, 1, 3) != 0) {
SetEa(&piasm->oper1, modeSREG, regUSP, sizeLONG);
SetEa(&piasm->oper2, modeAREG, GETBITS(wInstr, 3, 0), sizeLONG);
/* We must be moving to the USP. */
} else {
SetEa(&piasm->oper1, modeAREG, GETBITS(wInstr, 3, 0), sizeLONG);
SetEa(&piasm->oper2, modeSREG, regUSP, sizeLONG);
}
}
void
BuildReg(
IASM *piasm,
unsigned short wInstr,
unsigned short iop)
{
/* This function build the intermediate 68000 assembly language instruction
for the EXT, EXTB, SWAP, and UNLK instructions. */
static unsigned rgop[] = {
opEXT, opEXT, opEXTB, opSWAP, opUNLK
};
static unsigned rgsize[] = {
sizeWORD, sizeLONG, sizeLONG, sizeWORD, sizeNULL
};
static unsigned rgmode[] = {
modeDREG, modeDREG, modeDREG, modeDREG, modeAREG
};
unsigned size;
SetIasmHeader(piasm, rgop[iop], 1, size = rgsize[iop]);
SetEa(&piasm->oper1, rgmode[iop], GETBITS(wInstr, 3, 0), size);
}
void
BuildExtend(
IASM *piasm,
unsigned short wInstr,
unsigned short op)
{
/* This function build the intermediate 68000 assembly language instruction
for the ABCD, ADDX, CMPM, EXG, SBCD, and SUBX instructions. */
unsigned size;
unsigned reg1;
unsigned reg2;
/* Get the two registers used in the instruction. */
reg1 = GETBITS(wInstr, 3, 9);
reg2 = GETBITS(wInstr, 3, 0);
/* Is this an EXG instruction? */
if (op == opEXG) {
/* The size is always long. */
size = sizeLONG;
/* Is this "EXG Dn, An"? */
if (GETBITS(wInstr, 1, 7) != 0) {
SetEa(&piasm->oper1, modeDREG, reg1, sizeLONG);
SetEa(&piasm->oper2, modeAREG, reg2, sizeLONG);
/* Is this "EXG An, An"? */
} else if (GETBITS(wInstr, 1, 3) != 0) {
SetEa(&piasm->oper1, modeAREG, reg1, sizeLONG);
SetEa(&piasm->oper2, modeAREG, reg2, sizeLONG);
/* This must be "EXG Dn, Dn"? */
} else {
SetEa(&piasm->oper1, modeDREG, reg1, sizeLONG);
SetEa(&piasm->oper2, modeDREG, reg2, sizeLONG);
}
} else {
/* If bit 12 is set (ADDX, CMPM, or SUBX) then bits 6-7 indicate the
size. Otherwise (ABCD or SBCD), the size is a byte. */
if ((size = GETBITS(wInstr, 1, 12) != 0 ? GETBITS(wInstr, 2, 6) :
sizeBYTE) == sizeNULL) {
SetIasmHeader(piasm, opNULL, 0, sizeNULL);
} else {
/* Is this instruction "CMPM (An)+, (An)+"? */
if (op == opCMPM) {
SetEa(&piasm->oper1, modePOSTINC, reg2, size);
SetEa(&piasm->oper2, modePOSTINC, reg1, size);
/* Is this instruction of the form "OP -(An), -(An)"? */
} else if (GETBITS(wInstr, 1, 3) != 0) {
SetEa(&piasm->oper1, modePREDEC, reg2, size);
SetEa(&piasm->oper2, modePREDEC, reg1, size);
/* It must be of the form "OP Dn, Dn". */
} else {
SetEa(&piasm->oper1, modeDREG, reg2, size);
SetEa(&piasm->oper2, modeDREG, reg1, size);
}
}
SetIasmHeader(piasm, op, 2, size);
}
}
void
BuildLink(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the LINK instruction. */
SetIasmHeader(piasm, opLINK, 2, sizeWORD);
SetEa(&piasm->oper1, modeAREG, GETBITS(wInstr, 3, 0), sizeWORD);
SetEa(&piasm->oper2, modeSPECIAL, regIMMED, sizeWORD);
}
void
BuildTrap(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the TRAP instruction. */
SetIasmHeader(piasm, opTRAP, 1, sizeNULL);
SetEaImmed(&piasm->oper1, eaBYTEIMMED, (long)GETBITS(wInstr, 4, 0));
}
void
BuildToolbox(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the A-TRAP (Macintosh Toolbox) instruction. */
#ifdef TRAP_NAMES
SetIasmHeader(piasm, opMAX + ItrpdFromTrp(wInstr), 0, sizeNULL);
#else
SetIasmHeader(piasm, opTOOLBOX, 1, sizeNULL);
SetEaImmed(&piasm->oper1, eaLONGIMMED, (long)GETBITS(wInstr, 12, 0));
#endif
}
void
BuildSreg(
IASM *piasm,
unsigned short wInstr,
unsigned short grpop)
{
/* This function build the intermediate 68000 assembly language instruction
for the MOVE to and from the CCR and SR instructions. */
unsigned reg;
/* Are we dealing with the SR or the CCR? */
reg = GETBITS(grpop, 1, 1) != 0 ? regSR : regCCR;
SetIasmHeader(piasm, opMOVE, 2, sizeWORD);
/* Are we moving to the special register? */
if (GETBITS(grpop, 1, 0) != 0) {
SetEa(&piasm->oper1, modeSREG, reg, sizeWORD);
SetEa(&piasm->oper2, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
sizeWORD);
/* We must be moving from the special register. */
} else {
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
sizeWORD);
SetEa(&piasm->oper2, modeSREG, reg, sizeWORD);
}
}
void
BuildOneOper(
IASM *piasm,
unsigned short wInstr,
unsigned short op)
{
/* This function build the intermediate 68000 assembly language instruction
for the JMP, JSR, NBCD, PEA, TAS, FRESTORE, and FSAVE instructions. */
static unsigned rgsize[] = {
sizeNULL, sizeNULL, sizeBYTE, sizeLONG, sizeBYTE, sizeNULL, sizeNULL
};
unsigned size;
SetIasmHeader(piasm, op, 1, size = rgsize[op - opONEOPERBASE]);
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0), size);
}
void
BuildMovem(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the MOVEM instruction. */
unsigned size;
unsigned mode;
unsigned reglist;
SetIasmHeader(piasm, opMOVEM, 2, size = GETBITS(wInstr, 1, 6) != 0 ?
sizeLONG : sizeWORD);
/* The register list is read from the instruction stream and reversed if
the addressing mode is predecrement. */
mode = GETBITS(wInstr, 3, 3);
reglist = mode == modePREDEC ? WReverse(WFetch()) : WFetch();
/* Are we moving to the registers? */
if (GETBITS(wInstr, 1, 10) != 0) {
SetEa(&piasm->oper1, mode, GETBITS(wInstr, 3, 0), size);
SetEaImmed(&piasm->oper2, eaREGLIST, (long)reglist);
/* We must be moving from the registers. */
} else {
SetEaImmed(&piasm->oper1, eaREGLIST, (long)reglist);
SetEa(&piasm->oper2, mode, GETBITS(wInstr, 3, 0), size);
}
}
void
BuildChk(
IASM *piasm,
unsigned short wInstr,
unsigned short op)
{
/* This function build the intermediate 68000 assembly language instruction
for the CHK, DIVU, DIVS, LEA, MULU, and MULS instructions. */
unsigned size;
SetIasmHeader(piasm, op, 2, size = op == opLEA ? sizeLONG : sizeWORD);
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0), size);
SetEa(&piasm->oper2, op == opLEA ? modeAREG : modeDREG, GETBITS(wInstr, 3,
9), size);
}
void
BuildLongMath(
IASM *piasm,
unsigned short wInstr,
unsigned short op)
{
/* This function build the intermediate 68000 assembly language instruction
for the long MULS, MULU, DIVS, DIVU instructions. */
unsigned short wExt;
unsigned fSigned, fDouble;
unsigned destH, destL;
/* Fetch the extra instruction word */
wExt = WFetch();
/* get the destination registers */
destH = GETBITS(wExt, 3, 0);
destL = GETBITS(wExt, 3, 12);
/* get some flags */
fSigned = (GETBITS(wExt, 1, 11) != 0);
fDouble = (GETBITS(wExt, 1, 10) != 0);
/* is it a DIV ? */
if (GETBITS(wInstr, 1, 6) != 0)
{
if ((destH != destL) && !fDouble)
{
op = fSigned ? opDIVSL : opDIVUL;
}
else
{
op = fSigned ? opDIVS : opDIVU;
}
}
else
{
op = fSigned ? opMULS : opMULU;
}
SetIasmHeader(piasm, op, 2, sizeLONG);
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
sizeLONG);
if ((destH != destL) || fDouble)
{
SetEaRegPair(&piasm->oper2, modeDREGPAIR, destH, destL);
}
else
{
SetEa(&piasm->oper2, modeDREG, destL, sizeLONG);
}
}
void
BuildOneOperS(
IASM *piasm,
unsigned short wInstr,
unsigned short op)
{
/* This function build the intermediate 68000 assembly language instruction
for the CLR, NEG, NEGX, NOT, and TST instructions. */
unsigned size;
if ((size = GETBITS(wInstr, 2, 6)) == sizeNULL) {
SetIasmHeader(piasm, opNULL, 0, sizeNULL);
} else {
SetIasmHeader(piasm, op, 1, size);
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
size);
}
}
void
BuildQuick(
IASM *piasm,
unsigned short wInstr,
unsigned short op)
{
/* This function build the intermediate 68000 assembly language instruction
for the ADDQ and SUBQ instructions. */
unsigned size;
unsigned data;
if ((size = GETBITS(wInstr, 2, 6)) == sizeNULL) {
SetIasmHeader(piasm, opNULL, 0, sizeNULL);
} else {
SetIasmHeader(piasm, op, 2, size);
data = GETBITS(wInstr, 3, 9);
SetEaImmed(&piasm->oper1, eaBYTEIMMED, data == 0 ? 8 : data);
SetEa(&piasm->oper2, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
size);
}
}
void
BuildMoveq(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the MOVEQ instruction. */
SetIasmHeader(piasm, opMOVEQ, 2, sizeLONG);
SetEaImmed(&piasm->oper1, eaBYTEIMMED, (long)(char)GETBITS(wInstr, 8, 0));
SetEa(&piasm->oper2, modeDREG, GETBITS(wInstr, 3, 9), sizeLONG);
}
void
BuildNoOper(
IASM *piasm,
unsigned short wInstr,
unsigned short op)
{
/* This function build the intermediate 68000 assembly language instruction
for the ILLEGAL, NOP, RESET, RTR, RTS, and TRAPV instructions. */
SetIasmHeader(piasm, op, 0, sizeNULL);
}
void
BuildWExt(
IASM *piasm,
unsigned short wInstr,
unsigned short op)
{
/* This function build the intermediate 68000 assembly language instruction
for the STOP and RTD instructions. */
SetIasmHeader(piasm, op, 1, sizeNULL);
SetEa(&piasm->oper1, modeSPECIAL, regIMMED, sizeWORD);
}
void
BuildFP(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the majority of the floating point instructions. */
static unsigned mpbitssize[] = {
sizeLONG,
sizeSINGLE,
sizeEXTENDED,
sizePACKED,
sizeWORD,
sizeDOUBLE,
sizeBYTE,
sizePACKED
};
unsigned short wExt = WFetch();
unsigned op;
unsigned size;
/* Is this instruction an FMOVE <ea>,FPcr instruction? */
if (GETBITS(wExt, 2, 14) == 0x02) {
BuildFMoveFPcr(piasm, wInstr, wExt);
return;
}
/* Is this instruction an FMOVEM instruction? */
if (GETBITS(wExt, 2, 14) == 0x03) {
BuildFMovem(piasm, wInstr, wExt);
return;
}
/* Is this instruction "FMOVE FPn,<ea>"? */
if (GETBITS(wExt, 3, 13) == 0x03) {
SetIasmHeader(piasm, opFMOVE, 2, size = mpbitssize[GETBITS(wExt, 3,
10)]);
SetEa(&piasm->oper1, modeFREG, GETBITS(wExt, 3, 7), size);
SetEa(&piasm->oper2, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
size);
return;
}
/* Is this instruction an FMOVECR instruction? */
if (GETBITS(wInstr, 6, 0) == 0x00 && GETBITS(wExt, 6, 10) == 0x27) {
SetIasmHeader(piasm, opFMOVECR, 2, sizeEXTENDED);
SetEaImmed(&piasm->oper1, eaBYTEIMMED, (long)GETBITS(wExt, 6, 0));
SetEa(&piasm->oper2, modeFREG, GETBITS(wInstr, 3, 7), sizeEXTENDED);
return;
}
/* Is this instruction an FSINCOS instruction? */
if (GETBITS(wExt, 4, 3) == 0x06) {
op = opFSINCOS;
/* Calculate the opcode for this instruction. */
} else {
switch (op = GETBITS(wExt, 6, 0)) {
case 0x38:
/* Special case the FCMP opcode. */
op = opFCMP;
break;
case 0x3A:
/* Special case the FTST opcode. */
op = opFTST;
break;
default:
/* The floating point opcodes are ordered sequencially from
opFPBASE. */
op += opFPBASE;
break;
}
}
/* Is this instruction "FOP <ea>,FPn"? */
if (GETBITS(wExt, 1, 14) != 0) {
SetIasmHeader(piasm, op, 2, size = mpbitssize[GETBITS(wExt, 3, 10)]);
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
size);
/* Then, it must be "FOP FPm,FPn". */
} else {
SetIasmHeader(piasm, op, 2, size = sizeEXTENDED);
SetEa(&piasm->oper1, modeFREG, GETBITS(wInstr, 3, 10), sizeEXTENDED);
}
if (op == opFSINCOS) {
/* Set the destination FPc:FPs. */
SetEaRegPair(&piasm->oper2, eaFREGPAIR, GETBITS(wExt, 3, 0),
GETBITS(wExt, 3, 7));
} else {
/* Set the destination floating point register. */
SetEa(&piasm->oper2, modeFREG, GETBITS(wExt, 3, 7), size);
}
}
void
BuildFMoveFPcr(
IASM *piasm,
unsigned short wInstr,
unsigned short wExt)
{
/* This function build the intermediate 68000 assembly language instruction
for the "FMOVE FPcr,<ea>" and "FMOVE <ea>,FPcr" instructions. */
/* Set the header for this instruction. */
SetIasmHeader(piasm, opFMOVE, 2, sizeLONG);
/* Is this instruction "FMOVE <ea>,FPcr"? */
if (GETBITS(wExt, 1, 14) != 0) {
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
sizeLONG);
SetEa(&piasm->oper2, modeSREG, GETBITS(wExt, 3, 10), sizeLONG);
/* Then, it must be "FMOVE FPcr,<ea>". */
} else {
SetEa(&piasm->oper1, modeSREG, GETBITS(wExt, 3, 10), sizeLONG);
SetEa(&piasm->oper2, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
sizeLONG);
}
}
void
BuildFMovem(
IASM *piasm,
unsigned short wInstr,
unsigned short wExt)
{
/* This function build the intermediate 68000 assembly language instruction
for the FMOVEM instruction. */
unsigned size;
unsigned mode;
unsigned long reglist;
/* Determine the mode of the effective address. */
mode = GETBITS(wInstr, 3, 3);
/* Are we moving floating point control registers? */
if (GETBITS(wExt, 8, 0) == 0) {
size = sizeLONG;
reglist = (unsigned long)GETBITS(wExt, 3, 10) << 24;
/* Then we must be moving floating point registers. */
} else {
size = sizeEXTENDED;
/* The register list is read from the instruction stream and reversed if
the addressing mode is not predecrement. */
reglist = mode != modePREDEC ? WReverse(wExt) << 8 : wExt << 16;
}
/* Set the header for this instruction. */
SetIasmHeader(piasm, opFMOVEM, 2, size);
/* Are we moving from the registers? */
if (GETBITS(wInstr, 1, 13) != 0) {
SetEaImmed(&piasm->oper1, eaREGLIST, reglist);
SetEa(&piasm->oper2, mode, GETBITS(wInstr, 3, 0), sizeEXTENDED);
/* We must be moving to the registers. */
} else {
SetEa(&piasm->oper1, mode, GETBITS(wInstr, 3, 0), sizeEXTENDED);
SetEaImmed(&piasm->oper2, eaREGLIST, reglist);
}
}
void
BuildFDbcc(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the FDBcc instructions. */
unsigned short wExt = WFetch();
SetIasmHeader(piasm, opFDBcc + GETBITS(wExt, 6, 0), 2, sizeNULL);
SetEa(&piasm->oper1, modeDREG, GETBITS(wInstr, 3, 0), sizeNULL);
SetEaLabel(&piasm->oper2, (long)(short)WFetch() + 2L);
}
void
BuildFScc(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the FScc instructions. */
unsigned short wExt = WFetch();
SetIasmHeader(piasm, opFScc + GETBITS(wExt, 6, 0), 1, sizeBYTE);
SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
sizeBYTE);
}
void
BuildFTrapcc(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the FTRAPcc instructions. */
unsigned size;
/* Does the instruction have an argument? */
if ((size = GETBITS(wInstr, 3, 0) - 1) == sizeNULL) {
SetIasmHeader(piasm, opFScc + GETBITS(WFetch(), 6, 0), 0, sizeNULL);
} else if (size != sizeWORD && size != sizeLONG) {
SetIasmHeader(piasm, opNULL, 0, sizeNULL);
/* Determine what the argument is. */
} else {
SetIasmHeader(piasm, opFScc + GETBITS(WFetch(), 6, 0), 1, size);
SetEa(&piasm->oper1, modeSPECIAL, regIMMED, size);
}
}
void
BuildFBcc(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the FBcc instructions. */
unsigned size;
long disp;
/* Read the displacment for the branch. */
if (GETBITS(wInstr, 1, 6) != 0) {
size = sizeLONG;
disp = (long)((unsigned long)WFetch() << 16) | (unsigned long)WFetch();
} else {
size = sizeWORD;
disp = (long)(short)WFetch();
}
/* Build the intermediate instruction. */
SetIasmHeader(piasm, opFBcc + GETBITS(wInstr, 6, 0), 1, size);
SetEaLabel(&piasm->oper1, disp + 2L);
}
void
BuildFNop(
IASM *piasm,
unsigned short wInstr,
unsigned short wDummy)
{
/* This function build the intermediate 68000 assembly language instruction
for the FNOP instruction. */
unsigned short wExt = WFetch();
SetIasmHeader(piasm, opFNOP, 0, sizeNULL);
}
#ifdef TRAP_NAMES
#include "trpd.h"
extern TRPD rgtrpd[];
extern int ctrpd;
int
ItrpdFromTrp(
unsigned short trp)
{
int itrpdLower = 0;
int itrpdUpper = ctrpd - 1;
int itrpd;
// get rid of the option flags...
if(trp & 0x0800)
{
trp &= 0xf9ff; // toolbox trap
}
else
{
trp &= 0xf1ff; // os trap
}
// Conduct a binary search looking for the requested trap descriptor
while (itrpdLower <= itrpdUpper) {
itrpd = (itrpdLower + itrpdUpper) / 2;
if (trp < rgtrpd[itrpd].trp) {
itrpdUpper = itrpd - 1;
} else if (trp > rgtrpd[itrpd].trp) {
itrpdLower = itrpd + 1;
} else {
// The trap number was found; return the index.
return itrpd;
}
}
}
#endif