{
Этот исходный текст является частью Продвинутого векторного транслятора.
Copyright © 2017 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit Gen16bit;
{$MODE DELPHI,EXTENDEDSYNTAX ON}
interface
uses
Lang, Utils, IOStream, TranIntf, TranType, TranTree, BuildLex, BuildFTr, GenX86;
{$ASMMODE INTEL,CALLING REGISTER,INLINE ON,GOTO ON}
{$H+,I-,J-,M-,Q-,R-,T-}
type
RegisterStack16bit = class;
TranslatorBuilderOf16bitCode = class;
RegisterStack16bit = class(RefCountInterfacedObject, RegisterStack)
protected
class function isUsing(reg: int; const using: short_Array1d): boolean;
public
constructor create(const usingGPRS, usingXMMS: short_Array1d;
usingGPRAsPointerAndArray, usingGPRAsPointerAndIndex: int);
procedure clear(); virtual;
procedure pushReg(reg: int); virtual;
procedure popRegs(count: int); virtual;
procedure storeRegs(count: int; g: TextGenerator); virtual;
procedure restoreRegs(g: TextGenerator); virtual;
procedure restoreRegsWithoutCodeGeneration(); virtual;
procedure deallocateReg(g: TextGenerator); virtual;
procedure deallocateRegWithoutCodeGeneration(); virtual;
function isUsedRegister(reg: int): boolean; virtual;
function getNextUsedGPR(regGPR: int): int; virtual;
function getNextUsedXMM(regXMM: int): int; virtual;
function getNextUsedMMX(regMMX: int): int; virtual;
function getRegAt(index: int): int; virtual;
function base(): int; virtual;
function size(): int; virtual;
function changeToGPR16bit(index: int): int; virtual;
function changeToGPR32bit(index: int): int; virtual;
function changeToGPR64bit(index: int): int; virtual;
function changeToXMM(index, xtype: int): int; virtual;
function changeToYMM(index, xtype: int): int; virtual;
function changeToZMM(index, xtype: int): int; virtual;
function allocateGPR16bit(g: TextGenerator): int; virtual;
function allocateGPR32bit(g: TextGenerator): int; virtual;
function allocateGPR64bit(g: TextGenerator): int; virtual;
function allocateGPRForArray(g: TextGenerator): int; virtual;
function allocateGPRForIndex(g: TextGenerator): int; virtual;
function allocateGPRForPointer(g: TextGenerator): int; virtual;
function allocateXMM(xtype: int; g: TextGenerator): int; virtual;
function allocateYMM(xtype: int; g: TextGenerator): int; virtual;
function allocateZMM(xtype: int; g: TextGenerator): int; virtual;
function allocateFPU(count: int; g: TextGenerator): int; virtual;
function allocateMMX(g: TextGenerator): int; virtual;
protected
sbase: int;
ssize: int;
stack: short_Array1d;
usingXMMs: short_Array1d;
usingGPRs: short_Array1d;
usingGPRAsPointerAndArray: int;
usingGPRAsPointerAndIndex: int;
procedure checkRegister(reg: int); virtual;
end;
TranslatorBuilderOf16bitCode = class(RefCountInterfacedObject, BuilderOfTargetCode,
UnicodeTextEncoder)
public
const MAX_INT_AS_REAL = 2.147483648e+09;
const LABEL_LOCAL = '.L.';
const LABEL_ANONYMOUS = '@@';
const LABEL_PRECEDING = '@B';
const LABEL_FOLLOWING = '@F';
const LABEL_PROG_END = 'L.G.PROG.END';
const LABEL_POOL_REAL_LENGTH = 'L.P.REAL.LEN';
const LABEL_POOL_REAL_CONTENT = 'L.P.REAL.CON';
const LABEL_POOL_FLOAT_LENGTH = 'L.P.FLOAT.LEN';
const LABEL_POOL_FLOAT_CONTENT = 'L.P.FLOAT.CON';
const LABEL_POOL_DOUBLE_LENGTH = 'L.P.DOUBLE.LEN';
const LABEL_POOL_DOUBLE_CONTENT = 'L.P.DOUBLE.CON';
const LABEL_POOL_STRING_LENGTH = 'L.P.STRING.LEN';
const LABEL_POOL_STRING_CONTENT = 'L.P.STRING.CON';
const LABEL_POOL_STRING_ENTRY = 'L.P.STRING.';
const CONSTANT_ORG = 'ORG';
const VARIABLE_RESULT = 'RESULT';
const FUNCTION_DISPOSE = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.' + TranslatorTreeBuilder.FUNCTION_DISPOSE;
const FUNCTION_NEW_ARRAY = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.' + TranslatorTreeBuilder.FUNCTION_NEW_ARRAY;
const FUNCTION_NEW_STRUCT = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.' + TranslatorTreeBuilder.FUNCTION_NEW_STRUCT;
const FUNCTION_EXIT = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.exit';
const FUNCTION_CHECK_ARRAY_INDEX = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.checkArrayIndex';
const FUNCTION_FLOAT_TO_SHORT = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.floatToShort';
const FUNCTION_DOUBLE_TO_SHORT = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.doubleToShort';
const FUNCTION_REAL_TO_SHORT = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.realToShort';
protected
class function needAllocateForIndex(parentValue, nodeIndex: int): boolean;
class function needAllocateForArray(parentValue, nodeIndex: int): boolean;
class function needAllocateForPointer(parentValue, nodeIndex: int): boolean;
public
constructor create(); overload;
constructor create(generator: TextGenerator; owning: boolean); overload;
destructor destroy; override;
procedure setUnicodeTextEncoder(encoder: UnicodeTextEncoder); virtual;
procedure buildTargetCode(programme: BuilderOfTrees; stream: Output); virtual;
function encode(const text: UnicodeString): AnsiString; virtual;
strict private
ownGenerator: boolean;
fldGenerator: TextGenerator;
fldEncoder: UnicodeTextEncoder;
poolOfReals: PoolReal;
poolOfFloats: PoolReal;
poolOfDoubles: PoolReal;
poolOfStrings: PoolString;
procedure translateEntryEquality(entry: NamespaceEntry);
procedure translateEntryVariable(entry: NamespaceEntry);
procedure translateEntryFunction(entry: NamespaceEntry; programme: BuilderOfTrees);
procedure translateStructure(structure: TypeStructure);
procedure translateConstant(constant: GlobalConstant);
procedure translateVariable(variable: GlobalVariable);
procedure translateFunction(func: GlobalFunction; programme: BuilderOfTrees);
procedure translateTree(tree: SyntaxTree);
procedure translateNode(node: SyntaxNode; stack: RegisterStack);
procedure translateSwitch(node: SyntaxNode; stack: RegisterStack);
procedure writePools();
function insertArguments(args: TypeFunction; offset: int): int;
function insertLocalVars(tree: SyntaxTree; offset: int): int;
function getMemoryLocation(node: SyntaxNode; stack: RegisterStack;
hasValueForWrite: boolean): MemoryLocation;
protected
property generator: TextGenerator read fldGenerator;
property programmeReals: PoolReal read poolOfReals;
property programmeFloats: PoolReal read poolOfFloats;
property programmeDoubles: PoolReal read poolOfDoubles;
property programmeStrings: PoolString read poolOfStrings;
function getEntryFullName(entry: NamespaceEntry): AnsiString; virtual;
function getFieldFullName(field: StructureField): AnsiString; virtual;
end;
resourcestring
msgIllegalRegisters = 'Этот стек регистров может принимать только регистры, доступные для ' +
'16-битного кода.';
implementation
{ RegisterStack16bit }
class function RegisterStack16bit.isUsing(reg: int; const using: short_Array1d): boolean;
var
i: int;
begin
reg := getCommonRegister(reg);
for i := length(using) - 1 downto 0 do begin
if getCommonRegister(using[i]) = reg then begin
result := true;
exit;
end;
end;
result := false;
end;
constructor RegisterStack16bit.create(const usingGPRS, usingXMMS: short_Array1d;
usingGPRAsPointerAndArray, usingGPRAsPointerAndIndex: int);
begin
inherited create();
self.sbase := 0;
self.ssize := 0;
self.stack := nil;
self.usingXMMs := usingXMMS;
self.usingGPRs := usingGPRS;
self.usingGPRAsPointerAndArray := usingGPRAsPointerAndArray;
self.usingGPRAsPointerAndIndex := usingGPRAsPointerAndIndex;
end;
procedure RegisterStack16bit.clear();
begin
self.sbase := 0;
self.ssize := 0;
self.stack := nil;
end;
procedure RegisterStack16bit.pushReg(reg: int);
var
i: int;
regst: int;
sbase: int;
ssize: int;
stack: short_Array1d;
newstack: short_Array1d;
begin
checkRegister(reg);
if (reg >= ST1) and (reg <= ST7) then begin
reg := ST;
end;
ssize := self.ssize;
stack := self.stack;
if reg = ST then begin
sbase := self.sbase;
for i := ssize - 1 downto sbase do begin
regst := stack[i];
if (regst >= ST0) and (regst <= ST6) then begin
stack[i] := short(regst + 1);
end;
end;
end;
if length(stack) = ssize then begin
newstack := short_Array1d_create((ssize shl 1) + 1);
arraycopyPrimitives(stack, 0, newstack, 0, ssize);
self.stack := newstack;
stack := newstack;
end;
stack[ssize] := short(reg);
self.ssize := ssize + 1;
end;
procedure RegisterStack16bit.popRegs(count: int);
var
i: int;
delta: int;
regst: int;
sbase: int;
ssize: int;
stack: short_Array1d;
begin
sbase := self.sbase;
ssize := self.ssize;
stack := self.stack;
count := Math.max(0, Math.min(count, ssize));
dec(ssize, count);
self.ssize := ssize;
if sbase >= ssize then begin
self.sbase := ssize;
exit;
end;
delta := 1;
for i := ssize - 1 downto sbase do begin
regst := stack[i];
if (regst >= ST0) and (regst <= ST7) then begin
if delta > 0 then begin
delta := ST - regst;
end;
stack[i] := short(regst + delta);
end;
end;
end;
procedure RegisterStack16bit.storeRegs(count: int; g: TextGenerator);
var
nonPushable: boolean;
i: int;
j: int;
ofs: int;
reg1: int;
sbase: int;
ssize: int;
stack: short_Array1d;
sr1: String;
sSP: String;
sBP: String;
sDI: String;
begin
{ Инструкции, вставляемые этим методом, не модифицируют регистр флагов. }
sbase := self.sbase;
ssize := self.ssize;
stack := self.stack;
nonPushable := false;
i := sbase;
j := 0;
ofs := 0;
while (i < ssize) and (j < count) do begin
reg1 := stack[i];
case reg1 of
AX, CX, DX, BX, SP, BP, SI, DI: begin
inc(ofs, 2);
end;
(XMM0 + XSINT)..(XMM7 + XSINT), (XMM0 + XSFLOAT)..(XMM7 + XSFLOAT): begin
nonPushable := true;
inc(ofs, 4);
end;
(XMM0 + XSLONG)..(XMM7 + XSLONG), (XMM0 + XSDOUBLE)..(XMM7 + XSDOUBLE), MM0..MM7: begin
nonPushable := true;
inc(ofs, 8);
end;
ST0..ST7: begin
nonPushable := true;
inc(ofs, 10);
end;
(XMM0 + XPFLOAT)..(XMM7 + XPFLOAT), (XMM0 + XPDOUBLE)..(XMM7 + XPDOUBLE),
(XMM0 + XPINT)..(XMM7 + XPINT), (XMM0 + XPLONG)..(XMM7 + XPLONG): begin
nonPushable := true;
inc(ofs, 16);
end;
end;
inc(i);
inc(j);
end;
sSP := g.registerToString(SP);
sBP := g.registerToString(BP);
sDI := g.registerToString(DI);
if nonPushable then begin
g.writeInstruction('mov', sDI, sSP);
g.writeInstruction('pushf');
g.writeInstruction('sub', sDI, sBP);
g.writeInstruction('popf');
g.writeInstruction('lea', sDI, g.memoryToString(MNONE, DI, -ofs));
g.writeInstruction('lea', sSP, g.memoryToString(MNONE, BP, DI, 0));
end;
i := sbase;
j := 0;
while (i < ssize) and (j < count) do begin
reg1 := stack[i];
sr1 := g.registerToString(reg1);
case reg1 of
AX, CX, DX, BX, SP, BP, SI, DI: begin
if nonPushable then begin
dec(ofs, 2);
g.writeInstruction('mov', g.memoryToString(MNONE, BP, DI, ofs), sr1);
end else begin
g.writeInstruction('push', sr1);
end;
end;
(XMM0 + XSINT)..(XMM7 + XSINT): begin
dec(ofs, 4);
g.writeInstruction('movd', g.memoryToString(MNONE, BP, DI, ofs), sr1);
end;
(XMM0 + XSFLOAT)..(XMM7 + XSFLOAT): begin
dec(ofs, 4);
g.writeInstruction('movss', g.memoryToString(MNONE, BP, DI, ofs), sr1);
end;
(XMM0 + XSLONG)..(XMM7 + XSLONG), MM0..MM7: begin
dec(ofs, 8);
g.writeInstruction('movq', g.memoryToString(MNONE, BP, DI, ofs), sr1);
end;
(XMM0 + XSDOUBLE)..(XMM7 + XSDOUBLE): begin
dec(ofs, 8);
g.writeInstruction('movsd', g.memoryToString(MNONE, BP, DI, ofs), sr1);
end;
ST: begin
dec(ofs, 10);
g.writeInstruction('fstp', g.memoryToString(MREAL, BP, DI, ofs));
{ g.writeInstruction('fdecstp'); }
end;
ST1..ST7: begin
dec(ofs, 10);
g.writeInstruction('fxch', sr1);
g.writeInstruction('fstp', g.memoryToString(MREAL, BP, DI, ofs));
if reg1 > ST1 then begin
g.writeInstruction('fld', g.registerToString(reg1 - 1));
g.writeInstruction('ffree', sr1);
end;
end;
(XMM0 + XPINT)..(XMM7 + XPINT), (XMM0 + XPLONG)..(XMM7 + XPLONG): begin
dec(ofs, 16);
g.writeInstruction('movdqu', g.memoryToString(MNONE, BP, DI, ofs), sr1);
end;
(XMM0 + XPFLOAT)..(XMM7 + XPFLOAT): begin
dec(ofs, 16);
g.writeInstruction('movups', g.memoryToString(MNONE, BP, DI, ofs), sr1);
end;
(XMM0 + XPDOUBLE)..(XMM7 + XPDOUBLE): begin
dec(ofs, 16);
g.writeInstruction('movupd', g.memoryToString(MNONE, BP, DI, ofs), sr1);
end;
end;
inc(i);
inc(j);
end;
self.sbase := i;
end;
procedure RegisterStack16bit.restoreRegs(g: TextGenerator);
var
nonPopable: boolean;
i: int;
nbs: int;
ofs: int;
reg1: int;
reglf: int;
sbase: int;
limit: int;
stack: short_Array1d;
sr1: String;
sSP: String;
sBP: String;
sDI: String;
begin
{ Инструкции, вставляемые этим методом, не модифицируют регистр флагов. }
sbase := self.sbase;
limit := self.ssize - 1;
stack := self.stack;
reglf := ST - 1;
for i := sbase to limit do begin
reg1 := stack[i];
if (reg1 >= ST0) and (reg1 <= ST7) then begin
reglf := reg1;
break;
end;
end;
nonPopable := false;
i := sbase;
while i > 0 do begin
reg1 := stack[i - 1];
if (reg1 >= ST0) and (reg1 <= ST7) and (reglf < ST7) then begin
inc(reglf);
reg1 := reglf;
stack[i - 1] := short(reg1);
end;
if isUsedRegister(reg1) then begin
break;
end;
dec(i);
self.sbase := i;
case reg1 of
MM0..MM7, ST0..ST7,
(XMM0 + XPINT)..(XMM7 + XPINT), (XMM0 + XPLONG)..(XMM7 + XPLONG),
(XMM0 + XSINT)..(XMM7 + XSINT), (XMM0 + XSLONG)..(XMM7 + XSLONG),
(XMM0 + XPFLOAT)..(XMM7 + XPFLOAT), (XMM0 + XPDOUBLE)..(XMM7 + XPDOUBLE),
(XMM0 + XSFLOAT)..(XMM7 + XSFLOAT), (XMM0 + XSDOUBLE)..(XMM7 + XSDOUBLE):
nonPopable := true;
AX, CX, DX, BX, SP, BP, SI, DI: ;
end;
end;
nbs := i;
ofs := 0;
sSP := g.registerToString(SP);
sBP := g.registerToString(BP);
sDI := g.registerToString(DI);
if nonPopable then begin
g.writeInstruction('mov', sDI, sSP);
g.writeInstruction('pushf');
g.writeInstruction('sub', sDI, sBP);
g.writeInstruction('popf');
end;
for i := sbase - 1 downto nbs do begin
reg1 := stack[i];
sr1 := g.registerToString(reg1);
case reg1 of
AX, CX, DX, BX, SP, BP, SI, DI: begin
if nonPopable then begin
g.writeInstruction('mov', sr1, g.memoryToString(MNONE, BP, DI, ofs));
inc(ofs, 2);
end else begin
g.writeInstruction('pop', sr1);
end;
end;
(XMM0 + XSINT)..(XMM7 + XSINT): begin
g.writeInstruction('movd', sr1, g.memoryToString(MNONE, BP, DI, ofs));
inc(ofs, 4);
end;
(XMM0 + XSFLOAT)..(XMM7 + XSFLOAT): begin
g.writeInstruction('movss', sr1, g.memoryToString(MNONE, BP, DI, ofs));
inc(ofs, 4);
end;
(XMM0 + XSLONG)..(XMM7 + XSLONG), MM0..MM7: begin
g.writeInstruction('movq', sr1, g.memoryToString(MNONE, BP, DI, ofs));
inc(ofs, 8);
end;
(XMM0 + XSDOUBLE)..(XMM7 + XSDOUBLE): begin
g.writeInstruction('movsd', sr1, g.memoryToString(MNONE, BP, DI, ofs));
inc(ofs, 8);
end;
ST0..ST6: begin
g.writeInstruction('fld', g.memoryToString(MREAL, BP, DI, ofs));
if reg1 > ST0 then begin
g.writeInstruction('fstp', g.registerToString(reg1 + 1));
end;
inc(ofs, 10);
end;
ST7: begin
g.writeInstruction('fld', g.memoryToString(MREAL, BP, DI, ofs));
g.writeInstruction('fincstp');
inc(ofs, 10);
end;
(XMM0 + XPINT)..(XMM7 + XPINT), (XMM0 + XPLONG)..(XMM7 + XPLONG): begin
g.writeInstruction('movdqu', sr1, g.memoryToString(MNONE, BP, DI, ofs));
inc(ofs, 16);
end;
(XMM0 + XPFLOAT)..(XMM7 + XPFLOAT): begin
g.writeInstruction('movups', sr1, g.memoryToString(MNONE, BP, DI, ofs));
inc(ofs, 16);
end;
(XMM0 + XPDOUBLE)..(XMM7 + XPDOUBLE): begin
g.writeInstruction('movupd', sr1, g.memoryToString(MNONE, BP, DI, ofs));
inc(ofs, 16);
end;
end;
end;
if nonPopable then begin
g.writeInstruction('lea', sSP, g.memoryToString(MNONE, BP, DI, ofs));
end;
end;
procedure RegisterStack16bit.restoreRegsWithoutCodeGeneration();
var
i: int;
reg1: int;
reglf: int;
sbase: int;
limit: int;
stack: short_Array1d;
begin
sbase := self.sbase;
limit := self.ssize - 1;
stack := self.stack;
reglf := ST - 1;
for i := sbase to limit do begin
reg1 := stack[i];
if (reg1 >= ST0) and (reg1 <= ST7) then begin
reglf := reg1;
break;
end;
end;
i := sbase;
while i > 0 do begin
reg1 := stack[i - 1];
if (reg1 >= ST0) and (reg1 <= ST7) and (reglf < ST7) then begin
inc(reglf);
reg1 := reglf;
stack[i - 1] := short(reg1);
end;
if isUsedRegister(reg1) then begin
break;
end;
dec(i);
self.sbase := i;
end;
end;
procedure RegisterStack16bit.deallocateReg(g: TextGenerator);
begin
popRegs(1);
restoreRegs(g);
end;
procedure RegisterStack16bit.deallocateRegWithoutCodeGeneration();
begin
popRegs(1);
restoreRegsWithoutCodeGeneration();
end;
function RegisterStack16bit.isUsedRegister(reg: int): boolean;
var
i: int;
regcm: int;
sbase: int;
ssize: int;
stack: short_Array1d;
begin
regcm := getCommonRegister(reg);
sbase := self.sbase;
ssize := self.ssize;
stack := self.stack;
for i := ssize - 1 downto sbase do begin
if getCommonRegister(stack[i]) = regcm then begin
result := true;
exit;
end;
end;
result := false;
end;
function RegisterStack16bit.getNextUsedGPR(regGPR: int): int;
var
i: int;
regcm: int;
regus: int;
using: short_Array1d;
begin
using := self.usingGPRs;
regcm := AX + (regGPR and $0f);
result := AX + (using[0] and $0f);
for i := length(using) - 1 downto 0 do begin
regus := AX + (using[i] and $0f);
if regus = regcm then begin
exit;
end;
result := regus;
end;
end;
function RegisterStack16bit.getNextUsedXMM(regXMM: int): int;
var
i: int;
regcm: int;
regus: int;
using: short_Array1d;
begin
using := self.usingXMMs;
regcm := XMM0 + (regXMM and $1f);
result := XMM0 + (using[0] and $1f);
for i := length(using) - 1 downto 0 do begin
regus := XMM0 + (using[i] and $1f);
if regus = regcm then begin
exit;
end;
result := regus;
end;
end;
function RegisterStack16bit.getNextUsedMMX(regMMX: int): int;
begin
result := -1;
end;
function RegisterStack16bit.getRegAt(index: int): int;
var
ssize: int;
begin
ssize := self.ssize;
if (index < 0) or (index >= ssize) then begin
raise IndexOutOfBoundsException.create(msgIndexOutOfBounds);
end;
result := stack[ssize - index - 1];
end;
function RegisterStack16bit.base(): int;
begin
result := ssize - sbase;
end;
function RegisterStack16bit.size(): int;
begin
result := ssize;
end;
function RegisterStack16bit.changeToGPR16bit(index: int): int;
var
ssize: int;
stack: short_Array1d;
begin
ssize := self.ssize;
if (index < 0) or (index >= ssize) then begin
raise IndexOutOfBoundsException.create(msgIndexOutOfBounds);
end;
stack := self.stack;
index := ssize - index - 1;
result := stack[index];
if not isRegisterGP(result) then begin
result := -1;
exit;
end;
result := AX + (result and $0f);
stack[index] := short(result);
end;
function RegisterStack16bit.changeToGPR32bit(index: int): int;
begin
result := -1;
end;
function RegisterStack16bit.changeToGPR64bit(index: int): int;
begin
result := -1;
end;
function RegisterStack16bit.changeToXMM(index, xtype: int): int;
var
ssize: int;
stack: short_Array1d;
begin
ssize := self.ssize;
if (index < 0) or (index >= ssize) then begin
raise IndexOutOfBoundsException.create(msgIndexOutOfBounds);
end;
stack := self.stack;
index := ssize - index - 1;
result := stack[index];
if not isRegisterXMM(result) then begin
result := -1;
exit;
end;
result := XMM0 + (xtype and XMASK) + (result and $1f);
stack[index] := short(result);
end;
function RegisterStack16bit.changeToYMM(index, xtype: int): int;
begin
result := -1;
end;
function RegisterStack16bit.changeToZMM(index, xtype: int): int;
begin
result := -1;
end;
function RegisterStack16bit.allocateGPR16bit(g: TextGenerator): int;
var
i: int;
regst: int;
uslim: int;
sbase: int;
limit: int;
stack: short_Array1d;
using: short_Array1d;
begin
result := -1;
using := self.usingGPRs;
stack := self.stack;
limit := self.ssize - 1;
sbase := self.sbase;
uslim := length(using) - 1;
for i := limit downto 0 do begin
regst := getCommonRegister(stack[i]);
if result < 0 then begin
if isUsing(regst, using) then begin
result := getCommonRegister(getNextUsedGPR(regst));
end;
end else begin
if regst = result then begin
regst := AX + (regst and $0f);
if i >= sbase then begin
storeRegs(i - sbase + 1, g);
end;
pushReg(regst);
result := regst;
exit;
end;
end;
end;
if result >= 0 then begin
regst := AX + (result and $0f);
pushReg(regst);
result := regst;
exit;
end;
for i := 0 to uslim do begin
regst := AX + (using[i] and $0f);
if not isUsedRegister(regst) then begin
pushReg(regst);
result := regst;
exit;
end;
end;
for i := sbase to limit do begin
regst := getCommonRegister(stack[i]);
if isUsing(regst, using) then begin
regst := AX + (regst and $0f);
storeRegs(i - sbase + 1, g);
pushReg(regst);
result := regst;
exit;
end;
end;
result := -1;
end;
function RegisterStack16bit.allocateGPR32bit(g: TextGenerator): int;
begin
result := -1;
end;
function RegisterStack16bit.allocateGPR64bit(g: TextGenerator): int;
begin
result := -1;
end;
function RegisterStack16bit.allocateGPRForArray(g: TextGenerator): int;
var
i: int;
regst: int;
regAr: int;
sbase: int;
limit: int;
stack: short_Array1d;
begin
result := -1;
stack := self.stack;
limit := self.ssize - 1;
sbase := self.sbase;
regAr := getCommonRegister(self.usingGPRAsPointerAndArray);
for i := limit downto 0 do begin
regst := getCommonRegister(stack[i]);
if regst = regAr then begin
regst := AX + (regst and $0f);
if i >= sbase then begin
storeRegs(i - sbase + 1, g);
end;
pushReg(regst);
result := regst;
exit;
end;
end;
regst := AX + (regAr and $0f);
if not isUsedRegister(regst) then begin
pushReg(regst);
result := regst;
exit;
end;
for i := sbase to limit do begin
regst := getCommonRegister(stack[i]);
if regst = regAr then begin
regst := AX + (regst and $0f);
storeRegs(i - sbase + 1, g);
pushReg(regst);
result := regst;
exit;
end;
end;
end;
function RegisterStack16bit.allocateGPRForIndex(g: TextGenerator): int;
var
i: int;
regst: int;
regId: int;
sbase: int;
limit: int;
stack: short_Array1d;
begin
result := -1;
stack := self.stack;
limit := self.ssize - 1;
sbase := self.sbase;
regId := getCommonRegister(self.usingGPRAsPointerAndIndex);
for i := limit downto 0 do begin
regst := getCommonRegister(stack[i]);
if regst = regId then begin
regst := AX + (regst and $0f);
if i >= sbase then begin
storeRegs(i - sbase + 1, g);
end;
pushReg(regst);
result := regst;
exit;
end;
end;
regst := AX + (regId and $0f);
if not isUsedRegister(regst) then begin
pushReg(regst);
result := regst;
exit;
end;
for i := sbase to limit do begin
regst := getCommonRegister(stack[i]);
if regst = regId then begin
regst := AX + (regst and $0f);
storeRegs(i - sbase + 1, g);
pushReg(regst);
result := regst;
exit;
end;
end;
end;
function RegisterStack16bit.allocateGPRForPointer(g: TextGenerator): int;
var
i: int;
regst: int;
regP1: int;
regP2: int;
sbase: int;
limit: int;
stack: short_Array1d;
begin
result := -1;
stack := self.stack;
limit := self.ssize - 1;
sbase := self.sbase;
regP1 := getCommonRegister(self.usingGPRAsPointerAndArray);
regP2 := getCommonRegister(self.usingGPRAsPointerAndIndex);
for i := limit downto 0 do begin
regst := getCommonRegister(stack[i]);
if result < 0 then begin
if regst = regP1 then begin
result := regP2;
end else
if regst = regP2 then begin
result := regP1;
end;
end else begin
if regst = result then begin
regst := AX + (regst and $0f);
if i >= sbase then begin
storeRegs(i - sbase + 1, g);
end;
pushReg(regst);
result := regst;
exit;
end;
end;
end;
if result >= 0 then begin
regst := AX + (result and $0f);
pushReg(regst);
result := regst;
exit;
end;
regst := AX + (regP1 and $0f);
if not isUsedRegister(regst) then begin
pushReg(regst);
result := regst;
exit;
end;
regst := AX + (regP2 and $0f);
if not isUsedRegister(regst) then begin
pushReg(regst);
result := regst;
exit;
end;
for i := sbase to limit do begin
regst := getCommonRegister(stack[i]);
if (regst = regP1) or (regst = regP2) then begin
regst := AX + (regst and $0f);
storeRegs(i - sbase + 1, g);
pushReg(regst);
result := regst;
exit;
end;
end;
result := -1;
end;
function RegisterStack16bit.allocateXMM(xtype: int; g: TextGenerator): int;
var
i: int;
regst: int;
uslim: int;
sbase: int;
limit: int;
stack: short_Array1d;
using: short_Array1d;
begin
result := -1;
using := self.usingXMMs;
stack := self.stack;
limit := self.ssize - 1;
sbase := self.sbase;
uslim := length(using) - 1;
for i := limit downto 0 do begin
regst := getCommonRegister(stack[i]);
if result < 0 then begin
if isUsing(regst, using) then begin
result := getCommonRegister(getNextUsedXMM(regst));
end;
end else begin
if regst = result then begin
regst := XMM0 + (xtype and XMASK) + (regst and $1f);
if i >= sbase then begin
storeRegs(i - sbase + 1, g);
end;
pushReg(regst);
result := regst;
exit;
end;
end;
end;
if result >= 0 then begin
regst := XMM0 + (xtype and XMASK) + (result and $1f);
pushReg(regst);
result := regst;
exit;
end;
for i := 0 to uslim do begin
regst := XMM0 + (xtype and XMASK) + (using[i] and $1f);
if not isUsedRegister(regst) then begin
pushReg(regst);
result := regst;
exit;
end;
end;
for i := sbase to limit do begin
regst := getCommonRegister(stack[i]);
if isUsing(regst, using) then begin
regst := XMM0 + (xtype and XMASK) + (regst and $1f);
storeRegs(i - sbase + 1, g);
pushReg(regst);
result := regst;
exit;
end;
end;
result := -1;
end;
function RegisterStack16bit.allocateYMM(xtype: int; g: TextGenerator): int;
begin
result := -1;
end;
function RegisterStack16bit.allocateZMM(xtype: int; g: TextGenerator): int;
begin
result := -1;
end;
function RegisterStack16bit.allocateFPU(count: int; g: TextGenerator): int;
var
i: int;
reg: int;
sbase: int;
limit: int;
stack: short_Array1d;
begin
count := Math.max(1, Math.min(count, 8));
sbase := self.sbase;
limit := self.ssize - 1;
stack := self.stack;
reg := -count + (ST7 + 1);
for i := sbase to limit do begin
if stack[i] = reg then begin
storeRegs(i - sbase + 1, g);
break;
end;
end;
for i := 1 to count do begin
pushReg(ST);
end;
result := ST;
end;
function RegisterStack16bit.allocateMMX(g: TextGenerator): int;
begin
result := -1;
end;
procedure RegisterStack16bit.checkRegister(reg: int);
begin
case reg of
AX, CX, DX, BX, SP, BP, SI, DI, MM0..MM7, ST0..ST7,
(XMM0 + XPINT)..(XMM7 + XPINT), (XMM0 + XPLONG)..(XMM7 + XPLONG),
(XMM0 + XSINT)..(XMM7 + XSINT), (XMM0 + XSLONG)..(XMM7 + XSLONG),
(XMM0 + XPFLOAT)..(XMM7 + XPFLOAT), (XMM0 + XPDOUBLE)..(XMM7 + XPDOUBLE),
(XMM0 + XSFLOAT)..(XMM7 + XSFLOAT), (XMM0 + XSDOUBLE)..(XMM7 + XSDOUBLE): ;
else
raise IllegalArgumentException.create(msgIllegalRegisters);
end;
end;
{ TranslatorBuilderOf16bitCode }
class function TranslatorBuilderOf16bitCode.needAllocateForIndex(parentValue,
nodeIndex: int): boolean;
begin
result := (parentValue = TranslatorTreeBuilder.EXPR_ARRAY) and (nodeIndex = 1);
end;
class function TranslatorBuilderOf16bitCode.needAllocateForArray(parentValue,
nodeIndex: int): boolean;
begin
result := (parentValue = TranslatorTreeBuilder.EXPR_ARRAY) and (nodeIndex = 0);
end;
class function TranslatorBuilderOf16bitCode.needAllocateForPointer(parentValue,
nodeIndex: int): boolean;
begin
result := (parentValue = TranslatorTreeBuilder.EXPR_FIELD) and (nodeIndex = 0);
end;
constructor TranslatorBuilderOf16bitCode.create();
begin
create(TextGenerator.create(), true);
end;
constructor TranslatorBuilderOf16bitCode.create(generator: TextGenerator; owning: boolean);
begin
inherited create();
if generator = nil then begin
generator := TextGenerator.create();
owning := true;
end;
self.ownGenerator := owning;
self.fldGenerator := generator;
self.fldEncoder := nil;
self.poolOfReals := TranslatorPoolReal.create();
self.poolOfFloats := TranslatorPoolReal.create();
self.poolOfDoubles := TranslatorPoolReal.create();
self.poolOfStrings := TranslatorPoolString.create();
end;
destructor TranslatorBuilderOf16bitCode.destroy;
begin
if ownGenerator then begin
fldGenerator.free();
end;
inherited destroy;
end;
procedure TranslatorBuilderOf16bitCode.setUnicodeTextEncoder(encoder: UnicodeTextEncoder);
begin
if (encoder as TObject) = self then begin
encoder := nil;
end;
self.fldEncoder := encoder;
end;
procedure TranslatorBuilderOf16bitCode.buildTargetCode(programme: BuilderOfTrees; stream: Output);
var
i: int;
j: int;
org: int;
elimit: int;
mlimit: int;
module: Namespace;
entry: NamespaceEntry;
pentry: GlobalFunction;
g: TextGenerator;
begin
g := self.generator;
g.clear();
try
programmeReals.clear();
programmeFloats.clear();
programmeDoubles.clear();
programmeStrings.clear();
entry := programme.systemNamespace.findEntry(CONSTANT_ORG, false);
if entry is GlobalConstant then begin
org := (entry as GlobalConstant).intValue and $ffff;
end else begin
org := 0;
end;
entry := nil;
pentry := programme.entryPoint;
g.writeDirectives(MODE_16_BIT, org, encode(pentry.name));
g.writeEmptyLine();
g.writeEmptyLine();
g.writeCommentToLineEnd('constant of boolean type');
g.writeEquality('false', g.immediateToString(0));
g.writeEquality('true', g.immediateToString(1));
g.writeEmptyLine();
g.writeEmptyLine();
g.writeCommentToLineEnd('constant null');
g.writeEquality('null', g.immediateToString(0));
g.writeEmptyLine();
mlimit := programme.getNamespacesCount() - 1;
for j := 0 to mlimit do begin
module := programme.getNamespace(j);
if length(module.name) <= 0 then begin
continue;
end;
elimit := module.getEntriesCount() - 1;
for i := 0 to elimit do begin
translateEntryEquality(module.getEntry(i));
end;
end;
g.beginCodeSection();
translateFunction(pentry, programme);
for j := 0 to mlimit do begin
module := programme.getNamespace(j);
if length(module.name) <= 0 then begin
continue;
end;
elimit := module.getEntriesCount() - 1;
for i := 0 to elimit do begin
translateEntryFunction(module.getEntry(i), programme);
end;
end;
g.beginDataSection();
for j := 0 to mlimit do begin
module := programme.getNamespace(j);
if length(module.name) <= 0 then begin
continue;
end;
elimit := module.getEntriesCount() - 1;
for i := 0 to elimit do begin
translateEntryVariable(module.getEntry(i));
end;
end;
g.beginPoolSection();
writePools();
g.writeProgrammeTail();
g.writeEmptyLine();
g.writeCommentToLineEnd('programme end');
g.writeAlignGlobal(2);
g.writeLabelLong(LABEL_PROG_END);
g.optimize();
finally
stream.write(stringToByteArray(g.toString()));
end;
end;
function TranslatorBuilderOf16bitCode.encode(const text: UnicodeString): AnsiString;
var
encoder: UnicodeTextEncoder;
begin
encoder := self.fldEncoder;
if encoder <> nil then begin
result := encoder.encode(text);
end else begin
result := stringToUTF8(text);
end;
end;
procedure TranslatorBuilderOf16bitCode.translateEntryEquality(entry: NamespaceEntry);
begin
if entry is TypeStructure then begin
translateStructure(entry as TypeStructure);
end else
if entry is GlobalConstant then begin
translateConstant(entry as GlobalConstant);
end;
end;
procedure TranslatorBuilderOf16bitCode.translateEntryVariable(entry: NamespaceEntry);
begin
if not (entry is GlobalConstant) and (entry is GlobalVariable) then begin
translateVariable(entry as GlobalVariable);
end;
end;
procedure TranslatorBuilderOf16bitCode.translateEntryFunction(entry: NamespaceEntry;
programme: BuilderOfTrees);
begin
if entry is GlobalFunction then begin
translateFunction(entry as GlobalFunction, programme);
end;
end;
procedure TranslatorBuilderOf16bitCode.translateStructure(structure: TypeStructure);
var
i: int;
limit: int;
field: StructureField;
g: TextGenerator;
ename: String;
fname: String;
begin
g := self.generator;
ename := getEntryFullName(structure as NamespaceEntry);
g.writeEmptyLine();
g.writeCommentToLineEnd('structure ' + ename);
repeat
limit := structure.getFieldsCount() - 1;
for i := 0 to limit do begin
field := structure.getField(i);
fname := encode(field.name);
if length(fname) > 0 then begin
g.writeEquality(ename + '.' + fname, g.immediateToString(field.offset and $ffff));
end;
end;
structure := structure.ancestor;
until structure = nil;
g.writeEmptyLine();
end;
procedure TranslatorBuilderOf16bitCode.translateConstant(constant: GlobalConstant);
var
g: TextGenerator;
ename: String;
begin
g := self.generator;
ename := getEntryFullName(constant);
g.writeEmptyLine();
g.writeCommentToLineEnd('constant ' + ename);
case constant.dataType.kind of
TranslatorType.KIND_BOOLEAN:
if constant.booleanValue = true then begin
g.writeEquality(ename, 'true');
end else begin
g.writeEquality(ename, 'false');
end;
TranslatorType.KIND_CHAR:
g.writeEquality(ename, g.immediateToString(constant.charValue));
TranslatorType.KIND_BYTE:
g.writeEquality(ename, g.immediateToString(constant.byteValue));
TranslatorType.KIND_SHORT:
g.writeEquality(ename, g.immediateToString(constant.shortValue));
TranslatorType.KIND_FLOAT:
g.writeEquality(ename, g.memoryToString(MFLOAT, LABEL_POOL_FLOAT_CONTENT,
programmeFloats.indexAcquire(realToFloat(constant.realValue)) * 4));
TranslatorType.KIND_DOUBLE:
g.writeEquality(ename, g.memoryToString(MDOUBLE, LABEL_POOL_DOUBLE_CONTENT,
programmeDoubles.indexAcquire(realToDouble(constant.realValue)) * 8));
TranslatorType.KIND_REAL:
g.writeEquality(ename, g.memoryToStringDecOffset(MREAL, LABEL_POOL_REAL_CONTENT,
programmeReals.indexAcquire(constant.realValue) * 10));
end;
g.writeEmptyLine();
end;
procedure TranslatorBuilderOf16bitCode.translateVariable(variable: GlobalVariable);
var
vtype: TypeDescriptor;
g: TextGenerator;
ename: String;
szero: String;
begin
g := self.generator;
ename := getEntryFullName(variable);
vtype := variable.dataType;
g.writeAlignGlobal(2);
g.writeLabelGlobal(ename);
g.writeCommentToLineEnd(vtype.toString());
szero := g.immediateToStringShort(0);
case vtype.kind of
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
TranslatorType.KIND_SHORT:
g.writeInstruction('dw', szero);
TranslatorType.KIND_FLOAT:
g.writeInstruction('dd', g.immediateToStringInt(0));
TranslatorType.KIND_DOUBLE:
g.writeInstruction('dq', g.immediateToStringLong(0));
TranslatorType.KIND_REAL:
g.writeInstruction('dw', String_Array1d_create([
szero, szero, szero, szero, szero
]));
end;
g.writeEmptyLine();
end;
procedure TranslatorBuilderOf16bitCode.translateFunction(func: GlobalFunction;
programme: BuilderOfTrees);
var
interruptWithError: boolean;
functionWithSFrame: boolean;
functionIsEntry: boolean;
i: int;
limit: int;
pcount: int;
pstart: int;
pfinish: int;
argumsSize: int;
localsSize: int;
lexemes: Lexer;
tree: SyntaxTree;
root: SyntaxNode;
module: Namespace;
entry: NamespaceEntry;
ftype: TypeFunction;
g: TextGenerator;
comment: String;
ename: String;
begin
g := self.generator;
ename := getEntryFullName(func);
ftype := func.functionType;
module := func.owner;
functionIsEntry := length(module.name) <= 0;
if functionIsEntry = false then begin
g.writeAlignGlobal(2);
end;
g.writeLabelGlobal(ename);
limit := ftype.getArgumentsCount() - 1;
comment := ftype.getReturnType().toString();
if limit >= 0 then begin
g.writeCommentToLineEnd(comment + '(');
for i := 0 to limit do with ftype.getArgument(i) do begin
comment := dataType.toString() + #$20 + encode(name);
if i < limit then begin
g.writeCommentWithIdent(comment + ',');
end else begin
g.writeCommentWithIdent(comment + ')');
end;
end;
end else begin
g.writeCommentToLineEnd(comment + '()');
end;
lexemes := module.lexemes;
pcount := 1;
pstart := func.startPosition + 1;
pfinish := pstart - 1;
repeat
inc(pfinish);
case lexemes.getType(pfinish) of
TranslatorLexer.OPENED_CURLY_BRACKET:
inc(pcount);
TranslatorLexer.CLOSED_CURLY_BRACKET:
dec(pcount);
end;
until pcount = 0;
if func.isInterrupt() then begin
{ чтобы функция-прерывание имела параметр «код ошибки», нужно чтобы четвёртый параметр
начинался с "error" (например: error, errorCode, errorSegment, errorFlags и т. п.).
Регистр символов учитывается, т. е. имена вроде ErrorCode не распознаются как параметр
«код ошибки». }
inc(limit);
interruptWithError := (limit >= 4) and
stringStartsWith(UnicodeString('error'), ftype.getArgument(3).name);
tree := programme.buildSyntaxTree(func) as SyntaxTree;
if interruptWithError then begin
argumsSize := insertArguments(ftype, (11 - limit) shl 1);
end else begin
argumsSize := insertArguments(ftype, (10 - limit) shl 1);
end;
localsSize := insertLocalVars(tree, 0);
if func.isPureAssembler() then begin
g.writeAssembler(stringTrim(encode(lexemes.getSourceFragment(
lexemes.getLine(pstart), lexemes.getChar(pstart),
lexemes.getLine(pfinish), lexemes.getChar(pfinish)))));
end else begin
g.writeInstruction('push', g.registerToString(AX));
g.writeInstruction('push', g.registerToString(CX));
g.writeInstruction('push', g.registerToString(DX));
g.writeInstruction('push', g.registerToString(BX));
g.writeInstruction('push', g.registerToString(SI));
g.writeInstruction('push', g.registerToString(DI));
g.writeInstruction('enter', g.immediateToStringShort(localsSize),
g.immediateToStringByte(0));
if func.isAssembler() then begin
g.writeAssembler(stringTrim(encode(lexemes.getSourceFragment(
lexemes.getLine(pstart), lexemes.getChar(pstart),
lexemes.getLine(pfinish), lexemes.getChar(pfinish)))));
end else begin
translateTree(tree);
end;
g.writeInstruction('leave');
g.writeInstruction('pop', g.registerToString(DI));
g.writeInstruction('pop', g.registerToString(SI));
g.writeInstruction('pop', g.registerToString(BX));
g.writeInstruction('pop', g.registerToString(DX));
g.writeInstruction('pop', g.registerToString(CX));
g.writeInstruction('pop', g.registerToString(AX));
if interruptWithError then begin
g.writeInstruction('add', g.registerToString(SP), g.immediateToString(2));
end;
g.writeInstruction('iret');
end;
end else begin
tree := programme.buildSyntaxTree(func) as SyntaxTree;
if functionIsEntry and (g.exitMethod = TextGenerator.EXIT_RETF) then begin
argumsSize := insertArguments(ftype, 6);
end else begin
argumsSize := insertArguments(ftype, 4);
end;
localsSize := insertLocalVars(tree, 0);
if func.isPureAssembler() then begin
g.writeAssembler(stringTrim(encode(lexemes.getSourceFragment(
lexemes.getLine(pstart), lexemes.getChar(pstart),
lexemes.getLine(pfinish), lexemes.getChar(pfinish)))));
end else begin
functionWithSFrame := (argumsSize > 0) or (localsSize > 0);
if functionWithSFrame then begin
g.writeInstruction('enter', g.immediateToStringShort(localsSize),
g.immediateToStringByte(0));
end;
if func.isAssembler() then begin
g.writeAssembler(stringTrim(encode(lexemes.getSourceFragment(
lexemes.getLine(pstart), lexemes.getChar(pstart),
lexemes.getLine(pfinish), lexemes.getChar(pfinish)))));
end else begin
translateTree(tree);
end;
if functionIsEntry then begin
entry := programme.systemNamespace.findEntry(VARIABLE_RESULT, false);
if entry is GlobalVariable then begin
g.writeInstruction('mov', g.registerToString(AX),
g.memoryToString(MNONE, getEntryFullName(entry), 0));
end;
end else begin
entry := nil;
end;
if functionWithSFrame then begin
g.writeInstruction('leave');
end;
if functionIsEntry then begin
case g.exitMethod of
TextGenerator.EXIT_RETF: begin
if argumsSize > 0 then begin
g.writeInstruction('retf', g.immediateToString(argumsSize));
end else begin
g.writeInstruction('retf');
end;
end;
TextGenerator.EXIT_CALL: begin
if entry is GlobalVariable then begin
g.writeInstruction('push', g.registerToString(AX));
end else begin
g.writeInstruction('push', g.immediateToString(0));
end;
g.writeInstruction('call', FUNCTION_EXIT);
end;
else
if argumsSize > 0 then begin
g.writeInstruction('ret', g.immediateToString(argumsSize));
end else begin
g.writeInstruction('ret');
end;
end;
end else begin
if argumsSize > 0 then begin
g.writeInstruction('ret', g.immediateToString(argumsSize));
end else begin
g.writeInstruction('ret');
end;
end;
end;
end;
if tree <> nil then begin
root := tree.root as SyntaxNode;
tree.deleteChildrens(root);
root.clearData();
end;
g.writeEmptyLine();
end;
procedure TranslatorBuilderOf16bitCode.translateTree(tree: SyntaxTree);
var
i: int;
limit: int;
aLabelNumber: int;
nodePosition: int;
oldLineNumber: int;
newLineNumber: int;
node: BuilderNode;
g: TextGenerator;
lexemes: Lexer;
stack: RegisterStack;
sourceName: String;
begin
g := self.generator;
lexemes := ((tree.root as SyntaxNode).associate as GlobalFunction).owner.lexemes;
stack := RegisterStack16bit.create(short_Array1d_create([
AX, CX
]), short_Array1d_create([
XMM0, XMM1, XMM2, XMM3
]), BX, SI);
oldLineNumber := 0;
sourceName := encode(lexemes.sourceName);
limit := tree.getNodesWithLabelNumberCount() - 1;
for i := 1 to limit do begin
node := tree.getNodeWithLabelNumber(i) as BuilderNode;
nodePosition := node.position;
if nodePosition >= 0 then begin
newLineNumber := lexemes.getLine(nodePosition);
if (newLineNumber > 0) and (oldLineNumber <> newLineNumber) then begin
g.writeCommentWithIdent(sourceName + '[' + intToString(newLineNumber) + ']: ' +
encode(lexemes.getSourceLine(newLineNumber)));
oldLineNumber := newLineNumber;
end;
end;
aLabelNumber := node.assignedLabelNumber;
if aLabelNumber >= 0 then begin
g.writeLabelShort(LABEL_LOCAL + intToString(aLabelNumber));
end;
translateNode(node, stack);
end;
end;
procedure TranslatorBuilderOf16bitCode.translateNode(node: SyntaxNode; stack: RegisterStack);
var
regInUse: boolean;
reg1: int;
reg2: int;
reg3: int;
count: int;
buffer: int;
nodeIndex: int;
nodeValue: int;
nodeLN: int;
parentValue: int;
parent: SyntaxNode;
nodeAsoc: _Interface;
nodeType: TypeDescriptor;
mem: MemoryLocation;
child: SyntaxNode;
funcNode: SyntaxNode;
funcType: TypeFunction;
funcReturn: TypeDescriptor;
goAlwaysTo: BuilderNode;
goIfTrueTo: BuilderNode;
goIfFalseTo: BuilderNode;
g: TextGenerator;
slbl: String;
simm: String;
smmb: String;
smmw: String;
smmt: String;
smm: String;
srb: String;
sr1: String;
sr2: String;
sr3: String;
sAL: String;
sCL: String;
sDL: String;
sAX: String;
sCX: String;
sDX: String;
sSP: String;
sBP: String;
sSI: String;
sDI: String;
sEDX: String;
sST0: String;
sST1: String;
sXMM0: String;
sXMM4: String;
sXMM5: String;
begin
g := self.generator;
sAL := g.registerToString(AL);
sCL := g.registerToString(CL);
sDL := g.registerToString(DL);
sAX := g.registerToString(AX);
sCX := g.registerToString(CX);
sDX := g.registerToString(DX);
sSP := g.registerToString(SP);
sBP := g.registerToString(BP);
sSI := g.registerToString(SI);
sDI := g.registerToString(DI);
sEDX := g.registerToString(EDX);
sST0 := g.registerToString(ST0);
sST1 := g.registerToString(ST1);
sXMM0 := g.registerToString(XMM0);
sXMM4 := g.registerToString(XMM4);
sXMM5 := g.registerToString(XMM5);
nodeIndex := node.index;
nodeValue := node.value;
nodeLN := node.labelNumber;
nodeAsoc := node.associate;
nodeType := node.dataType;
goAlwaysTo := node.goAlwaysToNode as BuilderNode;
goIfTrueTo := node.goIfTrueToNode as BuilderNode;
goIfFalseTo := node.goIfFalseToNode as BuilderNode;
parent := node.parent as SyntaxNode;
{ Узлы дерева разбора, которые возвращают значения не boolean типа и
не порождают инструкций, указаны в этом цикле: }
while (parent <> nil) and (parent.labelNumber < 0) do begin
buffer := parent.value;
if (buffer <> TranslatorTreeBuilder.EXPR_QUESTION) and
(buffer <> TranslatorTreeBuilder.EXPR_TYPE_CAST) then begin
break;
end;
nodeIndex := parent.index;
parent := parent.parent as SyntaxNode;
end;
if parent <> nil then begin
parentValue := parent.value;
end else begin
parentValue := -1;
end;
case nodeValue of
TranslatorTreeBuilder.OPERATOR_VARIABLE,
TranslatorTreeBuilder.BLOCK_WITH: begin
reg2 := stack.getRegAt(0);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
with nodeAsoc as LocalVariable do begin
nodeType := dataType;
mem := MemoryLocationTfasm.create(g, 0, '.' + encode(name));
end;
smm := mem.memoryToString(MNONE, 0);
smmt := mem.memoryToString(MREAL, 0);
case nodeType.kind of
TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_BYTE: begin
reg2 := AL + (reg2 and $0f);
sr2 := g.registerToString(reg2);
g.writeInstruction('mov', smm, sr2);
end;
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT:
g.writeInstruction('mov', smm, sr2);
TranslatorType.KIND_FLOAT:
g.writeInstruction('movss', smm, sr2);
TranslatorType.KIND_DOUBLE:
g.writeInstruction('movsd', smm, sr2);
TranslatorType.KIND_REAL:
g.writeInstruction('fstp', smmt);
end;
end;
TranslatorTreeBuilder.OPERATOR_DISPOSE: begin
stack.storeRegs(1, g);
stack.popRegs(1);
g.writeInstruction('call', FUNCTION_DISPOSE);
end;
TranslatorTreeBuilder.OPERATOR_SWITCH: begin
translateSwitch(node, stack);
end;
TranslatorTreeBuilder.OPERATOR_RETURN: begin
stack.popRegs(stack.size());
if (goAlwaysTo <> nil) and (goAlwaysTo.labelNumber <> nodeLN + 1) then begin
g.writeInstruction('jmp', LABEL_LOCAL + intToString(goAlwaysTo.assignedLabelNumber));
end;
end;
TranslatorTreeBuilder.EXPR_VALUE_NULL: begin
if needAllocateForPointer(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForPointer(g);
end else
if needAllocateForArray(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForArray(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('xor', sr1, sr1);
end;
TranslatorTreeBuilder.EXPR_VALUE_BOOLEAN: begin
if goAlwaysTo = nil then begin
reg1 := stack.allocateGPR16bit(g);
sr1 := g.registerToString(reg1);
if (nodeAsoc as BooleanAsObject).booleanValue() = true then begin
g.writeInstruction('mov', sr1, 'true');
end else begin
g.writeInstruction('mov', sr1, 'false');
end;
end else begin
g.writeInstruction('jmp', LABEL_LOCAL + intToString(goAlwaysTo.assignedLabelNumber));
end;
end;
TranslatorTreeBuilder.EXPR_VALUE_INT: begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
buffer := (nodeAsoc as IntegerAsObject).shortValue();
if buffer = 0 then begin
g.writeInstruction('xor', sr1, sr1);
end else begin
simm := g.immediateToStringShort(buffer);
g.writeInstruction('mov', sr1, simm);
end;
end;
TranslatorTreeBuilder.EXPR_VALUE_REAL: begin
case nodeType.kind of
TranslatorType.KIND_FLOAT: begin
reg1 := stack.allocateXMM(XSFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sr1, g.memoryToString(MNONE,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(
(nodeAsoc as FloatAsObject).floatValue()) * 4));
end;
TranslatorType.KIND_DOUBLE: begin
reg1 := stack.allocateXMM(XSDOUBLE, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movsd', sr1, g.memoryToString(MNONE,
LABEL_POOL_DOUBLE_CONTENT, programmeDoubles.indexAcquire(
(nodeAsoc as DoubleAsObject).doubleValue()) * 8));
end;
TranslatorType.KIND_REAL: begin
stack.allocateFPU(1, g);
g.writeInstruction('fld', g.memoryToStringDecOffset(MREAL,
LABEL_POOL_REAL_CONTENT, programmeReals.indexAcquire(
(nodeAsoc as RealAsObject).realValue()) * 10));
end;
end;
end;
TranslatorTreeBuilder.EXPR_VALUE_STRING: begin
if needAllocateForPointer(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForPointer(g);
end else
if needAllocateForArray(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForArray(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('lea', sr1, g.memoryToString(MNONE,
LABEL_POOL_STRING_CONTENT, programmeStrings.indexAcquire(
(nodeAsoc as UnicodeStringAsObject).unicodeStringValue()) * 4));
end;
TranslatorTreeBuilder.EXPR_GLOBAL_FUNCTION: begin
if needAllocateForPointer(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForPointer(g);
end else
if needAllocateForArray(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForArray(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('lea', sr1, g.memoryToString(MNONE,
getEntryFullName(nodeAsoc as GlobalFunction), 0));
end;
TranslatorTreeBuilder.EXPR_GLOBAL_VARIABLE,
TranslatorTreeBuilder.EXPR_LOCAL_VARIABLE,
TranslatorTreeBuilder.EXPR_ARRAY,
TranslatorTreeBuilder.EXPR_FIELD: begin
mem := getMemoryLocation(node, stack, false);
smm := mem.memoryToString(MNONE, 0);
smmb := mem.memoryToString(MBYTE, 0);
smmt := mem.memoryToString(MREAL, 0);
case nodeType.kind of
TranslatorType.KIND_BOOLEAN: begin
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
g.writeInstruction('movzx', sDX, smmb);
g.writeInstruction('test', sDX, sDX);
stack.restoreRegs(g); { регистр флагов – без изменений }
if goIfTrueTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
end else
if goIfFalseTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jnz',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end else begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
g.writeInstruction('jmp',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end;
end else begin
reg1 := stack.allocateGPR16bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movzx', sr1, smmb);
stack.restoreRegs(g);
end;
end;
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, smm);
stack.restoreRegs(g);
end;
TranslatorType.KIND_BYTE: begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('movsx', sr1, smmb);
stack.restoreRegs(g);
end;
TranslatorType.KIND_FLOAT: begin
reg1 := stack.allocateXMM(XSFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sr1, smm);
stack.restoreRegs(g);
end;
TranslatorType.KIND_DOUBLE: begin
reg1 := stack.allocateXMM(XSDOUBLE, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movsd', sr1, smm);
stack.restoreRegs(g);
end;
TranslatorType.KIND_REAL: begin
stack.allocateFPU(1, g);
g.writeInstruction('fld', smmt);
stack.restoreRegs(g);
end;
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC: begin
if needAllocateForPointer(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForPointer(g);
end else
if needAllocateForArray(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForArray(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, smm);
stack.restoreRegs(g);
end;
end;
end;
TranslatorTreeBuilder.EXPR_NEW_STRUCT: begin
stack.storeRegs(stack.base(), g);
count := node.getChildrensCount();
buffer := (nodeType as TypeStructure).structureSize;
g.writeInstruction('push', g.immediateToStringShort(buffer));
g.writeInstruction('call', FUNCTION_NEW_STRUCT);
if (count > 0) or needAllocateForPointer(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForPointer(g);
end else
if needAllocateForArray(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForArray(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> AX then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sAX);
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_NEW_ARRAY_BY_ELEMENTS: begin
stack.storeRegs(stack.base(), g);
count := node.getChildrensCount();
buffer := (nodeType as TypeArray).elementType.size;
g.writeInstruction('push', g.immediateToStringShort(count));
g.writeInstruction('push', g.immediateToStringShort(buffer));
g.writeInstruction('call', FUNCTION_NEW_ARRAY);
if (count > 0) or needAllocateForArray(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForArray(g);
end else
if needAllocateForPointer(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForPointer(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> AX then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sAX);
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_NEW_ARRAY_BY_LENGTH: begin
stack.storeRegs(stack.base(), g);
stack.popRegs(1);
buffer := (nodeType as TypeArray).elementType.size;
g.writeInstruction('push', g.immediateToStringShort(buffer));
g.writeInstruction('call', FUNCTION_NEW_ARRAY);
if needAllocateForPointer(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForPointer(g);
end else
if needAllocateForArray(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForArray(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> AX then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sAX);
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_FIELD_ASSIGN,
TranslatorTreeBuilder.EXPR_ARRAY_ASSIGN: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
case nodeValue of
TranslatorTreeBuilder.EXPR_FIELD_ASSIGN: begin
sr2 := g.registerToString(reg2);
mem := MemoryLocationTfasm.create(g, reg2, reg1,
getFieldFullName(nodeAsoc as StructureField));
smm := mem.memoryToString(MNONE, 0);
smmt := mem.memoryToString(MREAL, 0);
stack.popRegs(1);
case nodeType.kind of
TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_BYTE: begin
reg2 := AL + (reg2 and $0f);
sr2 := g.registerToString(reg2);
g.writeInstruction('mov', smm, sr2);
end;
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT:
g.writeInstruction('mov', smm, sr2);
TranslatorType.KIND_FLOAT:
g.writeInstruction('movss', smm, sr2);
TranslatorType.KIND_DOUBLE:
g.writeInstruction('movsd', smm, sr2);
TranslatorType.KIND_REAL:
g.writeInstruction('fstp', smmt);
end;
end;
TranslatorTreeBuilder.EXPR_ARRAY_ASSIGN: begin
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
mem := MemoryLocationTfasm.create(g, reg2, reg1, SI, '');
smm := mem.memoryToString(MNONE, 0);
smmt := mem.memoryToString(MREAL, 0);
stack.popRegs(1);
regInUse := stack.isUsedRegister(SI);
if regInUse then begin
g.writeInstruction('mov', sDX, sSI);
end;
if nodeIndex = 0 then begin
g.writeInstruction('xor', sSI, sSI);
end else begin
g.writeInstruction('mov', sSI, g.immediateToStringShort(nodeIndex));
end;
g.writeInstruction('call', FUNCTION_CHECK_ARRAY_INDEX);
case nodeType.kind of
TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_BYTE: begin
reg2 := AL + (reg2 and $0f);
sr2 := g.registerToString(reg2);
g.writeInstruction('mov', smm, sr2);
end;
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
g.writeInstruction('shl', sSI, g.immediateToStringByte(1));
g.writeInstruction('mov', smm, sr2);
end;
TranslatorType.KIND_FLOAT: begin
g.writeInstruction('shl', sSI, g.immediateToStringByte(2));
g.writeInstruction('movss', smm, sr2);
end;
TranslatorType.KIND_DOUBLE: begin
g.writeInstruction('shl', sSI, g.immediateToStringByte(3));
g.writeInstruction('movsd', smm, sr2);
end;
TranslatorType.KIND_REAL: begin
g.writeInstruction('imul', sSI, sSI, g.immediateToStringByte(10));
g.writeInstruction('fstp', smmt);
end;
end;
g.writeInstruction('mov', sr1, sDI);
if regInUse then begin
g.writeInstruction('mov', sSI, sDX);
end;
end;
end;
if nodeIndex = parent.getChildrensCount() - 1 then begin
node := parent;
nodeIndex := node.index;
parent := node.parent as SyntaxNode;
while (parent <> nil) and (parent.labelNumber < 0) do begin
buffer := parent.value;
if (buffer <> TranslatorTreeBuilder.EXPR_QUESTION) and
(buffer <> TranslatorTreeBuilder.EXPR_TYPE_CAST) then begin
break;
end;
nodeIndex := parent.index;
parent := parent.parent as SyntaxNode;
end;
if parent <> nil then begin
parentValue := parent.value;
end else begin
parentValue := -1;
end;
reg2 := reg1;
sr2 := g.registerToString(reg2);
stack.popRegs(1);
if needAllocateForPointer(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForPointer(g);
end else
if needAllocateForArray(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForArray(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> reg2 then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sr2);
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_CALL: begin
funcNode := node.getChild(node.getChildrensCount() - 1) as SyntaxNode;
funcType := funcNode.dataType as TypeFunction;
funcReturn := funcType.getReturnType();
if funcNode.value = TranslatorTreeBuilder.EXPR_GLOBAL_FUNCTION then begin
stack.storeRegs(stack.base(), g);
g.writeInstruction('call', getEntryFullName(funcNode.associate as GlobalFunction));
end else begin
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
stack.popRegs(1);
stack.storeRegs(stack.base(), g);
g.writeInstruction('call', sr1);
end;
stack.popRegs(funcType.getArgumentsCount());
case TranslatorTreeBuilder.getTypeKind(nodeType) of
TranslatorType.KIND_BOOLEAN: begin
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
g.writeInstruction('test', sAX, sAX);
stack.restoreRegs(g); { регистр флагов – без изменений }
if goIfTrueTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
end else
if goIfFalseTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jnz',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end else begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
g.writeInstruction('jmp',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end;
end else begin
reg1 := stack.allocateGPR16bit(g);
if reg1 <> AX then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sAX);
end;
stack.restoreRegs(g);
end;
end;
TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE, TranslatorType.KIND_SHORT: begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> AX then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sAX);
end;
stack.restoreRegs(g);
end;
TranslatorType.KIND_FLOAT: begin
reg1 := stack.allocateXMM(XSFLOAT, g);
if reg1 <> XMM0 + XSFLOAT then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sr1, sXMM0);
end;
stack.restoreRegs(g);
end;
TranslatorType.KIND_DOUBLE: begin
reg1 := stack.allocateXMM(XSDOUBLE, g);
if reg1 <> XMM0 + XSDOUBLE then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('movsd', sr1, sXMM0);
end;
stack.restoreRegs(g);
end;
TranslatorType.KIND_REAL: begin
stack.allocateFPU(1, g);
stack.restoreRegs(g);
end;
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC: begin
if needAllocateForPointer(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForPointer(g);
end else
if needAllocateForArray(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForArray(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> AX then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sAX);
end;
stack.restoreRegs(g);
end;
else
if (nodeType = nil) and (funcReturn <> nil) and
(funcReturn.kind = TranslatorType.KIND_REAL) then begin
g.writeInstruction('ffree', sST0);
g.writeInstruction('fincstp');
end;
stack.restoreRegs(g);
end;
end;
TranslatorTreeBuilder.EXPR_INCR_POST,
TranslatorTreeBuilder.EXPR_DECR_POST,
TranslatorTreeBuilder.EXPR_INCR_PRED,
TranslatorTreeBuilder.EXPR_DECR_PRED: begin
regInUse := (nodeValue = TranslatorTreeBuilder.EXPR_INCR_POST) or
(nodeValue = TranslatorTreeBuilder.EXPR_DECR_POST);
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, false);
smm := mem.memoryToString(MNONE, 0);
smmb := mem.memoryToString(MBYTE, 0);
smmw := mem.memoryToString(MWORD, 0);
smmt := mem.memoryToString(MREAL, 0);
case child.dataType.kind of
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
if nodeType <> nil then begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
if regInUse then begin
g.writeInstruction('mov', sDX, smm);
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST:
g.writeInstruction('inc', smmw);
TranslatorTreeBuilder.EXPR_DECR_POST:
g.writeInstruction('dec', smmw);
end;
g.writeInstruction('mov', sr1, sDX);
end else begin
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('inc', smmw);
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('dec', smmw);
end;
g.writeInstruction('mov', sr1, smm);
end;
end else begin
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST,
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('inc', smmw);
TranslatorTreeBuilder.EXPR_DECR_POST,
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('dec', smmw);
end;
end;
end;
TranslatorType.KIND_BYTE: begin
if nodeType <> nil then begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
if regInUse then begin
g.writeInstruction('movsx', sDX, smmb);
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST:
g.writeInstruction('inc', smmb);
TranslatorTreeBuilder.EXPR_DECR_POST:
g.writeInstruction('dec', smmb);
end;
g.writeInstruction('mov', sr1, sDX);
end else begin
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('inc', smmb);
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('dec', smmb);
end;
g.writeInstruction('movsx', sr1, smmb);
end;
end else begin
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST,
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('inc', smmb);
TranslatorTreeBuilder.EXPR_DECR_POST,
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('dec', smmb);
end;
end;
end;
TranslatorType.KIND_FLOAT: begin
if nodeType <> nil then begin
reg1 := stack.allocateXMM(XSFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sr1, smm);
if regInUse then begin
g.writeInstruction('movss', sXMM4, sr1);
g.writeInstruction('movss', sXMM5, g.memoryToString(MNONE,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST:
g.writeInstruction('addss', sXMM4, sXMM5);
TranslatorTreeBuilder.EXPR_DECR_POST:
g.writeInstruction('subss', sXMM4, sXMM5);
end;
g.writeInstruction('movss', smm, sXMM4);
end else begin
g.writeInstruction('movss', sXMM4, g.memoryToString(MNONE,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('addss', sr1, sXMM4);
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('subss', sr1, sXMM4);
end;
g.writeInstruction('movss', smm, sr1);
end;
end else begin
g.writeInstruction('movss', sXMM4, smm);
g.writeInstruction('movss', sXMM5, g.memoryToString(MNONE,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST,
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('addss', sXMM4, sXMM5);
TranslatorTreeBuilder.EXPR_DECR_POST,
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('subss', sXMM4, sXMM5);
end;
g.writeInstruction('movss', smm, sXMM4);
end;
end;
TranslatorType.KIND_DOUBLE: begin
if nodeType <> nil then begin
reg1 := stack.allocateXMM(XSDOUBLE, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movsd', sr1, smm);
if regInUse then begin
g.writeInstruction('movsd', sXMM4, sr1);
g.writeInstruction('movsd', sXMM5, g.memoryToString(MNONE,
LABEL_POOL_DOUBLE_CONTENT, programmeDoubles.indexAcquire(1) * 8));
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST:
g.writeInstruction('addsd', sXMM4, sXMM5);
TranslatorTreeBuilder.EXPR_DECR_POST:
g.writeInstruction('subsd', sXMM4, sXMM5);
end;
g.writeInstruction('movsd', smm, sXMM4);
end else begin
g.writeInstruction('movsd', sXMM4, g.memoryToString(MNONE,
LABEL_POOL_DOUBLE_CONTENT, programmeDoubles.indexAcquire(1) * 8));
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('addsd', sr1, sXMM4);
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('subsd', sr1, sXMM4);
end;
g.writeInstruction('movsd', smm, sr1);
end;
end else begin
g.writeInstruction('movsd', sXMM4, smm);
g.writeInstruction('movsd', sXMM5, g.memoryToString(MNONE,
LABEL_POOL_DOUBLE_CONTENT, programmeDoubles.indexAcquire(1) * 8));
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST,
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('addsd', sXMM4, sXMM5);
TranslatorTreeBuilder.EXPR_DECR_POST,
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('subsd', sXMM4, sXMM5);
end;
g.writeInstruction('movsd', smm, sXMM4);
end;
end;
TranslatorType.KIND_REAL: begin
if nodeType <> nil then begin
if regInUse then begin
stack.allocateFPU(2, g);
stack.popRegs(1);
g.writeInstruction('fld', smmt);
g.writeInstruction('fld', sST0);
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST:
g.writeInstruction('fadd', g.memoryToString(MFLOAT,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
TranslatorTreeBuilder.EXPR_DECR_POST:
g.writeInstruction('fsub', g.memoryToString(MFLOAT,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
end;
g.writeInstruction('fstp', smmt);
end else begin
stack.allocateFPU(1, g);
g.writeInstruction('fld', smmt);
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('fadd', g.memoryToString(MFLOAT,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('fsub', g.memoryToString(MFLOAT,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
end;
g.writeInstruction('fstp', smmt);
g.writeInstruction('fld', smmt);
end;
end else begin
stack.allocateFPU(1, g);
stack.popRegs(1);
g.writeInstruction('fld', smmt);
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST,
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('fadd', g.memoryToString(MFLOAT,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
TranslatorTreeBuilder.EXPR_DECR_POST,
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('fsub', g.memoryToString(MFLOAT,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
end;
g.writeInstruction('fstp', smmt);
end;
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_TYPE_CAST: begin
reg2 := stack.getRegAt(0);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_BYTE,
TranslatorType.KIND_SHORT: {%region исходный тип данных – short}
case nodeType.kind of
TranslatorType.KIND_BYTE: begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
srb := g.registerToString(AL + (reg2 and $0f));
g.writeInstruction('movsx', sr1, srb);
end;
TranslatorType.KIND_FLOAT: begin
reg1 := stack.allocateXMM(XSFLOAT, g);
sr1 := g.registerToString(reg1);
if reg2 = AX then begin
g.writeInstruction('cwd');
end else begin
g.writeInstruction('mov', sDX, sr2);
g.writeInstruction('sar', sDX, g.immediateToStringByte($0f));
end;
g.writeInstruction('push', sDX);
g.writeInstruction('push', sr2);
g.writeInstruction('mov', sDI, sSP);
g.writeInstruction('sub', sDI, sBP);
g.writeInstruction('cvtsi2ss', sr1, g.memoryToString(MINT, BP, DI, 0));
g.writeInstruction('lea', sSP, g.memoryToString(MNONE, BP, DI, 4));
end;
TranslatorType.KIND_DOUBLE: begin
reg1 := stack.allocateXMM(XSDOUBLE, g);
sr1 := g.registerToString(reg1);
if reg2 = AX then begin
g.writeInstruction('cwd');
end else begin
g.writeInstruction('mov', sDX, sr2);
g.writeInstruction('sar', sDX, g.immediateToStringByte($0f));
end;
g.writeInstruction('push', sDX);
g.writeInstruction('push', sr2);
g.writeInstruction('mov', sDI, sSP);
g.writeInstruction('sub', sDI, sBP);
g.writeInstruction('cvtsi2sd', sr1, g.memoryToString(MINT, BP, DI, 0));
g.writeInstruction('lea', sSP, g.memoryToString(MNONE, BP, DI, 4));
end;
TranslatorType.KIND_REAL: begin
stack.allocateFPU(1, g);
if reg2 = AX then begin
g.writeInstruction('cwd');
end else begin
g.writeInstruction('mov', sDX, sr2);
g.writeInstruction('sar', sDX, g.immediateToStringByte($0f));
end;
g.writeInstruction('push', sDX);
g.writeInstruction('push', sr2);
g.writeInstruction('mov', sDI, sSP);
g.writeInstruction('sub', sDI, sBP);
g.writeInstruction('fild', g.memoryToString(MINT, BP, DI, 0));
g.writeInstruction('lea', sSP, g.memoryToString(MNONE, BP, DI, 4));
end;
end;
{%endregion}
TranslatorType.KIND_CHAR: {%region исходный тип данных – char}
case nodeType.kind of
TranslatorType.KIND_BYTE: begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
srb := g.registerToString(AL + (reg2 and $0f));
g.writeInstruction('movsx', sr1, srb);
end;
TranslatorType.KIND_FLOAT: begin
reg1 := stack.allocateXMM(XSFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('push', g.immediateToStringShort(0));
g.writeInstruction('push', sr2);
g.writeInstruction('mov', sDI, sSP);
g.writeInstruction('sub', sDI, sBP);
g.writeInstruction('cvtsi2ss', sr1, g.memoryToString(MINT, BP, DI, 0));
g.writeInstruction('lea', sSP, g.memoryToString(MNONE, BP, DI, 4));
end;
TranslatorType.KIND_DOUBLE: begin
reg1 := stack.allocateXMM(XSDOUBLE, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('push', g.immediateToStringShort(0));
g.writeInstruction('push', sr2);
g.writeInstruction('mov', sDI, sSP);
g.writeInstruction('sub', sDI, sBP);
g.writeInstruction('cvtsi2sd', sr1, g.memoryToString(MINT, BP, DI, 0));
g.writeInstruction('lea', sSP, g.memoryToString(MNONE, BP, DI, 4));
end;
TranslatorType.KIND_REAL: begin
stack.allocateFPU(1, g);
g.writeInstruction('push', g.immediateToStringShort(0));
g.writeInstruction('push', sr2);
g.writeInstruction('mov', sDI, sSP);
g.writeInstruction('sub', sDI, sBP);
g.writeInstruction('fild', g.memoryToString(MINT, BP, DI, 0));
g.writeInstruction('lea', sSP, g.memoryToString(MNONE, BP, DI, 4));
end;
end;
{%endregion}
TranslatorType.KIND_FLOAT: {%region исходный тип данных – float}
case nodeType.kind of
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sXMM4, sr2);
g.writeInstruction('call', FUNCTION_FLOAT_TO_SHORT);
g.writeInstruction('mov', sr1, sDX);
end;
TranslatorType.KIND_BYTE: begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sXMM4, sr2);
g.writeInstruction('call', FUNCTION_FLOAT_TO_SHORT);
g.writeInstruction('movsx', sr1, sDL);
end;
TranslatorType.KIND_DOUBLE: begin
reg1 := stack.allocateXMM(XSDOUBLE, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('cvtss2sd', sr1, sr2);
end;
TranslatorType.KIND_REAL: begin
stack.allocateFPU(1, g);
smm := g.memoryToString(MNONE, BP, DI, 0);
g.writeInstruction('mov', sDI, sSP);
g.writeInstruction('sub', sDI, sBP);
g.writeInstruction('lea', sDI, g.memoryToString(MNONE, DI, -4));
g.writeInstruction('lea', sSP, smm);
g.writeInstruction('movss', smm, sr2);
g.writeInstruction('fld', g.memoryToString(MFLOAT, BP, DI, 0));
g.writeInstruction('lea', sSP, g.memoryToString(MNONE, BP, DI, 4));
end;
end;
{%endregion}
TranslatorType.KIND_DOUBLE: {%region исходный тип данных – double}
case nodeType.kind of
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('movsd', sXMM4, sr2);
g.writeInstruction('call', FUNCTION_DOUBLE_TO_SHORT);
g.writeInstruction('mov', sr1, sDX);
end;
TranslatorType.KIND_BYTE: begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('movsd', sXMM4, sr2);
g.writeInstruction('call', FUNCTION_DOUBLE_TO_SHORT);
g.writeInstruction('movsx', sr1, sDL);
end;
TranslatorType.KIND_FLOAT: begin
reg1 := stack.allocateXMM(XSFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('cvtsd2ss', sr1, sr2);
end;
TranslatorType.KIND_REAL: begin
stack.allocateFPU(1, g);
smm := g.memoryToString(MNONE, BP, DI, 0);
g.writeInstruction('mov', sDI, sSP);
g.writeInstruction('sub', sDI, sBP);
g.writeInstruction('lea', sDI, g.memoryToString(MNONE, DI, -8));
g.writeInstruction('lea', sSP, smm);
g.writeInstruction('movsd', smm, sr2);
g.writeInstruction('fld', g.memoryToString(MDOUBLE, BP, DI, 0));
g.writeInstruction('lea', sSP, g.memoryToString(MNONE, BP, DI, 8));
end;
end;
{%endregion}
TranslatorType.KIND_REAL: {%region исходный тип данных – real}
case nodeType.kind of
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('call', FUNCTION_REAL_TO_SHORT);
g.writeInstruction('mov', sr1, sDX);
end;
TranslatorType.KIND_BYTE: begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('call', FUNCTION_REAL_TO_SHORT);
g.writeInstruction('movsx', sr1, sDL);
end;
TranslatorType.KIND_FLOAT: begin
reg1 := stack.allocateXMM(XSFLOAT, g);
sr1 := g.registerToString(reg1);
smm := g.memoryToString(MNONE, BP, DI, 0);
g.writeInstruction('mov', sDI, sSP);
g.writeInstruction('sub', sDI, sBP);
g.writeInstruction('lea', sDI, g.memoryToString(MNONE, DI, -4));
g.writeInstruction('lea', sSP, smm);
g.writeInstruction('fstp', g.memoryToString(MFLOAT, BP, DI, 0));
g.writeInstruction('movss', sr1, smm);
g.writeInstruction('lea', sSP, g.memoryToString(MNONE, BP, DI, 4));
end;
TranslatorType.KIND_DOUBLE: begin
reg1 := stack.allocateXMM(XSDOUBLE, g);
sr1 := g.registerToString(reg1);
smm := g.memoryToString(MNONE, BP, DI, 0);
g.writeInstruction('mov', sDI, sSP);
g.writeInstruction('sub', sDI, sBP);
g.writeInstruction('lea', sDI, g.memoryToString(MNONE, DI, -8));
g.writeInstruction('lea', sSP, smm);
g.writeInstruction('fstp', g.memoryToString(MDOUBLE, BP, DI, 0));
g.writeInstruction('movsd', sr1, smm);
g.writeInstruction('lea', sSP, g.memoryToString(MNONE, BP, DI, 8));
end;
end;
{%endregion}
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_SNOTB: begin
reg2 := stack.getRegAt(0);
stack.popRegs(1);
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
if reg1 <> reg2 then begin
sr2 := g.registerToString(reg2);
g.writeInstruction('mov', sr1, sr2);
end;
g.writeInstruction('not', sr1);
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_SNEG: begin
reg2 := stack.getRegAt(0);
sr2 := g.registerToString(reg2);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_SHORT: begin
stack.popRegs(1);
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
if reg1 <> reg2 then begin
g.writeInstruction('mov', sr1, sr2);
end;
g.writeInstruction('neg', sr1);
stack.restoreRegs(g);
end;
TranslatorType.KIND_FLOAT: begin
g.writeInstruction('movss', sXMM4, sr2);
g.writeInstruction('movss', sr2, g.memoryToString(MNONE,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(0) * 4));
g.writeInstruction('subss', sr2, sXMM4);
end;
TranslatorType.KIND_DOUBLE: begin
g.writeInstruction('movsd', sXMM4, sr2);
g.writeInstruction('movsd', sr2, g.memoryToString(MNONE,
LABEL_POOL_DOUBLE_CONTENT, programmeDoubles.indexAcquire(0) * 8));
g.writeInstruction('subsd', sr2, sXMM4);
end;
TranslatorType.KIND_REAL: begin
g.writeInstruction('fchs');
end;
end;
end;
TranslatorTreeBuilder.EXPR_SADD,
TranslatorTreeBuilder.EXPR_SSUB,
TranslatorTreeBuilder.EXPR_SMULL: begin
reg2 := stack.getRegAt(1);
reg3 := stack.getRegAt(0);
sr2 := g.registerToString(reg2);
sr3 := g.registerToString(reg3);
stack.popRegs(1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_SHORT: begin
stack.popRegs(1);
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
if reg1 <> reg2 then begin
g.writeInstruction('mov', sr1, sr2);
end;
case nodeValue of
TranslatorTreeBuilder.EXPR_SADD:
g.writeInstruction('add', sr1, sr3);
TranslatorTreeBuilder.EXPR_SSUB:
g.writeInstruction('sub', sr1, sr3);
TranslatorTreeBuilder.EXPR_SMULL:
g.writeInstruction('imul', sr1, sr3);
end;
end;
TranslatorType.KIND_FLOAT: begin
case nodeValue of
TranslatorTreeBuilder.EXPR_SADD:
g.writeInstruction('addss', sr2, sr3);
TranslatorTreeBuilder.EXPR_SSUB:
g.writeInstruction('subss', sr2, sr3);
TranslatorTreeBuilder.EXPR_SMULL:
g.writeInstruction('mulss', sr2, sr3);
end;
end;
TranslatorType.KIND_DOUBLE: begin
case nodeValue of
TranslatorTreeBuilder.EXPR_SADD:
g.writeInstruction('addsd', sr2, sr3);
TranslatorTreeBuilder.EXPR_SSUB:
g.writeInstruction('subsd', sr2, sr3);
TranslatorTreeBuilder.EXPR_SMULL:
g.writeInstruction('mulsd', sr2, sr3);
end;
end;
TranslatorType.KIND_REAL: begin
case nodeValue of
TranslatorTreeBuilder.EXPR_SADD:
g.writeInstruction('faddp');
TranslatorTreeBuilder.EXPR_SSUB:
g.writeInstruction('fsubp');
TranslatorTreeBuilder.EXPR_SMULL:
g.writeInstruction('fmulp');
end;
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_SDIVS,
TranslatorTreeBuilder.EXPR_SDIVU: begin
reg2 := stack.getRegAt(1);
reg3 := stack.getRegAt(0);
sr2 := g.registerToString(reg2);
sr3 := g.registerToString(reg3);
stack.popRegs(1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_SHORT: begin
stack.popRegs(1);
regInUse := stack.isUsedRegister(AX);
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
if reg3 = AX then begin
g.writeInstruction('xchg', sr3, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_SDIVS: begin
g.writeInstruction('cwd');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.EXPR_SDIVU: begin
g.writeInstruction('xor', sDX, sDX);
g.writeInstruction('div', sr2);
end;
end;
if reg1 <> AX then begin
g.writeInstruction('mov', sr1, sAX);
end;
end else begin
if regInUse then begin
g.writeInstruction('mov', sDI, sAX);
end;
if reg2 <> AX then begin
g.writeInstruction('mov', sAX, sr2);
end;
case nodeValue of
TranslatorTreeBuilder.EXPR_SDIVS: begin
g.writeInstruction('cwd');
g.writeInstruction('idiv', sr3);
end;
TranslatorTreeBuilder.EXPR_SDIVU: begin
g.writeInstruction('xor', sDX, sDX);
g.writeInstruction('div', sr3);
end;
end;
if reg1 <> AX then begin
g.writeInstruction('mov', sr1, sAX);
end;
if regInUse then begin
g.writeInstruction('mov', sAX, sDI);
end;
end;
end;
TranslatorType.KIND_FLOAT: begin
g.writeInstruction('divss', sr2, sr3);
end;
TranslatorType.KIND_DOUBLE: begin
g.writeInstruction('divsd', sr2, sr3);
end;
TranslatorType.KIND_REAL: begin
g.writeInstruction('fdivp');
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_SREMS,
TranslatorTreeBuilder.EXPR_SREMU: begin
reg2 := stack.getRegAt(1);
reg3 := stack.getRegAt(0);
sr2 := g.registerToString(reg2);
sr3 := g.registerToString(reg3);
stack.popRegs(1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_SHORT: begin
stack.popRegs(1);
regInUse := stack.isUsedRegister(AX);
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
if reg3 = AX then begin
g.writeInstruction('xchg', sr3, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_SREMS: begin
g.writeInstruction('cwd');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.EXPR_SREMU: begin
g.writeInstruction('xor', sDX, sDX);
g.writeInstruction('div', sr2);
end;
end;
if reg1 <> DX then begin
g.writeInstruction('mov', sr1, sDX);
end;
end else begin
if regInUse then begin
g.writeInstruction('mov', sDI, sAX);
end;
if reg2 <> AX then begin
g.writeInstruction('mov', sAX, sr2);
end;
case nodeValue of
TranslatorTreeBuilder.EXPR_SREMS: begin
g.writeInstruction('cwd');
g.writeInstruction('idiv', sr3);
end;
TranslatorTreeBuilder.EXPR_SREMU: begin
g.writeInstruction('xor', sDX, sDX);
g.writeInstruction('div', sr3);
end;
end;
if reg1 <> DX then begin
g.writeInstruction('mov', sr1, sDX);
end;
if regInUse then begin
g.writeInstruction('mov', sAX, sDI);
end;
end;
end;
TranslatorType.KIND_REAL: begin
regInUse := stack.isUsedRegister(AX);
if regInUse then begin
g.writeInstruction('mov', sDX, sAX);
end;
g.writeInstruction('fxch');
g.writeLabelShort(LABEL_ANONYMOUS);
g.writeInstruction('fprem');
g.writeInstruction('fnstsw', sAX);
g.writeInstruction('test', sAX, g.immediateToStringShort($0400));
g.writeInstruction('jnz', LABEL_PRECEDING);
g.writeInstruction('fstp', sST1);
if regInUse then begin
g.writeInstruction('mov', sAX, sDX);
end;
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_SSLL,
TranslatorTreeBuilder.EXPR_SSRA,
TranslatorTreeBuilder.EXPR_SSRL: begin
child := node.getChild(1) as SyntaxNode;
if child.value <> TranslatorTreeBuilder.EXPR_VALUE_INT then begin
reg2 := stack.getRegAt(1);
reg3 := stack.getRegAt(0);
stack.popRegs(2);
regInUse := stack.isUsedRegister(CX);
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
sr3 := g.registerToString(reg3);
if reg2 = CX then begin
g.writeInstruction('xchg', sr3, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_SSLL:
g.writeInstruction('shl', sr3, sCL);
TranslatorTreeBuilder.EXPR_SSRA:
g.writeInstruction('sar', sr3, sCL);
TranslatorTreeBuilder.EXPR_SSRL:
g.writeInstruction('shr', sr3, sCL);
end;
if reg1 <> reg3 then begin
g.writeInstruction('mov', sr1, sr3);
end;
end else begin
if regInUse then begin
g.writeInstruction('mov', sDX, sCX);
end;
if reg3 <> CX then begin
g.writeInstruction('mov', sCX, sr3);
end;
case nodeValue of
TranslatorTreeBuilder.EXPR_SSLL:
g.writeInstruction('shl', sr2, sCL);
TranslatorTreeBuilder.EXPR_SSRA:
g.writeInstruction('sar', sr2, sCL);
TranslatorTreeBuilder.EXPR_SSRL:
g.writeInstruction('shr', sr2, sCL);
end;
if reg1 <> reg2 then begin
g.writeInstruction('mov', sr1, sr2);
end;
if regInUse then begin
g.writeInstruction('mov', sCX, sDX);
end;
end;
end else begin
reg2 := stack.getRegAt(0);
buffer := (child.associate as IntegerAsObject).byteValue();
simm := g.immediateToStringByte(buffer);
stack.popRegs(1);
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
case nodeValue of
TranslatorTreeBuilder.EXPR_SSLL:
g.writeInstruction('shl', sr2, simm);
TranslatorTreeBuilder.EXPR_SSRA:
g.writeInstruction('sar', sr2, simm);
TranslatorTreeBuilder.EXPR_SSRL:
g.writeInstruction('shr', sr2, simm);
end;
if reg1 <> reg2 then begin
g.writeInstruction('mov', sr1, sr2);
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_SGT,
TranslatorTreeBuilder.EXPR_SGE,
TranslatorTreeBuilder.EXPR_SLT,
TranslatorTreeBuilder.EXPR_SLE,
TranslatorTreeBuilder.EXPR_SEQ,
TranslatorTreeBuilder.EXPR_SNE: begin
reg2 := stack.getRegAt(1);
reg3 := stack.getRegAt(0);
sr2 := g.registerToString(reg2);
sr3 := g.registerToString(reg3);
stack.popRegs(2);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_SHORT: begin
g.writeInstruction('cmp', sr2, sr3);
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.restoreRegs(g); { регистр флагов – без изменений }
if goIfTrueTo.labelNumber = nodeLN + 1 then begin
slbl := LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber);
case nodeValue of
TranslatorTreeBuilder.EXPR_SGT:
g.writeInstruction('jle', slbl);
TranslatorTreeBuilder.EXPR_SGE:
g.writeInstruction('jl', slbl);
TranslatorTreeBuilder.EXPR_SLT:
g.writeInstruction('jge', slbl);
TranslatorTreeBuilder.EXPR_SLE:
g.writeInstruction('jg', slbl);
TranslatorTreeBuilder.EXPR_SEQ:
g.writeInstruction('jne', slbl);
TranslatorTreeBuilder.EXPR_SNE:
g.writeInstruction('je', slbl);
end;
end else
if goIfFalseTo.labelNumber = nodeLN + 1 then begin
slbl := LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber);
case nodeValue of
TranslatorTreeBuilder.EXPR_SGT:
g.writeInstruction('jg', slbl);
TranslatorTreeBuilder.EXPR_SGE:
g.writeInstruction('jge', slbl);
TranslatorTreeBuilder.EXPR_SLT:
g.writeInstruction('jl', slbl);
TranslatorTreeBuilder.EXPR_SLE:
g.writeInstruction('jle', slbl);
TranslatorTreeBuilder.EXPR_SEQ:
g.writeInstruction('je', slbl);
TranslatorTreeBuilder.EXPR_SNE:
g.writeInstruction('jne', slbl);
end;
end else begin
slbl := LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber);
case nodeValue of
TranslatorTreeBuilder.EXPR_SGT:
g.writeInstruction('jle', slbl);
TranslatorTreeBuilder.EXPR_SGE:
g.writeInstruction('jl', slbl);
TranslatorTreeBuilder.EXPR_SLT:
g.writeInstruction('jge', slbl);
TranslatorTreeBuilder.EXPR_SLE:
g.writeInstruction('jg', slbl);
TranslatorTreeBuilder.EXPR_SEQ:
g.writeInstruction('jne', slbl);
TranslatorTreeBuilder.EXPR_SNE:
g.writeInstruction('je', slbl);
end;
g.writeInstruction('jmp',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end;
end else begin
reg1 := stack.allocateGPR16bit(g); { регистр флагов – без изменений }
srb := g.registerToString(AL + (reg1 and $0f));
sr1 := g.registerToString(reg1);
case nodeValue of
TranslatorTreeBuilder.EXPR_SGT:
g.writeInstruction('setg', srb);
TranslatorTreeBuilder.EXPR_SGE:
g.writeInstruction('setge', srb);
TranslatorTreeBuilder.EXPR_SLT:
g.writeInstruction('setl', srb);
TranslatorTreeBuilder.EXPR_SLE:
g.writeInstruction('setle', srb);
TranslatorTreeBuilder.EXPR_SEQ:
g.writeInstruction('sete', srb);
TranslatorTreeBuilder.EXPR_SNE:
g.writeInstruction('setne', srb);
end;
g.writeInstruction('movzx', sr1, srb);
stack.restoreRegs(g);
end;
end;
TranslatorType.KIND_FLOAT: begin
case nodeValue of
TranslatorTreeBuilder.EXPR_SGT: begin
g.writeInstruction('cmpss', sr3, sr2, g.immediateToStringByte(1));
g.writeInstruction('pmovmskb', sEDX, sr3);
end;
TranslatorTreeBuilder.EXPR_SGE: begin
g.writeInstruction('cmpss', sr3, sr2, g.immediateToStringByte(2));
g.writeInstruction('pmovmskb', sEDX, sr3);
end;
TranslatorTreeBuilder.EXPR_SLT: begin
g.writeInstruction('cmpss', sr2, sr3, g.immediateToStringByte(1));
g.writeInstruction('pmovmskb', sEDX, sr2);
end;
TranslatorTreeBuilder.EXPR_SLE: begin
g.writeInstruction('cmpss', sr2, sr3, g.immediateToStringByte(2));
g.writeInstruction('pmovmskb', sEDX, sr2);
end;
TranslatorTreeBuilder.EXPR_SEQ: begin
g.writeInstruction('cmpss', sr2, sr3, g.immediateToStringByte(0));
g.writeInstruction('pmovmskb', sEDX, sr2);
end;
TranslatorTreeBuilder.EXPR_SNE: begin
g.writeInstruction('cmpss', sr2, sr3, g.immediateToStringByte(4));
g.writeInstruction('pmovmskb', sEDX, sr2);
end;
end;
g.writeInstruction('test', sDX, g.immediateToStringShort($08));
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.restoreRegs(g); { регистр флагов – без изменений }
if goIfTrueTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
end else
if goIfFalseTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jnz',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end else begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
g.writeInstruction('jmp',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end;
end else begin
reg1 := stack.allocateGPR16bit(g); { регистр флагов – без изменений }
srb := g.registerToString(AL + (reg1 and $0f));
sr1 := g.registerToString(reg1);
g.writeInstruction('setnz', srb);
g.writeInstruction('movzx', sr1, srb);
stack.restoreRegs(g);
end;
end;
TranslatorType.KIND_DOUBLE: begin
case nodeValue of
TranslatorTreeBuilder.EXPR_SGT: begin
g.writeInstruction('cmpsd', sr3, sr2, g.immediateToStringByte(1));
g.writeInstruction('pmovmskb', sEDX, sr3);
end;
TranslatorTreeBuilder.EXPR_SGE: begin
g.writeInstruction('cmpsd', sr3, sr2, g.immediateToStringByte(2));
g.writeInstruction('pmovmskb', sEDX, sr3);
end;
TranslatorTreeBuilder.EXPR_SLT: begin
g.writeInstruction('cmpsd', sr2, sr3, g.immediateToStringByte(1));
g.writeInstruction('pmovmskb', sEDX, sr2);
end;
TranslatorTreeBuilder.EXPR_SLE: begin
g.writeInstruction('cmpsd', sr2, sr3, g.immediateToStringByte(2));
g.writeInstruction('pmovmskb', sEDX, sr2);
end;
TranslatorTreeBuilder.EXPR_SEQ: begin
g.writeInstruction('cmpsd', sr2, sr3, g.immediateToStringByte(0));
g.writeInstruction('pmovmskb', sEDX, sr2);
end;
TranslatorTreeBuilder.EXPR_SNE: begin
g.writeInstruction('cmpsd', sr2, sr3, g.immediateToStringByte(4));
g.writeInstruction('pmovmskb', sEDX, sr2);
end;
end;
g.writeInstruction('test', sDX, g.immediateToStringShort($80));
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.restoreRegs(g); { регистр флагов – без изменений }
if goIfTrueTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
end else
if goIfFalseTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jnz',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end else begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
g.writeInstruction('jmp',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end;
end else begin
reg1 := stack.allocateGPR16bit(g); { регистр флагов – без изменений }
srb := g.registerToString(AL + (reg1 and $0f));
sr1 := g.registerToString(reg1);
g.writeInstruction('setnz', srb);
g.writeInstruction('movzx', sr1, srb);
stack.restoreRegs(g);
end;
end;
TranslatorType.KIND_REAL: begin
g.writeInstruction('fxch');
g.writeInstruction('fcomip', sST0, sST1);
g.writeInstruction('ffree', sST0);
g.writeInstruction('fincstp');
g.writeInstruction('jnp', LABEL_FOLLOWING);
g.writeInstruction('mov', sDL, g.immediateToStringByte($ff));
g.writeInstruction('or', sDX, sDX);
if (nodeValue <> TranslatorTreeBuilder.EXPR_SLT) and
(nodeValue <> TranslatorTreeBuilder.EXPR_SLE) then begin
g.writeInstruction('stc');
end;
g.writeLabelShort(LABEL_ANONYMOUS);
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.restoreRegs(g); { регистр флагов – без изменений }
if goIfTrueTo.labelNumber = nodeLN + 1 then begin
slbl := LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber);
case nodeValue of
TranslatorTreeBuilder.EXPR_SGT:
g.writeInstruction('jbe', slbl);
TranslatorTreeBuilder.EXPR_SGE:
g.writeInstruction('jb', slbl);
TranslatorTreeBuilder.EXPR_SLT:
g.writeInstruction('jae', slbl);
TranslatorTreeBuilder.EXPR_SLE:
g.writeInstruction('ja', slbl);
TranslatorTreeBuilder.EXPR_SEQ:
g.writeInstruction('jne', slbl);
TranslatorTreeBuilder.EXPR_SNE:
g.writeInstruction('je', slbl);
end;
end else
if goIfFalseTo.labelNumber = nodeLN + 1 then begin
slbl := LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber);
case nodeValue of
TranslatorTreeBuilder.EXPR_SGT:
g.writeInstruction('ja', slbl);
TranslatorTreeBuilder.EXPR_SGE:
g.writeInstruction('jae', slbl);
TranslatorTreeBuilder.EXPR_SLT:
g.writeInstruction('jb', slbl);
TranslatorTreeBuilder.EXPR_SLE:
g.writeInstruction('jbe', slbl);
TranslatorTreeBuilder.EXPR_SEQ:
g.writeInstruction('je', slbl);
TranslatorTreeBuilder.EXPR_SNE:
g.writeInstruction('jne', slbl);
end;
end else begin
slbl := LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber);
case nodeValue of
TranslatorTreeBuilder.EXPR_SGT:
g.writeInstruction('jbe', slbl);
TranslatorTreeBuilder.EXPR_SGE:
g.writeInstruction('jb', slbl);
TranslatorTreeBuilder.EXPR_SLT:
g.writeInstruction('jae', slbl);
TranslatorTreeBuilder.EXPR_SLE:
g.writeInstruction('ja', slbl);
TranslatorTreeBuilder.EXPR_SEQ:
g.writeInstruction('jne', slbl);
TranslatorTreeBuilder.EXPR_SNE:
g.writeInstruction('je', slbl);
end;
g.writeInstruction('jmp',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end;
end else begin
reg1 := stack.allocateGPR16bit(g); { регистр флагов – без изменений }
srb := g.registerToString(AL + (reg1 and $0f));
sr1 := g.registerToString(reg1);
case nodeValue of
TranslatorTreeBuilder.EXPR_SGT:
g.writeInstruction('seta', srb);
TranslatorTreeBuilder.EXPR_SGE:
g.writeInstruction('setae', srb);
TranslatorTreeBuilder.EXPR_SLT:
g.writeInstruction('setb', srb);
TranslatorTreeBuilder.EXPR_SLE:
g.writeInstruction('setbe', srb);
TranslatorTreeBuilder.EXPR_SEQ:
g.writeInstruction('sete', srb);
TranslatorTreeBuilder.EXPR_SNE:
g.writeInstruction('setne', srb);
end;
g.writeInstruction('movzx', sr1, srb);
stack.restoreRegs(g);
end;
end;
end;
end;
TranslatorTreeBuilder.EXPR_SANDB,
TranslatorTreeBuilder.EXPR_SXORB,
TranslatorTreeBuilder.EXPR_SORB: begin
reg2 := stack.getRegAt(1);
reg3 := stack.getRegAt(0);
sr2 := g.registerToString(reg2);
sr3 := g.registerToString(reg3);
stack.popRegs(2);
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
case nodeValue of
TranslatorTreeBuilder.EXPR_SANDB:
g.writeInstruction('test', sr2, sr3);
TranslatorTreeBuilder.EXPR_SXORB:
g.writeInstruction('xor', sr2, sr3);
TranslatorTreeBuilder.EXPR_SORB:
g.writeInstruction('or', sr2, sr3);
end;
stack.restoreRegs(g); { регистр флагов – без изменений }
if goIfTrueTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
end else
if goIfFalseTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jnz',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end else begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
g.writeInstruction('jmp',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end;
end else begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
if reg1 <> reg2 then begin
g.writeInstruction('mov', sr1, sr2);
end;
case nodeValue of
TranslatorTreeBuilder.EXPR_SANDB:
g.writeInstruction('and', sr1, sr3);
TranslatorTreeBuilder.EXPR_SXORB:
g.writeInstruction('xor', sr1, sr3);
TranslatorTreeBuilder.EXPR_SORB:
g.writeInstruction('or', sr1, sr3);
end;
stack.restoreRegs(g);
end;
end;
TranslatorTreeBuilder.EXPR_SZR_TEST: begin
reg2 := stack.getRegAt(1);
reg3 := stack.getRegAt(0);
sr2 := g.registerToString(reg2);
sr3 := g.registerToString(reg3);
stack.popRegs(2);
g.writeInstruction('test', sr2, sr3);
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.restoreRegs(g); { регистр флагов – без изменений }
if goIfTrueTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jnz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
end else
if goIfFalseTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end else begin
g.writeInstruction('jnz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
g.writeInstruction('jmp',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end;
end else begin
reg1 := stack.allocateGPR16bit(g); { регистр флагов – без изменений }
srb := g.registerToString(AL + (reg1 and $0f));
sr1 := g.registerToString(reg1);
g.writeInstruction('setz', srb);
g.writeInstruction('movzx', sr1, srb);
stack.restoreRegs(g);
end;
end;
TranslatorTreeBuilder.EXPR_SNZ_TEST: begin
reg2 := stack.getRegAt(1);
reg3 := stack.getRegAt(0);
sr2 := g.registerToString(reg2);
sr3 := g.registerToString(reg3);
stack.popRegs(2);
g.writeInstruction('test', sr2, sr3);
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.restoreRegs(g); { регистр флагов – без изменений }
if goIfTrueTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
end else
if goIfFalseTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jnz',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end else begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
g.writeInstruction('jmp',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end;
end else begin
reg1 := stack.allocateGPR16bit(g); { регистр флагов – без изменений }
srb := g.registerToString(AL + (reg1 and $0f));
sr1 := g.registerToString(reg1);
g.writeInstruction('setnz', srb);
g.writeInstruction('movzx', sr1, srb);
stack.restoreRegs(g);
end;
end;
TranslatorTreeBuilder.EXPR_SEQ_NULL: begin
reg2 := stack.getRegAt(0);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
g.writeInstruction('test', sr2, sr2);
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.restoreRegs(g); { регистр флагов – без изменений }
if goIfTrueTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jnz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
end else
if goIfFalseTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end else begin
g.writeInstruction('jnz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
g.writeInstruction('jmp',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end;
end else begin
reg1 := stack.allocateGPR16bit(g); { регистр флагов – без изменений }
srb := g.registerToString(AL + (reg1 and $0f));
sr1 := g.registerToString(reg1);
g.writeInstruction('setz', srb);
g.writeInstruction('movzx', sr1, srb);
stack.restoreRegs(g);
end;
end;
TranslatorTreeBuilder.EXPR_SNE_NULL: begin
reg2 := stack.getRegAt(0);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
g.writeInstruction('test', sr2, sr2);
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.restoreRegs(g); { регистр флагов – без изменений }
if goIfTrueTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
end else
if goIfFalseTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jnz',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end else begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
g.writeInstruction('jmp',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end;
end else begin
reg1 := stack.allocateGPR16bit(g); { регистр флагов – без изменений }
srb := g.registerToString(AL + (reg1 and $0f));
sr1 := g.registerToString(reg1);
g.writeInstruction('setnz', srb);
g.writeInstruction('movzx', sr1, srb);
stack.restoreRegs(g);
end;
end;
TranslatorTreeBuilder.ASSIGN: begin
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, true);
smm := mem.memoryToString(MNONE, 0);
smmt := mem.memoryToString(MREAL, 0);
reg2 := mem.getRegisterSource();
srb := g.registerToString(AL + (reg2 and $0f));
sr2 := g.registerToString(reg2);
case child.dataType.kind of
TranslatorType.KIND_BOOLEAN: begin
g.writeInstruction('mov', smm, srb);
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
g.writeInstruction('test', sr2, sr2);
stack.restoreRegs(g); { регистр флагов – без изменений }
if goIfTrueTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
end else
if goIfFalseTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jnz',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end else begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
g.writeInstruction('jmp',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end;
end else begin
if nodeType <> nil then begin
reg1 := stack.allocateGPR16bit(g);
if reg1 <> reg2 then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sr2);
end;
end;
stack.restoreRegs(g);
end;
end;
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
g.writeInstruction('mov', smm, sr2);
if nodeType <> nil then begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> reg2 then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sr2);
end;
end;
stack.restoreRegs(g);
end;
TranslatorType.KIND_BYTE: begin
g.writeInstruction('mov', smm, srb);
if nodeType <> nil then begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> reg2 then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sr2);
end;
end;
stack.restoreRegs(g);
end;
TranslatorType.KIND_FLOAT: begin
g.writeInstruction('movss', smm, sr2);
if nodeType <> nil then begin
stack.pushReg(reg2);
end;
stack.restoreRegs(g);
end;
TranslatorType.KIND_DOUBLE: begin
g.writeInstruction('movsd', smm, sr2);
if nodeType <> nil then begin
stack.pushReg(reg2);
end;
stack.restoreRegs(g);
end;
TranslatorType.KIND_REAL: begin
g.writeInstruction('fstp', smmt);
if nodeType <> nil then begin
stack.pushReg(ST);
g.writeInstruction('fld', smmt);
end;
stack.restoreRegs(g);
end;
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC: begin
g.writeInstruction('mov', smm, sr2);
if nodeType <> nil then begin
if needAllocateForPointer(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForPointer(g);
end else
if needAllocateForArray(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForArray(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> reg2 then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sr2);
end;
end;
stack.restoreRegs(g);
end;
end;
end;
TranslatorTreeBuilder.ASSIGN_SADD,
TranslatorTreeBuilder.ASSIGN_SSUB,
TranslatorTreeBuilder.ASSIGN_SMULL: begin
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, true);
smm := mem.memoryToString(MNONE, 0);
smmb := mem.memoryToString(MBYTE, 0);
smmt := mem.memoryToString(MREAL, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
case child.dataType.kind of
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
g.writeInstruction('mov', sDX, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SADD:
g.writeInstruction('add', sDX, sr2);
TranslatorTreeBuilder.ASSIGN_SSUB:
g.writeInstruction('sub', sDX, sr2);
TranslatorTreeBuilder.ASSIGN_SMULL:
g.writeInstruction('imul', sDX, sr2);
end;
g.writeInstruction('mov', smm, sDX);
if nodeType <> nil then begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sDX);
end;
end;
TranslatorType.KIND_BYTE: begin
g.writeInstruction('movsx', sDX, smmb);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SADD:
g.writeInstruction('add', sDX, sr2);
TranslatorTreeBuilder.ASSIGN_SSUB:
g.writeInstruction('sub', sDX, sr2);
TranslatorTreeBuilder.ASSIGN_SMULL:
g.writeInstruction('imul', sDX, sr2);
end;
g.writeInstruction('mov', smm, sDL);
if nodeType <> nil then begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sDX);
end;
end;
TranslatorType.KIND_FLOAT: begin
g.writeInstruction('movss', sXMM4, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SADD:
g.writeInstruction('addss', sXMM4, sr2);
TranslatorTreeBuilder.ASSIGN_SSUB:
g.writeInstruction('subss', sXMM4, sr2);
TranslatorTreeBuilder.ASSIGN_SMULL:
g.writeInstruction('mulss', sXMM4, sr2);
end;
g.writeInstruction('movss', smm, sXMM4);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movss', sr2, sXMM4);
end;
end;
TranslatorType.KIND_DOUBLE: begin
g.writeInstruction('movsd', sXMM4, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SADD:
g.writeInstruction('addsd', sXMM4, sr2);
TranslatorTreeBuilder.ASSIGN_SSUB:
g.writeInstruction('subsd', sXMM4, sr2);
TranslatorTreeBuilder.ASSIGN_SMULL:
g.writeInstruction('mulsd', sXMM4, sr2);
end;
g.writeInstruction('movsd', smm, sXMM4);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movsd', sr2, sXMM4);
end;
end;
TranslatorType.KIND_REAL: begin
stack.pushReg(ST);
stack.allocateFPU(1, g);
g.writeInstruction('fld', smmt);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SADD:
g.writeInstruction('fadd', sST0, sST1);
TranslatorTreeBuilder.ASSIGN_SSUB:
g.writeInstruction('fsub', sST0, sST1);
TranslatorTreeBuilder.ASSIGN_SMULL:
g.writeInstruction('fmul', sST0, sST1);
end;
g.writeInstruction('fstp', sST1);
g.writeInstruction('fstp', smmt);
if nodeType <> nil then begin
g.writeInstruction('fld', smmt);
stack.popRegs(1);
end else begin
stack.popRegs(2);
end;
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.ASSIGN_SDIVS,
TranslatorTreeBuilder.ASSIGN_SDIVU: begin
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, true);
smm := mem.memoryToString(MNONE, 0);
smmb := mem.memoryToString(MBYTE, 0);
smmt := mem.memoryToString(MREAL, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
case child.dataType.kind of
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
regInUse := stack.isUsedRegister(AX);
if regInUse then begin
g.writeInstruction('mov', sDI, sAX);
end else
if reg2 = AX then begin
g.writeInstruction('mov', sDI, sAX);
reg2 := DI;
sr2 := sDI;
end;
g.writeInstruction('mov', sAX, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SDIVS: begin
g.writeInstruction('cwd');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.ASSIGN_SDIVU: begin
g.writeInstruction('xor', sDX, sDX);
g.writeInstruction('div', sr2);
end;
end;
g.writeInstruction('mov', smm, sAX);
if nodeType <> nil then begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> AX then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sAX);
end;
end;
if regInUse then begin
g.writeInstruction('mov', sAX, sDI);
end;
end;
TranslatorType.KIND_BYTE: begin
regInUse := stack.isUsedRegister(AX);
if regInUse then begin
g.writeInstruction('mov', sDI, sAX);
end else
if reg2 = AX then begin
g.writeInstruction('mov', sDI, sAX);
reg2 := DI;
sr2 := sDI;
end;
g.writeInstruction('movsx', sAX, smmb);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SDIVS: begin
g.writeInstruction('cwd');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.ASSIGN_SDIVU: begin
g.writeInstruction('xor', sDX, sDX);
g.writeInstruction('div', sr2);
end;
end;
g.writeInstruction('mov', smm, sAL);
if nodeType <> nil then begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> AX then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sAX);
end;
end;
if regInUse then begin
g.writeInstruction('mov', sAX, sDI);
end;
end;
TranslatorType.KIND_FLOAT: begin
g.writeInstruction('movss', sXMM4, smm);
g.writeInstruction('divss', sXMM4, sr2);
g.writeInstruction('movss', smm, sXMM4);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movss', sr2, sXMM4);
end;
end;
TranslatorType.KIND_DOUBLE: begin
g.writeInstruction('movsd', sXMM4, smm);
g.writeInstruction('divsd', sXMM4, sr2);
g.writeInstruction('movsd', smm, sXMM4);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movsd', sr2, sXMM4);
end;
end;
TranslatorType.KIND_REAL: begin
stack.pushReg(ST);
stack.allocateFPU(1, g);
g.writeInstruction('fld', smmt);
g.writeInstruction('fdiv', sST0, sST1);
g.writeInstruction('fstp', sST1);
g.writeInstruction('fstp', smmt);
if nodeType <> nil then begin
g.writeInstruction('fld', smmt);
stack.popRegs(1);
end else begin
stack.popRegs(2);
end;
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.ASSIGN_SREMS,
TranslatorTreeBuilder.ASSIGN_SREMU: begin
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, true);
smm := mem.memoryToString(MNONE, 0);
smmb := mem.memoryToString(MBYTE, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
buffer := child.dataType.kind;
case buffer of
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
regInUse := stack.isUsedRegister(AX);
if regInUse then begin
g.writeInstruction('mov', sDI, sAX);
end else
if reg2 = AX then begin
g.writeInstruction('mov', sDI, sAX);
reg2 := DI;
sr2 := sDI;
end;
g.writeInstruction('mov', sAX, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SREMS: begin
g.writeInstruction('cwd');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.ASSIGN_SREMU: begin
g.writeInstruction('xor', sDX, sDX);
g.writeInstruction('div', sr2);
end;
end;
g.writeInstruction('mov', smm, sDX);
if nodeType <> nil then begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> DX then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sDX);
end;
end;
if regInUse then begin
g.writeInstruction('mov', sAX, sDI);
end;
end;
TranslatorType.KIND_BYTE: begin
regInUse := stack.isUsedRegister(AX);
if regInUse then begin
g.writeInstruction('mov', sDI, sAX);
end else
if reg2 = AX then begin
g.writeInstruction('mov', sDI, sAX);
reg2 := DI;
sr2 := sDI;
end;
g.writeInstruction('movsx', sAX, smmb);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SREMS: begin
g.writeInstruction('cwd');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.ASSIGN_SREMU: begin
g.writeInstruction('xor', sDX, sDX);
g.writeInstruction('div', sr2);
end;
end;
g.writeInstruction('mov', smm, sDL);
if nodeType <> nil then begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> DX then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sDX);
end;
end;
if regInUse then begin
g.writeInstruction('mov', sAX, sDI);
end;
end;
TranslatorType.KIND_FLOAT, TranslatorType.KIND_DOUBLE, TranslatorType.KIND_REAL: begin
regInUse := stack.isUsedRegister(AX);
case buffer of
TranslatorType.KIND_FLOAT:
smmt := mem.memoryToString(MFLOAT, 0);
TranslatorType.KIND_DOUBLE:
smmt := mem.memoryToString(MDOUBLE, 0);
TranslatorType.KIND_REAL:
smmt := mem.memoryToString(MREAL, 0);
else
smmt := '';
end;
stack.pushReg(ST);
stack.allocateFPU(1, g);
if regInUse then begin
g.writeInstruction('mov', sDX, sAX);
end;
g.writeInstruction('fld', smmt);
g.writeLabelShort(LABEL_ANONYMOUS);
g.writeInstruction('fprem');
g.writeInstruction('fnstsw', sAX);
g.writeInstruction('test', sAX, g.immediateToStringShort($0400));
g.writeInstruction('jnz', LABEL_PRECEDING);
g.writeInstruction('fstp', sST1);
g.writeInstruction('fstp', smmt);
if nodeType <> nil then begin
g.writeInstruction('fld', smmt);
stack.popRegs(1);
end else begin
stack.popRegs(2);
end;
if regInUse then begin
g.writeInstruction('mov', sAX, sDX);
end;
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.ASSIGN_SSLL,
TranslatorTreeBuilder.ASSIGN_SSRA,
TranslatorTreeBuilder.ASSIGN_SSRL: begin
child := node.getChild(1) as SyntaxNode;
if child.value <> TranslatorTreeBuilder.EXPR_VALUE_INT then begin
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, true);
smm := mem.memoryToString(MNONE, 0);
smmb := mem.memoryToString(MBYTE, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
regInUse := stack.isUsedRegister(CX);
if regInUse then begin
g.writeInstruction('mov', sDI, sCX);
end;
if reg2 <> CX then begin
g.writeInstruction('mov', sCX, sr2);
end;
case child.dataType.kind of
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
g.writeInstruction('mov', sDX, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SSLL:
g.writeInstruction('shl', sDX, sCL);
TranslatorTreeBuilder.ASSIGN_SSRA:
g.writeInstruction('sar', sDX, sCL);
TranslatorTreeBuilder.ASSIGN_SSRL:
g.writeInstruction('shr', sDX, sCL);
end;
g.writeInstruction('mov', smm, sDX);
end;
TranslatorType.KIND_BYTE: begin
g.writeInstruction('movsx', sDX, smmb);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SSLL:
g.writeInstruction('shl', sDX, sCL);
TranslatorTreeBuilder.ASSIGN_SSRA:
g.writeInstruction('sar', sDX, sCL);
TranslatorTreeBuilder.ASSIGN_SSRL:
g.writeInstruction('shr', sDX, sCL);
end;
g.writeInstruction('mov', smm, sDL);
end;
end;
if nodeType <> nil then begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> DX then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sDX);
end;
end;
if regInUse then begin
g.writeInstruction('mov', sCX, sDI);
end;
end else begin
buffer := (child.associate as IntegerAsObject).byteValue();
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, false);
smm := mem.memoryToString(MNONE, 0);
smmb := mem.memoryToString(MBYTE, 0);
simm := g.immediateToStringByte(buffer);
case child.dataType.kind of
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
g.writeInstruction('mov', sDX, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SSLL:
g.writeInstruction('shl', sDX, simm);
TranslatorTreeBuilder.ASSIGN_SSRA:
g.writeInstruction('sar', sDX, simm);
TranslatorTreeBuilder.ASSIGN_SSRL:
g.writeInstruction('shr', sDX, simm);
end;
g.writeInstruction('mov', smm, sDX);
end;
TranslatorType.KIND_BYTE: begin
g.writeInstruction('movsx', sDX, smmb);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SSLL:
g.writeInstruction('shl', sDX, simm);
TranslatorTreeBuilder.ASSIGN_SSRA:
g.writeInstruction('sar', sDX, simm);
TranslatorTreeBuilder.ASSIGN_SSRL:
g.writeInstruction('shr', sDX, simm);
end;
g.writeInstruction('mov', smm, sDL);
end;
end;
if nodeType <> nil then begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
if reg1 <> DX then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sDX);
end;
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.ASSIGN_SANDB,
TranslatorTreeBuilder.ASSIGN_SXORB,
TranslatorTreeBuilder.ASSIGN_SORB: begin
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, true);
smm := mem.memoryToString(MNONE, 0);
smmb := mem.memoryToString(MBYTE, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
case child.dataType.kind of
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
g.writeInstruction('mov', sDX, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SANDB:
g.writeInstruction('and', sDX, sr2);
TranslatorTreeBuilder.ASSIGN_SXORB:
g.writeInstruction('xor', sDX, sr2);
TranslatorTreeBuilder.ASSIGN_SORB:
g.writeInstruction('or', sDX, sr2);
end;
g.writeInstruction('mov', smm, sDX);
end;
TranslatorType.KIND_BYTE: begin
g.writeInstruction('movsx', sDX, smmb);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SANDB:
g.writeInstruction('and', sDX, sr2);
TranslatorTreeBuilder.ASSIGN_SXORB:
g.writeInstruction('xor', sDX, sr2);
TranslatorTreeBuilder.ASSIGN_SORB:
g.writeInstruction('or', sDX, sr2);
end;
g.writeInstruction('mov', smm, sDL);
end;
TranslatorType.KIND_BOOLEAN: begin
g.writeInstruction('movzx', sDX, smmb);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SANDB:
g.writeInstruction('and', sDX, sr2);
TranslatorTreeBuilder.ASSIGN_SXORB:
g.writeInstruction('xor', sDX, sr2);
TranslatorTreeBuilder.ASSIGN_SORB:
g.writeInstruction('or', sDX, sr2);
end;
g.writeInstruction('mov', smm, sDL);
end;
end;
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.restoreRegs(g); { регистр флагов – без изменений }
if goIfTrueTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
end else
if goIfFalseTo.labelNumber = nodeLN + 1 then begin
g.writeInstruction('jnz',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end else begin
g.writeInstruction('jz',
LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
g.writeInstruction('jmp',
LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
end;
end else begin
if nodeType <> nil then begin
if needAllocateForIndex(parentValue, nodeIndex) then begin
reg1 := stack.allocateGPRForIndex(g);
end else begin
reg1 := stack.allocateGPR16bit(g);
end;
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sDX);
end;
stack.restoreRegs(g);
end;
end;
TranslatorTreeBuilder.JUMP: begin
if (node.parent as SyntaxNode).value = TranslatorTreeBuilder.EXPR_QUESTION then begin
stack.deallocateRegWithoutCodeGeneration();
end;
g.writeInstruction('jmp', LABEL_LOCAL + intToString(goAlwaysTo.assignedLabelNumber));
end;
end;
end;
procedure TranslatorBuilderOf16bitCode.translateSwitch(node: SyntaxNode; stack: RegisterStack);
var
i: int;
j: int;
k: int;
reg1: int;
caseC: int;
caseF: int;
caseS: int;
delta: int;
count: int;
default: int;
current: long;
labels: long_Array1d;
child: BuilderNode;
g: TextGenerator;
slabels: String_Array1d;
sdef: String;
sr1: String;
sDI: String;
procedure addLabel(caseValue, nodeLabel: int); inline;
var
newlabels: long_Array1d;
begin
if length(labels) = count then begin
newlabels := long_Array1d_create((count shl 1) + 1);
arraycopyPrimitives(labels, 0, newlabels, 0, count);
labels := newlabels;
end;
labels[count] := longBuild(nodeLabel, caseValue);
inc(count);
end;
procedure sortLabels(); inline;
var
i: int;
j: int;
valueAtI: int;
valueAtJ: int;
labelAtI: long;
labelAtJ: long;
begin
for i := count - 1 downto 1 do begin
labelAtI := labels[i];
valueAtI := int(labelAtI);
j := i - 1;
while j >= 0 do begin
labelAtJ := labels[j];
valueAtJ := int(labelAtJ);
if valueAtJ > valueAtI then begin
labels[i] := labelAtJ;
labels[j] := labelAtI;
labelAtI := labelAtJ;
valueAtI := valueAtJ;
j := i;
end;
dec(j);
end;
end;
end;
procedure setLabelsLength(newLength: int); inline;
var
newlabels: String_Array1d;
begin
if newLength < length(slabels) then begin
newlabels := String_Array1d_create(newLength);
arraycopyStrings(slabels, 0, newlabels, 0, newLength);
slabels := newlabels;
end;
end;
begin
g := self.generator;
count := 0;
default := -1;
labels := nil;
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sDI := g.registerToString(DI);
stack.popRegs(1);
for i := node.getChildrensCount() - 1 downto 0 do begin
child := node.getChild(i) as BuilderNode;
case child.value of
TranslatorTreeBuilder.BLOCK_CASE:
addLabel((child.associate as IntegerAsObject).shortValue(),
(child.goAlwaysToNode as BuilderNode).assignedLabelNumber);
TranslatorTreeBuilder.BLOCK_DEFAULT:
default := (child.goAlwaysToNode as BuilderNode).assignedLabelNumber;
end;
end;
sortLabels();
sdef := LABEL_LOCAL + intToString(default);
if count > 0 then begin
caseS := int(labels[0]);
caseF := int(labels[count - 1]);
end else begin
caseS := 0;
caseF := -1;
end;
caseC := caseF - caseS + 1;
if (caseC > 0) and (caseC < count shl 1) then begin
{ tableswitch }
g.writeInstruction('sub', sr1, g.immediateToStringShort(caseS));
g.writeInstruction('jl', sdef);
g.writeInstruction('cmp', sr1, g.immediateToStringShort(caseF - caseS));
g.writeInstruction('ja', sdef);
g.writeInstruction('mov', sDI, sr1);
g.writeInstruction('shl', sDI, g.immediateToString(1));
g.writeInstruction('jmp', g.memoryToString(MWORD, LABEL_FOLLOWING, DI, 0));
g.writeAlignLocal(2);
g.writeLabelShort(LABEL_ANONYMOUS);
i := 0;
k := 0;
slabels := String_Array1d_create(8);
for j := caseS to caseF do begin
current := labels[i];
if int(current) = j then begin
slabels[k] := LABEL_LOCAL + intToString(current.ints[1]);
inc(i);
end else begin
slabels[k] := sdef;
end;
inc(k);
if k = 8 then begin
g.writeInstruction('dw', slabels);
k := 0;
end;
end;
if k > 0 then begin
setLabelsLength(k);
g.writeInstruction('dw', slabels);
end;
end else begin
{ lookupswitch }
dec(count);
for i := 0 to count do begin
current := labels[i];
delta := int(current);
if i > 0 then begin
dec(delta, int(labels[i - 1]));
end;
g.writeInstruction('sub', sr1, g.immediateToStringShort(delta));
g.writeInstruction('jz', LABEL_LOCAL + intToString(current.ints[1]));
end;
g.writeInstruction('jmp', sdef);
end;
end;
procedure TranslatorBuilderOf16bitCode.writePools();
var
i: int;
j: int;
k: int;
l: int;
len: int;
limit: int;
exponent: int;
significand: long;
floatValue: float;
doubleValue: double;
realValue: real;
poolOfReal: PoolReal;
poolOfString: PoolString;
representer: RealValueRepresenter;
g: TextGenerator;
schars: String_Array1d;
stringValue: UnicodeString;
shex: String;
sdec: String;
begin
g := self.generator;
{%region числа типа float, используемые программой }
poolOfReal := programmeFloats;
limit := poolOfReal.getLength() - 1;
g.writeEmptyLine();
g.writeCommentToLineEnd('pool of float');
g.writeAlignGlobal(4);
g.writeLabelLong(LABEL_POOL_FLOAT_LENGTH);
g.writeInstruction('dw', g.immediateToStringShort(limit + 1), g.immediateToStringShort(0));
g.writeLabelLong(LABEL_POOL_FLOAT_CONTENT);
representer := RealValueRepresenter.create(RealValueRepresenter.FLOAT_SIGNIFICAND_DIGITS,
RealValueRepresenter.FLOAT_ORDER_DIGITS);
try
for i := 0 to limit do begin
floatValue := realToFloat(poolOfReal.getValue(i));
shex := g.immediateToStringInt(floatToIntBits(floatValue));
sdec := representer.toString(floatValue);
g.writeInstruction('dd', shex);
g.writeCommentToLineEnd(sdec);
end;
finally
representer.free();
end;
g.writeEmptyLine();
{%endregion}
{%region числа типа double, используемые программой }
poolOfReal := programmeDoubles;
limit := poolOfReal.getLength() - 1;
g.writeEmptyLine();
g.writeCommentToLineEnd('pool of double');
g.writeLabelLong(LABEL_POOL_DOUBLE_LENGTH);
g.writeInstruction('dw', g.immediateToStringShort(limit + 1), g.immediateToStringShort(0));
g.writeLabelLong(LABEL_POOL_DOUBLE_CONTENT);
representer := RealValueRepresenter.create(RealValueRepresenter.DOUBLE_SIGNIFICAND_DIGITS,
RealValueRepresenter.DOUBLE_ORDER_DIGITS);
try
for i := 0 to limit do begin
doubleValue := realToDouble(poolOfReal.getValue(i));
shex := g.immediateToStringLong(doubleToLongBits(doubleValue));
sdec := representer.toString(doubleValue);
g.writeInstruction('dq', shex);
g.writeCommentToLineEnd(sdec);
end;
finally
representer.free();
end;
g.writeEmptyLine();
{%endregion}
{%region числа типа real, используемые программой }
poolOfReal := programmeReals;
limit := poolOfReal.getLength() - 1;
g.writeEmptyLine();
g.writeCommentToLineEnd('pool of real');
g.writeLabelLong(LABEL_POOL_REAL_LENGTH);
g.writeInstruction('dw', g.immediateToStringShort(limit + 1), g.immediateToStringShort(0));
g.writeLabelLong(LABEL_POOL_REAL_CONTENT);
representer := RealValueRepresenter.create(RealValueRepresenter.REAL_SIGNIFICAND_DIGITS,
RealValueRepresenter.REAL_ORDER_DIGITS);
try
for i := 0 to limit do begin
realValue := poolOfReal.getValue(i);
exponent := realExtractExponent(realValue);
significand := realExtractSignificand(realValue);
sdec := representer.toString(realValue);
g.writeInstruction('dw', String_Array1d_create([
g.immediateToStringShort(significand.shorts[0]),
g.immediateToStringShort(significand.shorts[1]),
g.immediateToStringShort(significand.shorts[2]),
g.immediateToStringShort(significand.shorts[3]),
g.immediateToStringShort(exponent)
]));
g.writeCommentToLineEnd(sdec);
end;
finally
representer.free();
end;
g.writeEmptyLine();
{%endregion}
{%region строки типа char[], используемые программой }
poolOfString := programmeStrings;
limit := poolOfString.getLength() - 1;
g.writeEmptyLine();
g.writeCommentToLineEnd('pool of string');
g.writeLabelLong(LABEL_POOL_STRING_LENGTH);
g.writeInstruction('dw', g.immediateToStringShort(limit + 1));
g.writeLabelLong(LABEL_POOL_STRING_CONTENT);
for i := 0 to limit do begin
g.writeInstruction('dw', g.immediateToStringShort(length(poolOfString.getValue(i))),
g.labelRelativeToString(LABEL_POOL_STRING_ENTRY + intToString(i), -2))
end;
for i := 0 to limit do begin
g.writeLabelLong(LABEL_POOL_STRING_ENTRY + intToString(i));
stringValue := poolOfString.getValue(i);
len := length(stringValue);
j := 0;
while j < len do begin
k := len - j;
if k >= 8 then begin
schars := String_Array1d_create([
g.immediateToStringShort(int(stringValue[j + 1])),
g.immediateToStringShort(int(stringValue[j + 2])),
g.immediateToStringShort(int(stringValue[j + 3])),
g.immediateToStringShort(int(stringValue[j + 4])),
g.immediateToStringShort(int(stringValue[j + 5])),
g.immediateToStringShort(int(stringValue[j + 6])),
g.immediateToStringShort(int(stringValue[j + 7])),
g.immediateToStringShort(int(stringValue[j + 8]))
]);
end else begin
schars := String_Array1d_create(k);
for l := 1 to k do begin
schars[l - 1] := g.immediateToStringShort(int(stringValue[j + l]));
end;
end;
g.writeInstruction('dw', schars);
inc(j, 8);
end;
end;
g.writeEmptyLine();
{%endregion}
end;
function TranslatorBuilderOf16bitCode.insertArguments(args: TypeFunction; offset: int): int;
var
i: int;
delta: int;
g: TextGenerator;
begin
result := 0;
g := self.generator;
for i := args.getArgumentsCount() - 1 downto 0 do with args.getArgument(i) do begin
g.writeLabelRelative('.' + encode(name), BP, offset);
delta := dataType.getAlignedSize(TranslatorType.SIZE_16_BIT);
inc(offset, delta);
inc(result, delta);
end;
end;
function TranslatorBuilderOf16bitCode.insertLocalVars(tree: SyntaxTree; offset: int): int;
var
csize: int;
lsize: int;
locals: Hashtable;
root: SyntaxNode;
node: SyntaxNode;
enum: NodeEnumerator;
vars: Enumeration;
g: TextGenerator;
ltype: TypeDescriptor;
lname: UnicodeString;
begin
result := 0;
if tree = nil then begin
exit;
end;
locals := Hashtable.create();
try
root := tree.root as SyntaxNode;
{ определяем размер каждой локальной переменной }
node := root;
enum := root.enumerateChildrens();
repeat
case node.value of
TranslatorTreeBuilder.OPERATOR_VARIABLE, TranslatorTreeBuilder.BLOCK_WITH: begin
with node.associate as LocalVariable do begin
ltype := dataType;
lname := name;
end;
csize := ltype.getAlignedSize(TranslatorType.SIZE_16_BIT);
if locals.containsKey(lname) then begin
lsize := (locals.get(lname) as IntegerAsObject).intValue();
if csize > lsize then begin
locals.put(lname, csize);
end;
end else begin
locals.put(lname, csize);
end;
end;
end;
node := enum.nextChild() as SyntaxNode;
until node = nil;
{ определяем смещение каждой локальной переменной }
g := self.generator;
vars := locals.keys();
while vars.hasMoreElements() do begin
lname := (vars.nextElement() as UnicodeStringAsObject).unicodeStringValue();
lsize := (locals.get(lname) as IntegerAsObject).intValue();
dec(offset, lsize);
inc(result, lsize);
g.writeLabelRelative('.' + encode(lname), BP, offset);
end;
finally
locals.free();
end;
end;
function TranslatorBuilderOf16bitCode.getMemoryLocation(node: SyntaxNode; stack: RegisterStack;
hasValueForWrite: boolean): MemoryLocation;
var
regPtr: int;
regIdx: int;
regSrc: int;
size: int;
nodeValue: int;
g: TextGenerator;
srIdx: String;
begin
g := self.generator;
nodeValue := node.value;
if hasValueForWrite then begin
case nodeValue of
TranslatorTreeBuilder.EXPR_LOCAL_VARIABLE,
TranslatorTreeBuilder.EXPR_GLOBAL_VARIABLE: begin
regPtr := -1;
regIdx := -1;
regSrc := stack.getRegAt(0);
stack.popRegs(1);
end;
TranslatorTreeBuilder.EXPR_ARRAY: begin
regPtr := stack.getRegAt(2);
regIdx := stack.getRegAt(1);
regSrc := stack.getRegAt(0);
stack.popRegs(3);
end;
TranslatorTreeBuilder.EXPR_FIELD: begin
regPtr := stack.getRegAt(1);
regIdx := -1;
regSrc := stack.getRegAt(0);
stack.popRegs(2);
end;
else
exit;
end;
end else begin
case nodeValue of
TranslatorTreeBuilder.EXPR_LOCAL_VARIABLE,
TranslatorTreeBuilder.EXPR_GLOBAL_VARIABLE: begin
regPtr := -1;
regIdx := -1;
regSrc := -1;
end;
TranslatorTreeBuilder.EXPR_ARRAY: begin
regPtr := stack.getRegAt(1);
regIdx := stack.getRegAt(0);
regSrc := -1;
stack.popRegs(2);
end;
TranslatorTreeBuilder.EXPR_FIELD: begin
regPtr := stack.getRegAt(0);
regIdx := -1;
regSrc := -1;
stack.popRegs(1);
end;
else
exit;
end;
end;
case nodeValue of
TranslatorTreeBuilder.EXPR_LOCAL_VARIABLE: begin
result := MemoryLocationTfasm.create(g, regSrc,
'.' + encode((node.associate as LocalVariable).name));
end;
TranslatorTreeBuilder.EXPR_GLOBAL_VARIABLE: begin
result := MemoryLocationTfasm.create(g, regSrc,
getEntryFullName(node.associate as GlobalVariable));
end;
TranslatorTreeBuilder.EXPR_FIELD: begin
result := MemoryLocationTfasm.create(g, regSrc, regPtr,
getFieldFullName(node.associate as StructureField));
end;
TranslatorTreeBuilder.EXPR_ARRAY: begin
g.writeInstruction('call', FUNCTION_CHECK_ARRAY_INDEX);
srIdx := g.registerToString(regIdx);
size := node.dataType.size;
case size of
1: ;
2: g.writeInstruction('shl', srIdx, g.immediateToStringByte(1));
4: g.writeInstruction('shl', srIdx, g.immediateToStringByte(2));
8: g.writeInstruction('shl', srIdx, g.immediateToStringByte(3));
else
g.writeInstruction('imul', srIdx, srIdx, g.immediateToString(size));
end;
result := MemoryLocationTfasm.create(g, regSrc, regPtr, regIdx, '');
end;
else
result := nil;
end;
end;
function TranslatorBuilderOf16bitCode.getEntryFullName(entry: NamespaceEntry): AnsiString;
var
ownerName: UnicodeString;
entryName: UnicodeString;
begin
ownerName := entry.owner.name;
entryName := entry.name;
if length(ownerName) > 0 then begin
result := encode(ownerName) + '.' + encode(entryName);
exit;
end;
result := encode(entryName);
end;
function TranslatorBuilderOf16bitCode.getFieldFullName(field: StructureField): AnsiString;
var
where: _Interface;
begin
result := '';
where := field.owner;
if where is NamespaceEntry then begin
result := getEntryFullName(where as NamespaceEntry) + '.' + encode(field.name);
end;
end;
end.