/opcode.pas
unit Opcode;
interface
type
Mnemonic = (
mADD, mADDB, mADDBI, mADDI,
mAND, mANDB, mANDBI, mANDI,
mCALL,
mCLR,
mDEC, mDECB,
mHLT,
mINC, mINCB,
mJBT, mJMCE, mJMCNE, mJMP, mJNBT, mJNZ, mJNZB, mJZ, mJZB,
mLCALL,
mLJBT, mLJMCE, mLJMCNE, mLJMP, mLJNBT, mLJNZ, mLJNZB, mLJZ, mLJZB,
mLPD, mLPDI,
mMOV, mMOVB, mMOVBI, mMOVI, mMOVP,
mNOP,
mNOT, mNOTB,
mOR, mORB, mORBI, mORI,
mSETB,
mSINTR,
mTSL,
mWID,
mXFER,
mInvalid
);
Directive = (
dEQU,
dDB, dDW, dDD, dDS,
dSTRUC,
dORG,
dEVEN,
dNAME,
dSEGMENT,
dPUBLIC,
dEXTRN,
dENDS,
dEND
);
EncRRR = (rGA, rGB, rGC, rBC, rTP, rIX, rCC, rMC);
EncBBB = (Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7);
EncPPP = (pGA, pGB, pGC, pReserved, pTP);
EncWB = (
wReserved, { Instruction has no immediate/displacement data }
wOne, { One byte of immediate/displacement data }
wTwo, { Two bytes of immediate/displacement data }
wTSL, { Special case for TSL: one byte immediate and one byte displacement }
wLocation { One or two bytes displacement dependent on the distance to the target }
);
EncAA = (Base, BaseOffset, BaseIndex, BaseIndexIncrement);
EncMM = (mGA, mGB, mGC, mPP);
EncWidth = (widByte, widWord);
OperandType = (OpUnknown, OpRegister, OpPointer, OpImmediate, OpLocation,
OpMemory, OpBit, OpWidth, OpAbsent);
OperandSet = set of OperandType;
Operand = record
case Kind: OperandType of
OpUnknown: ();
OpRegister: (reg: EncRRR);
OpPointer: (preg: EncPPP);
OpImmediate: (immed: Word);
OpLocation: (loc: Word);
OpMemory: (
aa: EncAA;
mm: EncMM;
offset: Word;
);
OpBit: (bit: EncBBB);
OpWidth: (width: EncWidth);
end;
InstructionRBP = (
rbpReg, { RbP Encodes a register (RRR) }
rbpBit, { RbP Encodes a bit position (bbb) }
rbpPtrReg, { RbP encodes a pointer register (PPP) }
rbpNone, { RbP encodes nothing (0b000) }
rbpHlt, { RbP encodes 0b001 }
rbpSintr, { RbP encodes 0b010 }
rbpJmp, { RbP encodes 0b100 }
rbpWid, { RbP encodes logical widths }
rbpXfer { RbP encodes 0b011 }
);
{ | low order byte | high order byte | }
{ | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | }
{ | R/b/P | W B | A A | W | OPCODE | MM | }
{ }
{ R/b/P = Register, Bit, or Pointer/Register Select }
{ RRR bbb PPP }
{ 000 - GA 000 - bit 0 000 - GA }
{ 001 - GB 001 - bit 1 001 - GB }
{ 010 - GC 010 - bit 2 010 - GC }
{ 011 - BC 011 - bit 3 100 - TP }
{ 100 - TP 100 - bit 4 }
{ 101 - IX 101 - bit 5 }
{ 110 - CC 110 - bit 6 }
{ 111 - MC 111 - bit 7 }
{ }
{ WB = Number of immediate/displacement value bytes (EncWB) }
{ 00 - Reserved (wReserved) }
{ 01 - 1 byte (wOne) }
{ 10 - 2 bytes (word) (wTwo) }
{ 11 - TSL instruction only (wTSL) }
{ }
{ AA = Memory Address Mode }
{ 00 - Base address only }
{ 01 - Base address + 8 bit offset }
{ 10 - Base address + index register }
{ 11 - Base address + index register, post-increment }
{ }
{ W = Memory Data Width }
{ 0 - 1 byte (widByte) }
{ 1 - 2 bytes (widWord) }
{ }
{ OPCODE = Opcode, see below }
{ }
{ MM = Base Memory Address Select }
{ 00 - GA }
{ 01 - GB }
{ 10 - GC }
{ 11 - PP }
InstructionEncoding = record
{ these parts are matched against }
m: Mnemonic;
o1: OperandType;
o2: OperandType;
o3: OperandType;
{ these parts are encoded when the above fields match }
op: Byte; { pre-shifted into the high 6-bits }
w: EncWidth;
wb: EncWB;
rbp: InstructionRBP;
end;
PInstructionEncoding = ^InstructionEncoding;
const IEnc: array[0..80] of InstructionEncoding = (
(m: mADD; o1: OpRegister; o2: OpMemory; o3: OpAbsent;
op: $A0; w: widWord; wb: wReserved; rbp: rbpReg),
(m: mADD; o1: OpMemory; o2: OpRegister; o3: OpAbsent;
op: $D0; w: widWord; wb: wReserved; rbp: rbpReg),
(m: mADDB; o1: OpRegister; o2: OpMemory; o3: OpAbsent;
op: $A0; w: widWord; wb: wReserved; rbp: rbpReg),
(m: mADDB; o1: OpMemory; o2: OpRegister; o3: OpAbsent;
op: $D0; w: widWord; wb: wReserved; rbp: rbpReg), {error in width?}
(m: mADDBI; o1: OpRegister; o2: OpImmediate; o3: OpAbsent;
op: $20; w: widByte; wb: wOne; rbp: rbpReg),
(m: mADDBI; o1: OpMemory; o2: OpImmediate; o3: OpAbsent;
op: $C0; w: widByte; wb: wOne; rbp: rbpNone),
(m: mADDI; o1: OpRegister; o2: OpImmediate; o3: OpAbsent;
op: $20; w: widWord; wb: wTwo; rbp: rbpReg),
(m: mADDI; o1: OpMemory; o2: OpImmediate; o3: OpAbsent;
op: $C0; w: widWord; wb: wTwo; rbp: rbpNone),
(m: mAND; o1: OpRegister; o2: OpMemory; o3: OpAbsent;
op: $A8; w: widWord; wb: wReserved; rbp: rbpReg),
(m: mAND; o1: OpMemory; o2: OpRegister; o3: OpAbsent;
op: $D8; w: widWord; wb: wReserved; rbp: rbpReg),
(m: mANDB; o1: OpRegister; o2: OpMemory; o3: OpAbsent;
op: $A8; w: widByte; wb: wReserved; rbp: rbpReg),
(m: mANDB; o1: OpMemory; o2: OpRegister; o3: OpAbsent;
op: $D8; w: widWord; wb: wReserved; rbp: rbpReg),
(m: mANDBI; o1: OpRegister; o2: OpImmediate; o3: OpAbsent;
op: $28; w: widByte; wb: wOne; rbp: rbpReg),
(m: mANDBI; o1: OpMemory; o2: OpImmediate; o3: OpAbsent;
op: $C8; w: widByte; wb: wOne; rbp: rbpNone),
(m: mANDI; o1: OpRegister; o2: OpImmediate; o3: OpAbsent;
op: $28; w: widWord; wb: wTwo; rbp: rbpReg),
(m: mANDI; o1: OpMemory; o2: OpImmediate; o3: OpAbsent;
op: $C8; w: widWord; wb: wTwo; rbp: rbpNone),
(m: mCALL; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $9C; w: widWord; wb: wLocation; rbp: rbpJmp),
(m: mCLR; o1: OpMemory; o2: OpBit; o3: OpAbsent;
op: $F8; w: widByte; wb: wReserved; rbp: rbpBit),
(m: mDEC; o1: OpRegister; o2: OpAbsent; o3: OpAbsent;
op: $3C; w: widByte; wb: wReserved; rbp: rbpReg),
(m: mDEC; o1: OpMemory; o2: OpAbsent; o3: OpAbsent;
op: $EC; w: widWord; wb: wReserved; rbp: rbpNone),
(m: mDECB; o1: OpMemory; o2: OpAbsent; o3: OpAbsent;
op: $EC; w: widByte; wb: wReserved; rbp: rbpNone),
(m: mHLT; o1: OpAbsent; o2: OpAbsent; o3: OpAbsent;
op: $48; w: widByte; wb: wReserved; rbp: rbpHlt),
(m: mINC; o1: OpRegister; o2: OpAbsent; o3: OpAbsent;
op: $38; w: widByte; wb: wReserved; rbp: rbpReg),
(m: mINC; o1: OpMemory; o2: OpAbsent; o3: OpAbsent;
op: $E8; w: widWord; wb: wReserved; rbp: rbpNone),
(m: mJBT; o1: OpMemory; o2: OpBit; o3: OpLocation;
op: $BC; w: widByte; wb: wLocation; rbp: rbpBit),
(m: mJMCE; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $B0; w: widByte; wb: wLocation; rbp: rbpNone),
(m: mJMCNE; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $B4; w: widByte; wb: wLocation; rbp: rbpNone),
(m: mJMP; o1: OpLocation; o2: OpAbsent; o3: OpAbsent;
op: $20; w: widByte; wb: wLocation; rbp: rbpJmp), { AUG shows w changing for 8/16-bit displacement }
(m: mJNBT; o1: OpMemory; o2: OpBit; o3: OpLocation;
op: $B8; w: widByte; wb: wLocation; rbp: rbpBit),
(m: mJNZ; o1: OpRegister; o2: OpLocation; o3: OpAbsent;
op: $40; w: widByte; wb: wLocation; rbp: rbpReg),
(m: mJNZ; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $E0; w: widWord; wb: wLocation; rbp: rbpNone),
(m: mJNZB; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $E0; w: widByte; wb: wLocation; rbp: rbpNone),
(m: mJZ; o1: OpRegister; o2: OpLocation; o3: OpAbsent;
op: $44; w: widByte; wb: wLocation; rbp: rbpReg),
(m: mJZ; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $E4; w: widWord; wb: wLocation; rbp: rbpNone),
(m: mJZB; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $E4; w: widByte; wb: wLocation; rbp: rbpNone),
(m: mLCALL; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $9C; w: widWord; wb: wTwo; rbp: rbpJmp),
(m: mLJBT; o1: OpMemory; o2: OpBit; o3: OpLocation;
op: $BC; w: widByte; wb: wTwo; rbp: rbpBit),
(m: mLJMCE; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $B0; w: widByte; wb: wTwo; rbp: rbpNone),
(m: mLJMCNE; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $B4; w: widByte; wb: wTwo; rbp: rbpNone),
(m: mLJMP; o1: OpLocation; o2: OpAbsent; o3: OpAbsent;
op: $20; w: widWord; wb: wTwo; rbp: rbpJmp), { AUG shows w changing for 8/16-bit displacement }
(m: mLJNBT; o1: OpMemory; o2: OpBit; o3: OpLocation;
op: $B8; w: widByte; wb: wTwo; rbp: rbpBit),
(m: mLJNZ; o1: OpRegister; o2: OpLocation; o3: OpAbsent;
op: $40; w: widByte; wb: wTwo; rbp: rbpReg),
(m: mLJNZ; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $E0; w: widWord; wb: wTwo; rbp: rbpNone),
(m: mLJNZB; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $E0; w: widByte; wb: wTwo; rbp: rbpNone),
(m: mLJZ; o1: OpRegister; o2: OpLocation; o3: OpAbsent;
op: $44; w: widByte; wb: wTwo; rbp: rbpReg),
(m: mLJZ; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $E4; w: widWord; wb: wTwo; rbp: rbpNone),
(m: mLJZB; o1: OpMemory; o2: OpLocation; o3: OpAbsent;
op: $E4; w: widByte; wb: wTwo; rbp: rbpNone),
(m: mLPD; o1: OpPointer; o2: OpMemory; o3: OpAbsent;
op: $88; w: widWord; wb: wReserved; rbp: rbpPtrReg),
(m: mLPDI; o1: OpPointer; o2: OpImmediate; o3: OpAbsent;
op: $08; w: widWord; wb: wTwo; rbp: rbpPtrReg),
(m: mMOV; o1: OpMemory; o2: OpRegister; o3: OpAbsent;
op: $84; w: widWord; wb: wReserved; rbp: rbpReg),
(m: mMOV; o1: OpRegister; o2: OpMemory; o3: OpAbsent;
op: $80; w: widWord; wb: wReserved; rbp: rbpReg),
(m: mMOV; o1: OpMemory; o2: OpMemory; o3: OpAbsent;
op: $90; w: widWord; wb: wReserved; rbp: rbpNone),
{ MOV M, M is encoded as a pair of instructions. Each one encodes a memory
register and optional offset. The second opcode is $CC. }
(m: mMOVB; o1: OpMemory; o2: OpRegister; o3: OpAbsent;
op: $84; w: widByte; wb: wReserved; rbp: rbpReg),
(m: mMOVB; o1: OpRegister; o2: OpMemory; o3: OpAbsent;
op: $80; w: widByte; wb: wReserved; rbp: rbpReg),
(m: mMOVB; o1: OpMemory; o2: OpMemory; o3: OpAbsent;
op: $90; w: widByte; wb: wReserved; rbp: rbpNone),
{ MOVB M, M works just like MOV with a different W field. }
(m: mMOVBI; o1: OpRegister; o2: OpImmediate; o3: OpAbsent;
op: $30; w: widByte; wb: wOne; rbp: rbpReg),
(m: mMOVBI; o1: OpMemory; o2: OpImmediate; o3: OpAbsent;
op: $4C; w: widByte; wb: wOne; rbp: rbpNone),
(m: mMOVI; o1: OpRegister; o2: OpImmediate; o3: OpAbsent;
op: $30; w: widWord; wb: wTwo; rbp: rbpReg),
(m: MMOVI; o1: OpMemory; o2: OpImmediate; o3: OpAbsent;
op: $4C; w: widWord; wb: wTwo; rbp: rbpNone),
(m: mMOVP; o1: OpMemory; o2: OpPointer; o3: OpAbsent;
op: $98; w: widWord; wb: wReserved; rbp: rbpPtrReg),
(m: mMOVP; o1: OpPointer; o2: OpMemory; o3: OpAbsent;
op: $8C; w: widWord; wb: wReserved; rbp: rbpPtrReg),
(m: mNOP; o1: OpAbsent; o2: OpAbsent; o3: OpAbsent;
op: $00; w: widByte; wb: wReserved; rbp: rbpNone),
(m: mNOT; o1: OpRegister; o2: OpAbsent; o3: OpAbsent;
op: $2C; w: widByte; wb: wReserved; rbp: rbpReg),
(m: mNOT; o1: OpMemory; o2: OpAbsent; o3: OpAbsent;
op: $DC; w: widWord; wb: wReserved; rbp: rbpNone),
(m: mNOT; o1: OpRegister; o2: OpMemory; o3: OpAbsent;
op: $AC; w: widWord; wb: wReserved; rbp: rbpReg),
(m: mNOTB; o1: OpMemory; o2: OpAbsent; o3: OpAbsent;
op: $DC; w: widByte; wb: wReserved; rbp: rbpNone),
(m: mNOTB; o1: OpRegister; o2: OpMemory; o3: OpAbsent;
op: $AC; w: widByte; wb: wReserved; rbp: rbpReg),
(m: mOR; o1: OpRegister; o2: OpMemory; o3: OpAbsent;
op: $A4; w: widWord; wb: wReserved; rbp: rbpReg),
(m: mOR; o1: OpMemory; o2: OpRegister; o3: OpAbsent;
op: $D4; w: widWord; wb: wReserved; rbp: rbpReg),
(m: mORB; o1: OpRegister; o2: OpMemory; o3: OpAbsent;
op: $A4; w: widByte; wb: wReserved; rbp: rbpReg),
(m: mORB; o1: OpMemory; o2: OpRegister; o3: OpAbsent;
op: $D4; w: widByte; wb: wReserved; rbp: rbpReg),
(m: mORBI; o1: OpRegister; o2: OpImmediate; o3: OpAbsent;
op: $24; w: widByte; wb: wOne; rbp: rbpReg),
(m: mORBI; o1: OpMemory; o2: OpImmediate; o3: OpAbsent;
op: $C4; w: widByte; wb: wOne; rbp: rbpNone),
(m: mORI; o1: OpRegister; o2: OpImmediate; o3: OpAbsent;
op: $24; w: widWord; wb: wTwo; rbp: rbpReg),
(m: mORI; o1: OpMemory; o2: OpImmediate; o3: OpAbsent;
op: $C4; w: widWord; wb: wTwo; rbp: rbpNone),
(m: mSETB; o1: OpMemory; o2: OpBit; o3: OpAbsent;
op: $F4; w: widByte; wb: wReserved; rbp: rbpBit),
(m: mSINTR; o1: OpAbsent; o2: OpAbsent; o3: OpAbsent;
op: $00; w: widByte; wb: wReserved; rbp: rbpSintr),
(m: mTSL; o1: OpMemory; o2: OpImmediate; o3: OpLocation;
op: $94; w: widByte; wb: wTSL; rbp: rbpNone),
(m: mWID; o1: OpWidth; o2: OpWidth; o3: OpAbsent;
op: $00; w: widByte; wb: wReserved; rbp: rbpWid),
(m: mXFER; o1: OpAbsent; o2: OpAbsent; o3: OpAbsent;
op: $00; w: widByte; wb: wReserved; rbp: rbpXfer),
(m: mInvalid; o1: OpAbsent; o2: OpAbsent; o3: OpAbsent;
op: $FF; w: widByte; wb: wReserved; rbp: rbpNone)
);
(const m: Mnemonic; var i, j: Integer);
implementation
(const m: Mnemonic; var i, j: Integer);
var x: Integer;
begin
for x := Low(IEnc) to High(IEnc) do
if IEnc[x].m = m then
Break;
i := x;
for x := i + 1 to High(IEnc) do
If IEnc[x].m <> m then
Break;
j := x - 1;
end;
end.