{
Этот исходный текст является частью Продвинутого векторного транслятора.
Copyright © 2017 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit GenX86;
{$MODE DELPHI,EXTENDEDSYNTAX ON}
interface
uses
Lang, Utils, TranType;
{$ASMMODE INTEL,CALLING REGISTER,INLINE ON,GOTO ON}
{$H+,I-,J-,M-,Q-,R-,T-}
type
MemoryLocation = interface;
RegisterStack = interface;
MemoryLocationTfasm = class;
TextGenerator = class;
TextGenerator64 = class;
TextGenerator_Class = class of TextGenerator;
RegistersX86 = class helper for _Object
public
{ режимы (разрядности) кода }
const MODE_NONE = 0;
const MODE_16_BIT = TranslatorType.SIZE_16_BIT;
const MODE_32_BIT = TranslatorType.SIZE_32_BIT;
const MODE_64_BIT = TranslatorType.SIZE_64_BIT;
{ GPR 8 бит }
const R0B = $00;
const R1B = $01;
const R2B = $02;
const R3B = $03;
const R4B = $04;
const R5B = $05;
const R6B = $06;
const R7B = $07;
const R8B = $08;
const R9B = $09;
const R10B = $0a;
const R11B = $0b;
const R12B = $0c;
const R13B = $0d;
const R14B = $0e;
const R15B = $0f;
{ GPR 16 бит }
const R0W = $10;
const R1W = $11;
const R2W = $12;
const R3W = $13;
const R4W = $14;
const R5W = $15;
const R6W = $16;
const R7W = $17;
const R8W = $18;
const R9W = $19;
const R10W = $1a;
const R11W = $1b;
const R12W = $1c;
const R13W = $1d;
const R14W = $1e;
const R15W = $1f;
{ GPR 32 бит }
const R0D = $20;
const R1D = $21;
const R2D = $22;
const R3D = $23;
const R4D = $24;
const R5D = $25;
const R6D = $26;
const R7D = $27;
const R8D = $28;
const R9D = $29;
const R10D = $2a;
const R11D = $2b;
const R12D = $2c;
const R13D = $2d;
const R14D = $2e;
const R15D = $2f;
{ GPR 64 бит }
const R0 = $30;
const R1 = $31;
const R2 = $32;
const R3 = $33;
const R4 = $34;
const R5 = $35;
const R6 = $36;
const R7 = $37;
const R8 = $38;
const R9 = $39;
const R10 = $3a;
const R11 = $3b;
const R12 = $3c;
const R13 = $3d;
const R14 = $3e;
const R15 = $3f;
{ MMX }
const MM0 = $40;
const MM1 = $41;
const MM2 = $42;
const MM3 = $43;
const MM4 = $44;
const MM5 = $45;
const MM6 = $46;
const MM7 = $47;
{ FPU }
const ST0 = $50;
const ST1 = $51;
const ST2 = $52;
const ST3 = $53;
const ST4 = $54;
const ST5 = $55;
const ST6 = $56;
const ST7 = $57;
{ XMM }
const XMM0 = $60;
const XMM1 = $61;
const XMM2 = $62;
const XMM3 = $63;
const XMM4 = $64;
const XMM5 = $65;
const XMM6 = $66;
const XMM7 = $67;
const XMM8 = $68;
const XMM9 = $69;
const XMM10 = $6a;
const XMM11 = $6b;
const XMM12 = $6c;
const XMM13 = $6d;
const XMM14 = $6e;
const XMM15 = $6f;
const XMM16 = $70;
const XMM17 = $71;
const XMM18 = $72;
const XMM19 = $73;
const XMM20 = $74;
const XMM21 = $75;
const XMM22 = $76;
const XMM23 = $77;
const XMM24 = $78;
const XMM25 = $79;
const XMM26 = $7a;
const XMM27 = $7b;
const XMM28 = $7c;
const XMM29 = $7d;
const XMM30 = $7e;
const XMM31 = $7f;
{ YMM }
const YMM0 = $80;
const YMM1 = $81;
const YMM2 = $82;
const YMM3 = $83;
const YMM4 = $84;
const YMM5 = $85;
const YMM6 = $86;
const YMM7 = $87;
const YMM8 = $88;
const YMM9 = $89;
const YMM10 = $8a;
const YMM11 = $8b;
const YMM12 = $8c;
const YMM13 = $8d;
const YMM14 = $8e;
const YMM15 = $8f;
const YMM16 = $90;
const YMM17 = $91;
const YMM18 = $92;
const YMM19 = $93;
const YMM20 = $94;
const YMM21 = $95;
const YMM22 = $96;
const YMM23 = $97;
const YMM24 = $98;
const YMM25 = $99;
const YMM26 = $9a;
const YMM27 = $9b;
const YMM28 = $9c;
const YMM29 = $9d;
const YMM30 = $9e;
const YMM31 = $9f;
{ ZMM }
const ZMM0 = $a0;
const ZMM1 = $a1;
const ZMM2 = $a2;
const ZMM3 = $a3;
const ZMM4 = $a4;
const ZMM5 = $a5;
const ZMM6 = $a6;
const ZMM7 = $a7;
const ZMM8 = $a8;
const ZMM9 = $a9;
const ZMM10 = $aa;
const ZMM11 = $ab;
const ZMM12 = $ac;
const ZMM13 = $ad;
const ZMM14 = $ae;
const ZMM15 = $af;
const ZMM16 = $b0;
const ZMM17 = $b1;
const ZMM18 = $b2;
const ZMM19 = $b3;
const ZMM20 = $b4;
const ZMM21 = $b5;
const ZMM22 = $b6;
const ZMM23 = $b7;
const ZMM24 = $b8;
const ZMM25 = $b9;
const ZMM26 = $ba;
const ZMM27 = $bb;
const ZMM28 = $bc;
const ZMM29 = $bd;
const ZMM30 = $be;
const ZMM31 = $bf;
{ альтернативные названия регистров }
const RAX = R0;
const RCX = R1;
const RDX = R2;
const RBX = R3;
const RSP = R4;
const RBP = R5;
const RSI = R6;
const RDI = R7;
const EAX = R0D;
const ECX = R1D;
const EDX = R2D;
const EBX = R3D;
const ESP = R4D;
const EBP = R5D;
const ESI = R6D;
const EDI = R7D;
const AX = R0W;
const CX = R1W;
const DX = R2W;
const BX = R3W;
const SP = R4W;
const BP = R5W;
const SI = R6W;
const DI = R7W;
const AL = R0B;
const CL = R1B;
const DL = R2B;
const BL = R3B;
const SPL = R4B;
const BPL = R5B;
const SIL = R6B;
const DIL = R7B;
const ST = ST0;
{ XMM subtypes (combination with XMMi, YMMi or ZMMi need) }
const XPINT = $0000; // 4 packed int
const XPLONG = $0100; // 2 packed long
const XPFLOAT = $0200; // 4 packed float
const XPDOUBLE = $0300; // 2 packed double
const XSINT = $0400; // 1 scalar int
const XSLONG = $0500; // 1 scalar long
const XSFLOAT = $0600; // 1 scalar float
const XSDOUBLE = $0700; // 1 scalar double
const XMASK = $0700;
{ memory size modifiers }
const MNONE = 0;
const MBYTE = 1;
const MWORD = 2;
const MDWORD = 4;
const MQWORD = 8;
const MTBYTE = 10;
const MSHORT = MWORD;
const MINT = MDWORD;
const MLONG = MQWORD;
const MFLOAT = MDWORD;
const MDOUBLE = MQWORD;
const MREAL = MTBYTE;
{ register-relative methods }
class function isRegisterGP(reg: int): boolean;
class function isRegisterXMM(reg: int): boolean;
class function isRegisterYMM(reg: int): boolean;
class function isRegisterZMM(reg: int): boolean;
class function isRegisterFPU(reg: int): boolean;
class function isRegisterMMX(reg: int): boolean;
class function getRegisterSize(reg: int): int;
class function getCommonRegister(reg: int): int;
end;
MemoryLocation = interface(_Interface) ['{CE5EA53F-65D8-4177-B5CD-D1252ADC30E4}']
function getRegisterSource(): int;
function memoryToString(modifier: int; displacement: int): String;
end;
RegisterStack = interface(_Interface) ['{CE5EA53F-65D8-4177-B5CD-D1252ADC30E5}']
procedure clear();
procedure pushReg(reg: int);
procedure popRegs(count: int);
procedure storeRegs(count: int; generator: TextGenerator);
procedure restoreRegs(generator: TextGenerator);
procedure restoreRegsWithoutCodeGeneration();
procedure deallocateReg(generator: TextGenerator);
procedure deallocateRegWithoutCodeGeneration();
function isUsedRegister(reg: int): boolean;
function getNextUsedGPR(regGPR: int): int;
function getNextUsedXMM(regXMM: int): int;
function getNextUsedMMX(regMMX: int): int;
function getRegAt(index: int): int;
function base(): int;
function size(): int;
function changeToGPR16bit(index: int): int;
function changeToGPR32bit(index: int): int;
function changeToGPR64bit(index: int): int;
function changeToXMM(index, xtype: int): int;
function changeToYMM(index, xtype: int): int;
function changeToZMM(index, xtype: int): int;
function allocateGPR16bit(generator: TextGenerator): int;
function allocateGPR32bit(generator: TextGenerator): int;
function allocateGPR64bit(generator: TextGenerator): int;
function allocateGPRForArray(generator: TextGenerator): int;
function allocateGPRForIndex(generator: TextGenerator): int;
function allocateGPRForPointer(generator: TextGenerator): int;
function allocateXMM(xtype: int; generator: TextGenerator): int;
function allocateYMM(xtype: int; generator: TextGenerator): int;
function allocateZMM(xtype: int; generator: TextGenerator): int;
function allocateFPU(count: int; generator: TextGenerator): int;
function allocateMMX(generator: TextGenerator): int;
end;
MemoryLocationTfasm = class(RefCountInterfacedObject, MemoryLocation)
public
constructor create(generator: TextGenerator; regSrc: int;
const labelBase: String); overload;
constructor create(generator: TextGenerator; regSrc: int;
regBase: int; const labelOffset: String); overload;
constructor create(generator: TextGenerator; regSrc: int;
regBase, regIndex: int; const labelOffset: String); overload;
constructor create(generator: TextGenerator; regSrc: int;
regBase, regIndex, scale: int; const labelOffset: String); overload;
function getRegisterSource(): int; virtual;
function memoryToString(modifier: int; offset: int): String; virtual;
strict private
mode: int;
scale: int;
regSrc: int;
regBase: int;
regIndex: int;
generator: TextGenerator;
labelName: String;
end;
TextGenerator = class(Vector)
public
const EXIT_RET = 0;
const EXIT_RETF = 1;
const EXIT_CALL = 4;
const USE16 = 'use16';
const USE32 = 'use32';
const USE64 = 'use64';
class function isNeedHeapSize(): boolean; virtual;
class function isNeedStackSize(): boolean; virtual;
class function isNeedExitMethod(): boolean; virtual;
public
constructor create(); virtual;
function toString(): AnsiString; override;
procedure clear(); override;
procedure optimize(); virtual;
procedure beginCodeSection(); virtual;
procedure beginDataSection(); virtual;
procedure beginPoolSection(); virtual;
procedure writeEmptyLine(); virtual;
procedure writeText(const text: String); virtual;
procedure writeAlignGlobal(align: int); virtual;
procedure writeAlignLocal(align: int); virtual;
procedure writeDirectives(mode, org: int; const entry: String); virtual;
procedure writeProgrammeTail(); virtual;
procedure writeAssembler(const text: String); virtual;
procedure writeCommentToLineEnd(const commentText: String); virtual;
procedure writeCommentWithIdent(const commentText: String); virtual;
procedure writeEquality(const macroName, macroValue: String); virtual;
procedure writeLabelGlobal(const labelName: String); virtual;
procedure writeLabelLong(const labelName: String); virtual;
procedure writeLabelShort(const labelName: String); virtual;
procedure writeLabelRelative(const labelName: String; regBase, offset: int); virtual;
procedure writeInstruction(const mnemonic: String); overload; virtual;
procedure writeInstruction(const mnemonic, operand1: String); overload; virtual;
procedure writeInstruction(const mnemonic, operand1, operand2: String); overload; virtual;
procedure writeInstruction(const mnemonic, operand1, operand2,
operand3: String); overload; virtual;
procedure writeInstruction(const mnemonic, operand1, operand2, operand3,
operand4: String); overload; virtual;
procedure writeInstruction(const mnemonic: String;
const operands: String_Array1d); overload; virtual;
function labelCurrentOffsetToString(offset: int): String; virtual;
function labelRelativeToString(const labelName: String; offset: int): String; virtual;
function labelRelativeAnotherToString(const labelName, another: String;
offset: int): String; virtual;
function registerToString(reg: int): String; virtual;
function memoryToStringDecOffset(modifier: int; const labelBase: String;
offset: int): String; virtual;
function memoryToString(modifier: int; regBase: int;
offset: int): String; overload; virtual;
function memoryToString(modifier: int; regBase: int; regIndex: int;
offset: int): String; overload; virtual;
function memoryToString(modifier: int; regBase: int; regIndex, scale: int;
offset: int): String; overload; virtual;
function memoryToString(modifier: int; const labelBase: String;
offset: int): String; overload; virtual;
function memoryToString(modifier: int; const labelBase: String; regIndex: int;
offset: int): String; overload; virtual;
function memoryToString(modifier: int; const labelBase: String; regIndex, scale: int;
offset: int): String; overload; virtual;
function memoryToString(modifier: int; regBase: int;
const labelOffset: String; offset: int): String; overload; virtual;
function memoryToString(modifier: int; regBase: int; regIndex: int;
const labelOffset: String; offset: int): String; overload; virtual;
function memoryToString(modifier: int; regBase: int; regIndex, scale: int;
const labelOffset: String; offset: int): String; overload; virtual;
function memoryToString(modifier: int; const labelBase: String;
const labelOffset: String; offset: int): String; overload; virtual;
function memoryToString(modifier: int; const labelBase: String; regIndex: int;
const labelOffset: String; offset: int): String; overload; virtual;
function memoryToString(modifier: int; const labelBase: String; regIndex, scale: int;
const labelOffset: String; offset: int): String; overload; virtual;
function immediateToString(value: int): String; virtual;
function immediateToStringByte(value: int): String; virtual;
function immediateToStringShort(value: int): String; virtual;
function immediateToStringInt(value: int): String; virtual;
function immediateToStringLong(value: long): String; virtual;
protected
fldExitMethod: int;
procedure setHeapSize(heapSize: int); virtual;
procedure setStackSize(stackSize: int); virtual;
procedure setExitMethod(exitMethod: int); virtual;
function getHeapSize(): int; virtual;
function getStackSize(): int; virtual;
function offsetToDecString(offset: int): String; virtual;
function offsetToHexString(offset: int): String; virtual;
function modifierToString(modifier: int): String; virtual;
private
labelWrited: boolean;
strict private
fldHeapSize: int;
fldStackSize: int;
public
property heapSize: int read getHeapSize write setHeapSize;
property stackSize: int read getStackSize write setStackSize;
property exitMethod: int read fldExitMethod write setExitMethod;
end;
TextGenerator64 = class(TextGenerator)
public
procedure writeDirectives(mode, org: int; const entry: String); override;
function registerToString(reg: int): String; override;
end;
implementation
{ RegistersX86 }
class function RegistersX86.isRegisterGP(reg: int): boolean;
begin
case reg and $ff of
R0B..R15:
result := true;
else
result := false;
end;
end;
class function RegistersX86.isRegisterXMM(reg: int): boolean;
begin
case reg and $ff of
XMM0..XMM31:
result := true;
else
result := false;
end;
end;
class function RegistersX86.isRegisterYMM(reg: int): boolean;
begin
case reg and $ff of
XMM0..YMM31:
result := true;
else
result := false;
end;
end;
class function RegistersX86.isRegisterZMM(reg: int): boolean;
begin
case reg and $ff of
XMM0..ZMM31:
result := true;
else
result := false;
end;
end;
class function RegistersX86.isRegisterFPU(reg: int): boolean;
begin
case reg and $ff of
ST0..ST7:
result := true;
else
result := false;
end;
end;
class function RegistersX86.isRegisterMMX(reg: int): boolean;
begin
case reg and $ff of
MM0..MM7:
result := true;
else
result := false;
end;
end;
class function RegistersX86.getRegisterSize(reg: int): int;
begin
case reg and $ff of
R0B..R15B:
result := 8;
R0W..R15W:
result := 16;
R0D..R15D:
result := 32;
R0..R15, MM0..MM7:
result := 64;
ST0..ST7:
result := 80;
XMM0..XMM31:
result := 128;
YMM0..YMM31:
result := 256;
ZMM0..ZMM31:
result := 512;
else
result := 0;
end;
end;
class function RegistersX86.getCommonRegister(reg: int): int;
begin
case reg and $ff of
R0B..R15:
result := R0 + (reg and $0f);
MM0..MM7, ST0..ST7:
result := ST0 + (reg and $0f);
XMM0..ZMM31:
result := ZMM0 + (reg and $1f);
end;
end;
{ MemoryLocationTfasm }
constructor MemoryLocationTfasm.create(generator: TextGenerator; regSrc: int;
const labelBase: String);
begin
inherited create();
self.mode := 0;
self.scale := 1;
self.regSrc := regSrc;
self.regBase := -1;
self.regIndex := -1;
self.generator := generator;
self.labelName := labelBase;
end;
constructor MemoryLocationTfasm.create(generator: TextGenerator; regSrc: int;
regBase: int; const labelOffset: String);
begin
inherited create();
self.mode := 1;
self.scale := 1;
self.regSrc := regSrc;
self.regBase := regBase;
self.regIndex := -1;
self.generator := generator;
self.labelName := labelOffset;
end;
constructor MemoryLocationTfasm.create(generator: TextGenerator; regSrc: int;
regBase, regIndex: int; const labelOffset: String);
begin
inherited create();
self.mode := 2;
self.scale := 1;
self.regSrc := regSrc;
self.regBase := regBase;
self.regIndex := regIndex;
self.generator := generator;
self.labelName := labelOffset;
end;
constructor MemoryLocationTfasm.create(generator: TextGenerator; regSrc: int;
regBase, regIndex, scale: int; const labelOffset: String);
begin
inherited create();
self.mode := 2;
self.scale := scale;
self.regSrc := regSrc;
self.regBase := regBase;
self.regIndex := regIndex;
self.generator := generator;
self.labelName := labelOffset;
end;
function MemoryLocationTfasm.getRegisterSource(): int;
begin
result := regSrc;
end;
function MemoryLocationTfasm.memoryToString(modifier: int; offset: int): String;
begin
case mode of
0: result := generator.memoryToString(modifier, labelName, offset);
1: result := generator.memoryToString(modifier, regBase, labelName, offset);
2: result := generator.memoryToString(modifier, regBase, regIndex, scale, labelName, offset);
else
result := '';
end;
end;
{ TextGenerator }
class function TextGenerator.isNeedHeapSize(): boolean;
begin
result := false;
end;
class function TextGenerator.isNeedStackSize(): boolean;
begin
result := false;
end;
class function TextGenerator.isNeedExitMethod(): boolean;
begin
result := true;
end;
constructor TextGenerator.create();
begin
inherited create();
self.labelWrited := false;
end;
function TextGenerator.toString(): AnsiString;
var
i: int;
limit: int;
element: _Interface;
representation: String;
begin
result := '';
limit := size() - 1;
for i := 0 to limit do begin
element := elementAt(i);
if element <> nil then begin
representation := element.toString();
end else begin
representation := '';
end;
result := result + (representation + LINE_ENDING);
end;
end;
procedure TextGenerator.clear();
begin
inherited clear();
labelWrited := false;
end;
procedure TextGenerator.optimize();
const
POP = #$09#$09'pop'#$09;
PUSH = #$09#$09'push'#$09;
var
writed: boolean;
i: int;
limit: int;
e1: _Interface;
e2: _Interface;
s1: String;
s2: String;
r1: String;
r2: String;
procedure remove(); inline;
begin
removeElementAt(i + 1);
removeElementAt(i);
dec(limit, 2);
writed := true;
e2 := elementAt(i);
if e2 <> nil then begin
s2 := e2.toString();
end else begin
s2 := '';
end;
end;
begin
limit := size() - 1;
repeat
writed := false;
e2 := elementAt(limit);
if e2 <> nil then begin
s2 := e2.toString();
end else begin
s2 := '';
end;
for i := limit - 1 downto 0 do begin
e1 := elementAt(i);
if e1 <> nil then begin
s1 := e1.toString();
end else begin
s1 := '';
end;
if stringStartsWith(POP, s1) and stringStartsWith(PUSH, s2) then begin
{ pop reg, push reg }
r1 := copy(s1, length(POP) + 1, length(s1));
r2 := copy(s2, length(PUSH) + 1, length(s2));
if r1 = r2 then begin
remove();
continue;
end;
end;
if stringStartsWith(PUSH, s1) and stringStartsWith(POP, s2) then begin
{ push reg, pop reg }
r1 := copy(s1, length(PUSH) + 1, length(s1));
r2 := copy(s2, length(POP) + 1, length(s2));
if r1 = r2 then begin
remove();
continue;
end;
end;
s2 := s1;
end;
until not writed;
end;
procedure TextGenerator.beginCodeSection();
begin
end;
procedure TextGenerator.beginDataSection();
begin
end;
procedure TextGenerator.beginPoolSection();
begin
end;
procedure TextGenerator.writeEmptyLine();
begin
addElement('');
labelWrited := false;
end;
procedure TextGenerator.writeText(const text: String);
begin
addElement(text);
labelWrited := false;
end;
procedure TextGenerator.writeAlignGlobal(align: int);
begin
addElement('align ' + immediateToString(align));
labelWrited := false;
end;
procedure TextGenerator.writeAlignLocal(align: int);
begin
addElement(#$09'align ' + immediateToString(align));
labelWrited := false;
end;
procedure TextGenerator.writeDirectives(mode, org: int; const entry: String);
begin
case mode of
MODE_16_BIT: begin
addElement(USE16);
addElement('org ' + immediateToStringShort(org));
end;
MODE_32_BIT: begin
addElement(USE32);
addElement('org ' + immediateToStringInt(org));
end;
MODE_64_BIT: begin
addElement(USE64);
{ игнорируем org: код позиционно-независимый }
end;
end;
labelWrited := false;
end;
procedure TextGenerator.writeProgrammeTail();
begin
end;
procedure TextGenerator.writeAssembler(const text: String);
var
index: int;
element: _Interface;
line: String;
begin
index := size() - 1;
if labelWrited and (index >= 0) then begin
element := elementAt(index);
if element <> nil then begin
line := element.toString();
end else begin
line := '';
end;
setElementAt(index, line + text);
end else begin
addElement(#$09#$09 + text);
end;
labelWrited := false;
end;
procedure TextGenerator.writeCommentToLineEnd(const commentText: String);
var
c: int;
index: int;
element: _Interface;
line: String;
begin
index := size() - 1;
if index >= 0 then begin
element := elementAt(index);
if element <> nil then begin
line := element.toString();
end else begin
line := '';
end;
c := length(line);
if (c <= 0) or (int(line[c]) <= $20) then begin
line := line + '; ' + commentText;
end else begin
line := line + ' ; ' + commentText;
end;
setElementAt(index, line);
end else begin
addElement('; ' + commentText);
end;
labelWrited := false;
end;
procedure TextGenerator.writeCommentWithIdent(const commentText: String);
begin
writeAssembler('; ' + commentText);
end;
procedure TextGenerator.writeEquality(const macroName, macroValue: String);
begin
addElement(macroName + ' equ ' + macroValue);
labelWrited := false;
end;
procedure TextGenerator.writeLabelGlobal(const labelName: String);
begin
addElement(labelName + ':');
labelWrited := false;
end;
procedure TextGenerator.writeLabelLong(const labelName: String);
var
c: int;
text: String;
begin
c := length(labelName);
if c < 7 then begin
text := labelName + ':'#$09#$09;
end else
if c < 15 then begin
text := labelName + ':'#$09;
end else begin
text := labelName + ':';
end;
addElement(text);
labelWrited := true;
end;
procedure TextGenerator.writeLabelShort(const labelName: String);
var
text: String;
begin
if length(labelName) < 7 then begin
text := #$09 + labelName + ':'#$09;
end else begin
text := #$09 + labelName + ':';
end;
addElement(text);
labelWrited := true;
end;
procedure TextGenerator.writeLabelRelative(const labelName: String; regBase, offset: int);
begin
writeAssembler('label'#$09 + labelName + ' at ' +
registerToString(regBase) + offsetToHexString(offset));
end;
procedure TextGenerator.writeInstruction(const mnemonic: String);
begin
writeAssembler(mnemonic);
end;
procedure TextGenerator.writeInstruction(const mnemonic, operand1: String);
begin
writeInstruction(mnemonic, String_Array1d_create([
operand1
]));
end;
procedure TextGenerator.writeInstruction(const mnemonic, operand1, operand2: String);
begin
writeInstruction(mnemonic, String_Array1d_create([
operand1, operand2
]));
end;
procedure TextGenerator.writeInstruction(const mnemonic, operand1, operand2, operand3: String);
begin
writeInstruction(mnemonic, String_Array1d_create([
operand1, operand2, operand3
]));
end;
procedure TextGenerator.writeInstruction(const mnemonic, operand1, operand2, operand3,
operand4: String);
begin
writeInstruction(mnemonic, String_Array1d_create([
operand1, operand2, operand3, operand4
]));
end;
procedure TextGenerator.writeInstruction(const mnemonic: String; const operands: String_Array1d);
var
i: int;
limit: int;
instruction: String;
begin
limit := length(operands) - 1;
if limit >= 0 then begin
if length(mnemonic) < 8 then begin
instruction := mnemonic + #$09;
end else begin
instruction := mnemonic + #$20;
end;
for i := 0 to limit do begin
instruction := instruction + operands[i];
if i < limit then begin
instruction := instruction + ', ';
end;
end;
writeAssembler(instruction);
exit;
end;
writeAssembler(mnemonic);
end;
function TextGenerator.labelCurrentOffsetToString(offset: int): String;
begin
result := '$' + offsetToHexString(offset);
end;
function TextGenerator.labelRelativeToString(const labelName: String; offset: int): String;
begin
result := labelName + offsetToHexString(offset) + '-$';
end;
function TextGenerator.labelRelativeAnotherToString(const labelName, another: String;
offset: int): String;
begin
if length(another) > 0 then begin
result := labelName + offsetToHexString(offset) + '-' + another;
end else begin
result := labelName + offsetToHexString(offset) + '-$';
end;
end;
function TextGenerator.registerToString(reg: int): String;
begin
case reg and $ff of
R0B: result := 'al';
R1B: result := 'cl';
R2B: result := 'dl';
R3B: result := 'bl';
R4B: result := 'spl';
R5B: result := 'bpl';
R6B: result := 'sil';
R7B: result := 'dil';
R8B..R15B: result := 'r' + intToString(reg and $0f) + 'b';
R0W: result := 'ax';
R1W: result := 'cx';
R2W: result := 'dx';
R3W: result := 'bx';
R4W: result := 'sp';
R5W: result := 'bp';
R6W: result := 'si';
R7W: result := 'di';
R8W..R15W: result := 'r' + intToString(reg and $0f) + 'w';
R0D: result := 'eax';
R1D: result := 'ecx';
R2D: result := 'edx';
R3D: result := 'ebx';
R4D: result := 'esp';
R5D: result := 'ebp';
R6D: result := 'esi';
R7D: result := 'edi';
R8D..R15D: result := 'r' + intToString(reg and $0f) + 'd';
R0: result := 'rax';
R1: result := 'rcx';
R2: result := 'rdx';
R3: result := 'rbx';
R4: result := 'rsp';
R5: result := 'rbp';
R6: result := 'rsi';
R7: result := 'rdi';
R8..R15: result := 'r' + intToString(reg and $0f);
MM0..MM7: result := 'mm' + intToString(reg and $0f);
ST0..ST7: result := 'st' + intToString(reg and $0f);
XMM0..XMM31: result := 'xmm' + intToString(reg and $1f);
YMM0..YMM31: result := 'ymm' + intToString(reg and $1f);
ZMM0..ZMM31: result := 'zmm' + intToString(reg and $1f);
else result := 'invalid register[$' + intToHexString(reg and $ff) + ']';
end;
end;
function TextGenerator.memoryToStringDecOffset(modifier: int; const labelBase: String;
offset: int): String;
begin
result := modifierToString(modifier) + '[' + labelBase + offsetToDecString(offset) + ']';
end;
function TextGenerator.memoryToString(modifier: int; regBase: int;
offset: int): String;
begin
result := modifierToString(modifier) + '[' + registerToString(regBase) +
offsetToHexString(offset) + ']';
end;
function TextGenerator.memoryToString(modifier: int; regBase: int; regIndex: int;
offset: int): String;
begin
result := memoryToString(modifier, regBase, regIndex, 1, offset);
end;
function TextGenerator.memoryToString(modifier: int; regBase: int; regIndex, scale: int;
offset: int): String;
begin
case scale of
1: result := modifierToString(modifier) + '[' + registerToString(regBase) + '+' +
registerToString(regIndex) + offsetToHexString(offset) + ']';
2: result := modifierToString(modifier) + '[' + registerToString(regBase) + '+' +
registerToString(regIndex) + '*2' + offsetToHexString(offset) + ']';
4: result := modifierToString(modifier) + '[' + registerToString(regBase) + '+' +
registerToString(regIndex) + '*4' + offsetToHexString(offset) + ']';
8: result := modifierToString(modifier) + '[' + registerToString(regBase) + '+' +
registerToString(regIndex) + '*8' + offsetToHexString(offset) + ']';
else
result := 'invalid scale[' + intToString(scale) + ']';
end;
end;
function TextGenerator.memoryToString(modifier: int; const labelBase: String;
offset: int): String;
begin
result := modifierToString(modifier) + '[' + labelBase + offsetToHexString(offset) + ']';
end;
function TextGenerator.memoryToString(modifier: int; const labelBase: String; regIndex: int;
offset: int): String;
begin
result := memoryToString(modifier, labelBase, regIndex, 1, offset);
end;
function TextGenerator.memoryToString(modifier: int; const labelBase: String; regIndex, scale: int;
offset: int): String;
var
sBase: String;
begin
if length(labelBase) > 0 then begin
sBase := labelBase + '+';
end else begin
sBase := '';
end;
case scale of
1: result := modifierToString(modifier) + '[' + sBase +
registerToString(regIndex) + offsetToHexString(offset) + ']';
2: result := modifierToString(modifier) + '[' + sBase +
registerToString(regIndex) + '*2' + offsetToHexString(offset) + ']';
4: result := modifierToString(modifier) + '[' + sBase +
registerToString(regIndex) + '*4' + offsetToHexString(offset) + ']';
8: result := modifierToString(modifier) + '[' + sBase +
registerToString(regIndex) + '*8' + offsetToHexString(offset) + ']';
else
result := 'invalid scale[' + intToString(scale) + ']';
end;
end;
function TextGenerator.memoryToString(modifier: int; regBase: int; const labelOffset: String;
offset: int): String;
begin
if length(labelOffset) > 0 then begin
result := modifierToString(modifier) + '[' + registerToString(regBase) + '+' +
labelOffset + offsetToHexString(offset) + ']';
end else begin
result := modifierToString(modifier) + '[' + registerToString(regBase) +
offsetToHexString(offset) + ']';
end;
end;
function TextGenerator.memoryToString(modifier: int; regBase: int; regIndex: int;
const labelOffset: String; offset: int): String;
begin
result := memoryToString(modifier, regBase, regIndex, 1, labelOffset, offset);
end;
function TextGenerator.memoryToString(modifier: int; regBase: int; regIndex, scale: int;
const labelOffset: String; offset: int): String;
var
sOffset: String;
begin
if length(labelOffset) > 0 then begin
sOffset := '+' + labelOffset;
end else begin
sOffset := '';
end;
case scale of
1: result := modifierToString(modifier) + '[' + registerToString(regBase) + '+' +
registerToString(regIndex) + sOffset + offsetToHexString(offset) + ']';
2: result := modifierToString(modifier) + '[' + registerToString(regBase) + '+' +
registerToString(regIndex) + '*2' + sOffset + offsetToHexString(offset) + ']';
4: result := modifierToString(modifier) + '[' + registerToString(regBase) + '+' +
registerToString(regIndex) + '*4' + sOffset + offsetToHexString(offset) + ']';
8: result := modifierToString(modifier) + '[' + registerToString(regBase) + '+' +
registerToString(regIndex) + '*8' + sOffset + offsetToHexString(offset) + ']';
else
result := 'invalid scale[' + intToString(scale) + ']';
end;
end;
function TextGenerator.memoryToString(modifier: int; const labelBase: String;
const labelOffset: String; offset: int): String;
begin
if (length(labelBase) > 0) and (length(labelOffset) > 0) then begin
result := modifierToString(modifier) + '[' + labelBase + '+' + labelOffset +
offsetToHexString(offset) + ']';
end else begin
result := modifierToString(modifier) + '[' + labelBase + labelOffset +
offsetToHexString(offset) + ']';
end;
end;
function TextGenerator.memoryToString(modifier: int; const labelBase: String; regIndex: int;
const labelOffset: String; offset: int): String;
begin
result := memoryToString(modifier, labelBase, regIndex, 1, labelOffset, offset);
end;
function TextGenerator.memoryToString(modifier: int; const labelBase: String; regIndex, scale: int;
const labelOffset: String; offset: int): String;
var
sBase: String;
sOffset: String;
begin
if length(labelBase) > 0 then begin
sBase := labelBase + '+';
end else begin
sBase := '';
end;
if length(labelOffset) > 0 then begin
sOffset := '+' + labelOffset;
end else begin
sOffset := '';
end;
case scale of
1: result := modifierToString(modifier) + '[' + sBase +
registerToString(regIndex) + sOffset + offsetToHexString(offset) + ']';
2: result := modifierToString(modifier) + '[' + sBase +
registerToString(regIndex) + '*2' + sOffset + offsetToHexString(offset) + ']';
4: result := modifierToString(modifier) + '[' + sBase +
registerToString(regIndex) + '*4' + sOffset + offsetToHexString(offset) + ']';
8: result := modifierToString(modifier) + '[' + sBase +
registerToString(regIndex) + '*8' + sOffset + offsetToHexString(offset) + ']';
else
result := 'invalid scale[' + intToString(scale) + ']';
end;
end;
function TextGenerator.immediateToString(value: int): String;
begin
case value of
-$80000000..-$00010000:
result := '-$' + intToHexString(-value);
-$0000ffff..-$00000100:
result := '-$' + shortToHexString(-value);
-$000000ff..-$00000001:
result := '-$' + byteToHexString(-value);
+$00000000..+$000000ff:
result := '$' + byteToHexString(value);
+$00000100..+$0000ffff:
result := '$' + shortToHexString(value);
else
result := '$' + intToHexString(value);
end;
end;
function TextGenerator.immediateToStringByte(value: int): String;
begin
result := '$' + byteToHexString(value);
end;
function TextGenerator.immediateToStringShort(value: int): String;
begin
result := '$' + shortToHexString(value);
end;
function TextGenerator.immediateToStringInt(value: int): String;
begin
result := '$' + intToHexString(value);
end;
function TextGenerator.immediateToStringLong(value: long): String;
begin
result := '$' + longToHexString(value);
end;
procedure TextGenerator.setHeapSize(heapSize: int);
begin
self.fldHeapSize := heapSize;
end;
procedure TextGenerator.setStackSize(stackSize: int);
begin
self.fldStackSize := stackSize;
end;
procedure TextGenerator.setExitMethod(exitMethod: int);
begin
self.fldExitMethod := exitMethod;
end;
function TextGenerator.getHeapSize(): int;
begin
result := fldHeapSize;
end;
function TextGenerator.getStackSize(): int;
begin
result := fldStackSize;
end;
function TextGenerator.offsetToDecString(offset: int): String;
begin
case offset of
-$80000000..-$00000001:
result := intToString(offset);
+$00000001..+$7fffffff:
result := '+' + intToString(offset);
else
result := '';
end;
end;
function TextGenerator.offsetToHexString(offset: int): String;
begin
case offset of
-$80000000..-$00010000:
result := '-$' + intToHexString(-offset);
-$0000ffff..-$00000100:
result := '-$' + shortToHexString(-offset);
-$000000ff..-$00000001:
result := '-$' + byteToHexString(-offset);
+$00000001..+$000000ff:
result := '+$' + byteToHexString(offset);
+$00000100..+$0000ffff:
result := '+$' + shortToHexString(offset);
+$00010000..+$7fffffff:
result := '+$' + intToHexString(offset);
else
result := '';
end;
end;
function TextGenerator.modifierToString(modifier: int): String;
begin
case modifier of
MNONE:
result := '';
MBYTE:
result := 'byte';
MWORD:
result := 'word';
MDWORD:
result := 'dword';
MQWORD:
result := 'qword';
MTBYTE:
result := 'tbyte';
else
result := 'invalid modifier[$' + intToHexString(modifier) + ']';
end;
end;
{ TextGenerator64 }
procedure TextGenerator64.writeDirectives(mode, org: int; const entry: String);
var
i: int;
begin
inherited writeDirectives(mode, org, entry);
writeEmptyLine();
for i := 0 to 7 do begin
if (i <= 3) or (i >= 6) then begin
writeEquality('r' + intToString(i), inherited registerToString(R0 + i));
end;
end;
for i := 0 to 7 do begin
writeEquality('r' + intToString(i) + 'd', inherited registerToString(R0D + i));
end;
for i := 0 to 7 do begin
writeEquality('r' + intToString(i) + 'w', inherited registerToString(R0W + i));
end;
for i := 0 to 7 do begin
writeEquality('r' + intToString(i) + 'b', inherited registerToString(R0B + i));
end;
end;
function TextGenerator64.registerToString(reg: int): String;
begin
case reg and $ff of
R0B..R15B:
result := 'r' + intToString(reg and $0f) + 'b';
R0W..R15W:
result := 'r' + intToString(reg and $0f) + 'w';
R0D..R15D:
result := 'r' + intToString(reg and $0f) + 'd';
R4: result := 'rsp';
R5: result := 'rbp';
R0..R3, R6..R15:
result := 'r' + intToString(reg and $0f);
else
result := inherited registerToString(reg);
end;
end;
end.