{
Этот исходный текст является частью Продвинутого векторного транслятора.
Copyright © 2017 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit Gen64bit;
{$MODE DELPHI,EXTENDEDSYNTAX ON}
interface
uses
Lang, Utils, IOStream, TranIntf, TranType, TranTree, BuildLex, BuildFTr,
GenX86, Gen16bit, Gen32bit;
{$ASMMODE INTEL,CALLING REGISTER,INLINE ON,GOTO ON}
{$H+,I-,J-,M-,Q-,R-,T-}
type
RegisterStack64bit = class;
TranslatorBuilderOf64bitCode = class;
RegisterStack64bit = class(RegisterStack32bit)
public
constructor create(const usingGPRS, usingXMMS: short_Array1d);
procedure storeRegs(count: int; g: TextGenerator); override;
procedure restoreRegs(g: TextGenerator); override;
function getNextUsedGPR(regGPR: int): int; override;
function changeToGPR64bit(index: int): int; override;
function allocateGPR64bit(g: TextGenerator): int; override;
function allocateGPRForArray(g: TextGenerator): int; override;
function allocateGPRForIndex(g: TextGenerator): int; override;
function allocateGPRForPointer(g: TextGenerator): int; override;
protected
procedure checkRegister(reg: int); override;
end;
TranslatorBuilderOf64bitCode = class(TranslatorBuilderOf32bitCode)
public
const LABEL_EXCEPTION_HANDLER = '.L.EH';
const LABEL_POOL_LONG_LENGTH = 'L.P.LONG.LEN';
const LABEL_POOL_LONG_CONTENT = 'L.P.LONG.CON';
const LABEL_POOL_ULTRA_LENGTH = 'L.P.XULTRA.LEN';
const LABEL_POOL_ULTRA_CONTENT = 'L.P.XULTRA.CON';
const LABEL_POOL_XVECTOR_LENGTH = 'L.P.XVECT.LEN';
const LABEL_POOL_XVECTOR_CONTENT = 'L.P.XVECT.CON';
const FUNCTION_EXCEPTION_INHERITED_FROM = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.exceptionInheritedFrom';
const FUNCTION_LONG_QMULHS = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.longQMULHS';
const FUNCTION_ULTRA_EXTRACT = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.ultraExtract';
const FUNCTION_ULTRA_QMULL = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.ultraQMULL';
const FUNCTION_ULTRA_QMULH = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.ultraQMULH';
const FUNCTION_ULTRA_OMULHS = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.ultraOMULHS';
const FUNCTION_FLOAT_TO_LONG = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.floatToLong';
const FUNCTION_DOUBLE_TO_LONG = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.doubleToLong';
const FUNCTION_REAL_TO_LONG = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.realToLong';
const FUNCTION_XVECTOR_EXTRACT = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.xvectorExtract';
const FUNCTION_XVECTOR_TO_ULTRA = TranslatorTreeBuilder.NAMESPACE_SYSTEM +
'.xvectorToUltra';
public
constructor create(extension: int; generator: TextGenerator64; owning: boolean);
procedure buildTargetCode(programme: BuilderOfTrees; stream: Output); override;
strict private
fldExtension: int;
poolOfLong: PoolLong;
poolOfUltra: PoolUltra;
poolOfXVector: PoolXVector;
procedure translateEntryEquality(entry: NamespaceEntry);
procedure translateEntryReadonly(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 translateException(exception: GlobalException);
procedure translateFunction(func: GlobalFunction; programme: BuilderOfTrees);
procedure translateTree(tree: SyntaxTree);
procedure translateNode(node: SyntaxNode; stack: RegisterStack);
procedure translateSwitch(node: SyntaxNode; stack: RegisterStack);
procedure translateExceptionHandler(root: SyntaxNode; argums, locals: int);
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 extension: int read fldExtension;
property programmeLongs: PoolLong read poolOfLong;
property programmeXUltras: PoolUltra read poolOfUltra;
property programmeXVectors: PoolXVector read poolOfXVector;
end;
implementation
{ RegisterStack64bit }
constructor RegisterStack64bit.create(const usingGPRS, usingXMMS: short_Array1d);
begin
inherited create(usingGPRS, usingXMMS, -1, -1);
end;
procedure RegisterStack64bit.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;
sRSP: 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
R0..R15, R0D..R15D: begin
inc(ofs, 8);
end;
(XMM0 + XSLONG)..(XMM15 + XSLONG), (XMM0 + XSDOUBLE)..(XMM15 + XSDOUBLE), MM0..MM7,
(XMM0 + XSINT)..(XMM15 + XSINT), (XMM0 + XSFLOAT)..(XMM15 + XSFLOAT): begin
nonPushable := true;
inc(ofs, 8);
end;
ST0..ST7,
(XMM0 + XPFLOAT)..(XMM15 + XPFLOAT), (XMM0 + XPDOUBLE)..(XMM15 + XPDOUBLE),
(XMM0 + XPINT)..(XMM15 + XPINT), (XMM0 + XPLONG)..(XMM15 + XPLONG): begin
nonPushable := true;
inc(ofs, 16);
end;
end;
inc(i);
inc(j);
end;
sRSP := g.registerToString(RSP);
if nonPushable then begin
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -ofs));
end;
i := sbase;
j := 0;
while (i < ssize) and (j < count) do begin
reg1 := stack[i];
sr1 := g.registerToString(reg1);
case reg1 of
R0..R15, R0D..R15D: begin
if nonPushable then begin
dec(ofs, 8);
g.writeInstruction('mov', g.memoryToString(MNONE, RSP, ofs), sr1);
end else begin
g.writeInstruction('push', g.registerToString(R0 + (reg1 and $0f)));
end;
end;
(XMM0 + XSINT)..(XMM15 + XSINT): begin
dec(ofs, 8);
g.writeInstruction('movd', g.memoryToString(MNONE, RSP, ofs), sr1);
end;
(XMM0 + XSFLOAT)..(XMM15 + XSFLOAT): begin
dec(ofs, 8);
g.writeInstruction('movss', g.memoryToString(MNONE, RSP, ofs), sr1);
end;
(XMM0 + XSLONG)..(XMM15 + XSLONG), MM0..MM7: begin
dec(ofs, 8);
g.writeInstruction('movq', g.memoryToString(MNONE, RSP, ofs), sr1);
end;
(XMM0 + XSDOUBLE)..(XMM15 + XSDOUBLE): begin
dec(ofs, 8);
g.writeInstruction('movsd', g.memoryToString(MNONE, RSP, ofs), sr1);
end;
ST: begin
dec(ofs, 16);
g.writeInstruction('fstp', g.memoryToString(MREAL, RSP, ofs));
{ g.writeInstruction('fdecstp'); }
end;
ST1..ST7: begin
dec(ofs, 16);
g.writeInstruction('fxch', sr1);
g.writeInstruction('fstp', g.memoryToString(MREAL, RSP, ofs));
if reg1 > ST1 then begin
g.writeInstruction('fld', g.registerToString(reg1 - 1));
g.writeInstruction('ffree', sr1);
end;
end;
(XMM0 + XPINT)..(XMM15 + XPINT), (XMM0 + XPLONG)..(XMM15 + XPLONG): begin
dec(ofs, 16);
g.writeInstruction('movdqu', g.memoryToString(MNONE, RSP, ofs), sr1);
end;
(XMM0 + XPFLOAT)..(XMM15 + XPFLOAT): begin
dec(ofs, 16);
g.writeInstruction('movups', g.memoryToString(MNONE, RSP, ofs), sr1);
end;
(XMM0 + XPDOUBLE)..(XMM15 + XPDOUBLE): begin
dec(ofs, 16);
g.writeInstruction('movupd', g.memoryToString(MNONE, RSP, ofs), sr1);
end;
end;
inc(i);
inc(j);
end;
self.sbase := i;
end;
procedure RegisterStack64bit.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;
sRSP: 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)..(XMM15 + XPINT), (XMM0 + XPLONG)..(XMM15 + XPLONG),
(XMM0 + XSINT)..(XMM15 + XSINT), (XMM0 + XSLONG)..(XMM15 + XSLONG),
(XMM0 + XPFLOAT)..(XMM15 + XPFLOAT), (XMM0 + XPDOUBLE)..(XMM15 + XPDOUBLE),
(XMM0 + XSFLOAT)..(XMM15 + XSFLOAT), (XMM0 + XSDOUBLE)..(XMM15 + XSDOUBLE):
nonPopable := true;
R0..R15, R0D..R15D: ;
end;
end;
nbs := i;
ofs := 0;
sRSP := g.registerToString(RSP);
for i := sbase - 1 downto nbs do begin
reg1 := stack[i];
sr1 := g.registerToString(reg1);
case reg1 of
R0..R15, R0D..R15D: begin
if nonPopable then begin
g.writeInstruction('mov', sr1, g.memoryToString(MNONE, RSP, ofs));
inc(ofs, 8);
end else begin
g.writeInstruction('pop', g.registerToString(R0 + (reg1 and $0f)));
end;
end;
(XMM0 + XSINT)..(XMM15 + XSINT): begin
g.writeInstruction('movd', sr1, g.memoryToString(MNONE, RSP, ofs));
inc(ofs, 8);
end;
(XMM0 + XSFLOAT)..(XMM15 + XSFLOAT): begin
g.writeInstruction('movss', sr1, g.memoryToString(MNONE, RSP, ofs));
inc(ofs, 8);
end;
(XMM0 + XSLONG)..(XMM15 + XSLONG), MM0..MM7: begin
g.writeInstruction('movq', sr1, g.memoryToString(MNONE, RSP, ofs));
inc(ofs, 8);
end;
(XMM0 + XSDOUBLE)..(XMM15 + XSDOUBLE): begin
g.writeInstruction('movsd', sr1, g.memoryToString(MNONE, RSP, ofs));
inc(ofs, 8);
end;
ST0..ST6: begin
g.writeInstruction('fld', g.memoryToString(MREAL, RSP, ofs));
if reg1 > ST0 then begin
g.writeInstruction('fstp', g.registerToString(reg1 + 1));
end;
inc(ofs, 16);
end;
ST7: begin
g.writeInstruction('fld', g.memoryToString(MREAL, RSP, ofs));
g.writeInstruction('fincstp');
inc(ofs, 16);
end;
(XMM0 + XPINT)..(XMM15 + XPINT), (XMM0 + XPLONG)..(XMM15 + XPLONG): begin
g.writeInstruction('movdqu', sr1, g.memoryToString(MNONE, RSP, ofs));
inc(ofs, 16);
end;
(XMM0 + XPFLOAT)..(XMM15 + XPFLOAT): begin
g.writeInstruction('movups', sr1, g.memoryToString(MNONE, RSP, ofs));
inc(ofs, 16);
end;
(XMM0 + XPDOUBLE)..(XMM15 + XPDOUBLE): begin
g.writeInstruction('movupd', sr1, g.memoryToString(MNONE, RSP, ofs));
inc(ofs, 16);
end;
end;
end;
if nonPopable then begin
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, ofs));
end;
end;
function RegisterStack64bit.getNextUsedGPR(regGPR: int): int;
var
i: int;
regcm: int;
regus: int;
using: short_Array1d;
begin
using := self.usingGPRs;
regcm := R0 + (regGPR and $0f);
result := R0 + (using[0] and $0f);
for i := length(using) - 1 downto 0 do begin
regus := R0 + (using[i] and $0f);
if regus = regcm then begin
exit;
end;
result := regus;
end;
end;
function RegisterStack64bit.changeToGPR64bit(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 := R0 + (result and $0f);
stack[index] := short(result);
end;
function RegisterStack64bit.allocateGPR64bit(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 := R0 + (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 := R0 + (result and $0f);
pushReg(regst);
result := regst;
exit;
end;
for i := 0 to uslim do begin
regst := R0 + (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 := R0 + (regst and $0f);
storeRegs(i - sbase + 1, g);
pushReg(regst);
result := regst;
exit;
end;
end;
result := -1;
end;
function RegisterStack64bit.allocateGPRForArray(g: TextGenerator): int;
begin
result := allocateGPR64bit(g);
end;
function RegisterStack64bit.allocateGPRForIndex(g: TextGenerator): int;
begin
result := allocateGPR64bit(g);
end;
function RegisterStack64bit.allocateGPRForPointer(g: TextGenerator): int;
begin
result := allocateGPR64bit(g);
end;
procedure RegisterStack64bit.checkRegister(reg: int);
begin
case reg of
R0..R15, R0D..R15D, MM0..MM7, ST0..ST7,
(XMM0 + XPINT)..(XMM15 + XPINT), (XMM0 + XPLONG)..(XMM15 + XPLONG),
(XMM0 + XSINT)..(XMM15 + XSINT), (XMM0 + XSLONG)..(XMM15 + XSLONG),
(XMM0 + XPFLOAT)..(XMM15 + XPFLOAT), (XMM0 + XPDOUBLE)..(XMM15 + XPDOUBLE),
(XMM0 + XSFLOAT)..(XMM15 + XSFLOAT), (XMM0 + XSDOUBLE)..(XMM15 + XSDOUBLE): ;
else
raise IllegalArgumentException.create(msgIllegalRegisters);
end;
end;
{ TranslatorBuilderOf64bitCode }
constructor TranslatorBuilderOf64bitCode.create(extension: int;
generator: TextGenerator64; owning: boolean);
begin
inherited create(generator, owning);
self.fldExtension := extension;
self.poolOfLong := TranslatorPoolLong.create();
self.poolOfUltra := TranslatorPoolUltra.create();
self.poolOfXVector := TranslatorPoolXVector.create();
end;
procedure TranslatorBuilderOf64bitCode.buildTargetCode(programme: BuilderOfTrees; stream: Output);
var
i: int;
j: int;
elimit: int;
mlimit: int;
module: Namespace;
pentry: GlobalFunction;
g: TextGenerator;
begin
g := self.generator;
g.clear();
try
programmeReals.clear();
programmeFloats.clear();
programmeDoubles.clear();
programmeStrings.clear();
programmeFunctions.clear();
programmeLongs.clear();
programmeXUltras.clear();
programmeXVectors.clear();
pentry := programme.entryPoint;
g.writeDirectives(MODE_64_BIT, 0, 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();
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
translateEntryReadonly(module.getEntry(i));
end;
end;
writePools();
g.writeProgrammeTail();
g.writeEmptyLine();
g.writeCommentToLineEnd('programme end');
g.writeAlignGlobal(8);
g.writeLabelLong(LABEL_PROG_END);
g.optimize();
finally
stream.write(stringToByteArray(g.toString()));
end;
end;
procedure TranslatorBuilderOf64bitCode.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 TranslatorBuilderOf64bitCode.translateEntryReadonly(entry: NamespaceEntry);
begin
if entry is GlobalException then begin
translateException(entry as GlobalException);
end;
end;
procedure TranslatorBuilderOf64bitCode.translateEntryVariable(entry: NamespaceEntry);
begin
if not (entry is GlobalConstant) and (entry is GlobalVariable) then begin
translateVariable(entry as GlobalVariable);
end;
end;
procedure TranslatorBuilderOf64bitCode.translateEntryFunction(entry: NamespaceEntry;
programme: BuilderOfTrees);
begin
if entry is GlobalFunction then begin
translateFunction(entry as GlobalFunction, programme);
end;
end;
procedure TranslatorBuilderOf64bitCode.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));
end;
end;
structure := structure.ancestor;
until structure = nil;
g.writeEmptyLine();
end;
procedure TranslatorBuilderOf64bitCode.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_INT:
g.writeEquality(ename, g.immediateToString(constant.intValue));
TranslatorType.KIND_LONG:
g.writeEquality(ename, g.memoryToString(MLONG, LABEL_POOL_LONG_CONTENT,
programmeLongs.indexAcquire(constant.longValue) * 8));
TranslatorType.KIND_ULTRA:
g.writeEquality(ename, g.memoryToString(MNONE, LABEL_POOL_ULTRA_CONTENT,
programmeXUltras.indexAcquire(constant.getUltraValue()) * 16));
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));
TranslatorType.KIND_XVECTOR:
g.writeEquality(ename, g.memoryToString(MNONE, LABEL_POOL_XVECTOR_CONTENT,
programmeXVectors.indexAcquire(constant.getXVectorValue()) * 16));
end;
g.writeEmptyLine();
end;
procedure TranslatorBuilderOf64bitCode.translateVariable(variable: GlobalVariable);
var
vtype: TypeDescriptor;
g: TextGenerator;
ename: String;
szero: String;
begin
g := self.generator;
ename := getEntryFullName(variable);
vtype := variable.dataType;
g.writeAlignGlobal(8);
g.writeLabelGlobal(ename);
g.writeCommentToLineEnd(vtype.toString());
case vtype.kind of
TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
TranslatorType.KIND_SHORT, TranslatorType.KIND_INT, TranslatorType.KIND_FLOAT:
g.writeInstruction('dd', g.immediateToStringInt(0));
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
TranslatorType.KIND_LONG, TranslatorType.KIND_DOUBLE:
g.writeInstruction('dq', g.immediateToStringLong(0));
TranslatorType.KIND_ULTRA, TranslatorType.KIND_XVECTOR: begin
szero := g.immediateToStringLong(0);
g.writeInstruction('dq', szero, szero);
end;
TranslatorType.KIND_REAL: begin
szero := g.immediateToStringShort(0);
g.writeInstruction('dw', String_Array1d_create([
szero, szero, szero, szero, szero
]));
end;
end;
g.writeEmptyLine();
end;
procedure TranslatorBuilderOf64bitCode.translateException(exception: GlobalException);
var
g: TextGenerator;
ename: String;
begin
g := self.generator;
ename := getEntryFullName(exception);
g.writeAlignGlobal(4);
g.writeLabelGlobal(ename);
g.writeCommentToLineEnd('exception');
exception := exception.ancestor;
if exception <> nil then begin
g.writeInstruction('dd', g.labelRelativeToString(getEntryFullName(exception), 0));
end else begin
g.writeInstruction('dd', g.immediateToStringInt(0));
end;
g.writeEmptyLine();
end;
procedure TranslatorBuilderOf64bitCode.translateFunction(func: GlobalFunction;
programme: BuilderOfTrees);
var
interruptWithError: boolean;
functionWithSFrame: boolean;
functionIsEntry: boolean;
funcassembler: boolean;
pureassembler: 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
if func.publicObject then begin
programmeFunctions.addElement(func);
end;
g := self.generator;
ename := getEntryFullName(func);
ftype := func.functionType;
module := func.owner;
funcassembler := func.isAssembler();
pureassembler := func.isPureAssembler();
functionIsEntry := length(module.name) <= 0;
if functionIsEntry = false then begin
g.writeAlignGlobal(4);
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 >= 6) and
stringStartsWith(UnicodeString('error'), ftype.getArgument(5).name);
tree := programme.buildSyntaxTree(func) as SyntaxTree;
if interruptWithError then begin
argumsSize := insertArguments(ftype, (22 - limit) shl 3);
end else begin
argumsSize := insertArguments(ftype, (21 - limit) shl 3);
end;
localsSize := insertLocalVars(tree, 0);
if pureassembler 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('pushq', g.immediateToString(0));
g.writeInstruction('push', g.registerToString(R0));
g.writeInstruction('push', g.registerToString(R1));
g.writeInstruction('push', g.registerToString(R2));
g.writeInstruction('push', g.registerToString(R3));
g.writeInstruction('push', g.registerToString(R6));
g.writeInstruction('push', g.registerToString(R7));
g.writeInstruction('push', g.registerToString(R8));
g.writeInstruction('push', g.registerToString(R9));
g.writeInstruction('push', g.registerToString(R10));
g.writeInstruction('push', g.registerToString(R11));
g.writeInstruction('push', g.registerToString(R12));
g.writeInstruction('push', g.registerToString(R13));
g.writeInstruction('push', g.registerToString(R14));
g.writeInstruction('push', g.registerToString(R15));
if funcassembler = false then begin
g.writeInstruction('lea', g.registerToString(R15),
g.memoryToString(MNONE, LABEL_EXCEPTION_HANDLER, 0));
end;
g.writeInstruction('enter', g.immediateToStringShort(localsSize),
g.immediateToStringByte(0));
g.writeInstruction('mov', g.registerToString(R0), g.registerToString(RBP));
g.writeInstruction('mov', g.memoryToString(MNONE, R0, $78), g.registerToString(RBP));
if funcassembler 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(R15));
g.writeInstruction('pop', g.registerToString(R14));
g.writeInstruction('pop', g.registerToString(R13));
g.writeInstruction('pop', g.registerToString(R12));
g.writeInstruction('pop', g.registerToString(R11));
g.writeInstruction('pop', g.registerToString(R10));
g.writeInstruction('pop', g.registerToString(R9));
g.writeInstruction('pop', g.registerToString(R8));
g.writeInstruction('pop', g.registerToString(R7));
g.writeInstruction('pop', g.registerToString(R6));
g.writeInstruction('pop', g.registerToString(R3));
g.writeInstruction('pop', g.registerToString(R2));
g.writeInstruction('pop', g.registerToString(R1));
g.writeInstruction('pop', g.registerToString(R0));
if interruptWithError then begin
g.writeInstruction('add', g.registerToString(RSP), g.immediateToString($10));
end else begin
g.writeInstruction('add', g.registerToString(RSP), g.immediateToString($08));
end;
g.writeInstruction('iretq');
end;
end else begin
tree := programme.buildSyntaxTree(func) as SyntaxTree;
if funcassembler then begin
argumsSize := insertArguments(ftype, $10);
end else
if functionIsEntry and (g.exitMethod = TextGenerator.EXIT_RETF) then begin
argumsSize := insertArguments(ftype, $20);
end else begin
argumsSize := insertArguments(ftype, $18);
end;
localsSize := insertLocalVars(tree, 0);
if pureassembler 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) or (funcassembler = false);
if funcassembler = false then begin
g.writeInstruction('push', g.registerToString(R15));
g.writeInstruction('lea', g.registerToString(R15),
g.memoryToString(MNONE, LABEL_EXCEPTION_HANDLER, 0));
end;
if functionWithSFrame then begin
g.writeInstruction('enter', g.immediateToStringShort(localsSize),
g.immediateToStringByte(0));
end;
if funcassembler 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(R0),
g.memoryToString(MNONE, getEntryFullName(entry), 0));
end;
end else begin
entry := nil;
end;
if functionWithSFrame then begin
g.writeInstruction('leave');
end;
if funcassembler = false then begin
g.writeInstruction('pop', g.registerToString(R15));
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(R0));
end else begin
g.writeInstruction('pushq', 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;
end else begin
root := nil;
end;
if funcassembler = false then begin
{ вставка обработчика исключений }
translateExceptionHandler(root, argumsSize, localsSize);
end;
if tree <> nil then begin
{ очистка памяти }
tree.deleteChildrens(root);
root.clearData();
end;
g.writeEmptyLine();
end;
procedure TranslatorBuilderOf64bitCode.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 := RegisterStack64bit.create(short_Array1d_create([
R0, R6, R7, R8, R9, R10, R11, R12, R13, R14
]), short_Array1d_create([
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11
]));
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 TranslatorBuilderOf64bitCode.translateNode(node: SyntaxNode; stack: RegisterStack);
var
regInUse: boolean;
reg1: int;
reg2: int;
count: int;
buffer: int;
buffer1: int;
buffer2: int;
buffer3: int;
nodeIndex: int;
nodeValue: int;
nodeLN: int;
parent: SyntaxNode;
nodeAsoc: _Interface;
nodeType: TypeDescriptor;
mem: MemoryLocation;
child: SyntaxNode;
current: SyntaxNode;
funcNode: SyntaxNode;
funcType: TypeFunction;
funcReturn: TypeDescriptor;
gotoNode: BuilderNode;
goAlwaysTo: BuilderNode;
goIfTrueTo: BuilderNode;
goIfFalseTo: BuilderNode;
g: TextGenerator;
slbl: String;
simm: String;
smmb: String;
smmw: String;
smmd: String;
smmq: String;
smmt: String;
smm: String;
srb: String;
srw: String;
srd: String;
srq: String;
sr1: String;
sr2: String;
sR0B: String;
sR1B: String;
sR2B: String;
sR3B: String;
sR0S: String;
sR2S: String;
sR3S: String;
sR0I: String;
sR1I: String;
sR2I: String;
sR3I: String;
sR0L: String;
sR1L: String;
sR2L: String;
sR3L: String;
sRSP: String;
sST0: String;
sST1: String;
sXMM0: String;
sXMM12: String;
sXMM13: String;
begin
g := self.generator;
sR0B := g.registerToString(R0B);
sR1B := g.registerToString(R1B);
sR2B := g.registerToString(R2B);
sR3B := g.registerToString(R3B);
sR0S := g.registerToString(R0W);
sR2S := g.registerToString(R2W);
sR3S := g.registerToString(R3W);
sR0I := g.registerToString(R0D);
sR1I := g.registerToString(R1D);
sR2I := g.registerToString(R2D);
sR3I := g.registerToString(R3D);
sR0L := g.registerToString(R0);
sR1L := g.registerToString(R1);
sR2L := g.registerToString(R2);
sR3L := g.registerToString(R3);
sRSP := g.registerToString(RSP);
sST0 := g.registerToString(ST0);
sST1 := g.registerToString(ST1);
sXMM0 := g.registerToString(XMM0);
sXMM12 := g.registerToString(XMM12);
sXMM13 := g.registerToString(XMM13);
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;
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
sr2 := g.registerToString(R0B + (reg2 and $0f));
g.writeInstruction('mov', smm, sr2);
end;
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
sr2 := g.registerToString(R0W + (reg2 and $0f));
g.writeInstruction('mov', smm, sr2);
end;
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
TranslatorType.KIND_INT, TranslatorType.KIND_LONG:
g.writeInstruction('mov', smm, sr2);
TranslatorType.KIND_ULTRA:
g.writeInstruction('movdqu', 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);
TranslatorType.KIND_XVECTOR:
g.writeInstruction('movups', smm, sr2);
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_THROW: begin
g.writeInstruction('lea', sR2L,
g.memoryToString(MNONE, g.labelCurrentOffsetToString(0), 0));
g.writeInstruction('lea', sR1L,
g.memoryToString(MNONE, getEntryFullName(nodeAsoc as GlobalException), 0));
g.writeInstruction('jmp', LABEL_EXCEPTION_HANDLER);
end;
TranslatorTreeBuilder.OPERATOR_RETURN,
TranslatorTreeBuilder.TF_OPERATOR_RETURN: begin
buffer := stack.size();
if buffer > 0 then begin
reg1 := stack.getRegAt(0);
end else begin
reg1 := -1;
end;
sr1 := g.registerToString(reg1);
stack.popRegs(buffer);
if nodeValue = TranslatorTreeBuilder.TF_OPERATOR_RETURN then begin
case reg1 of
R0..R15, R0D..R15D: begin
g.writeInstruction('push', g.registerToString(R0 + (reg1 and $0f)));
end;
ST: begin
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -$10));
g.writeInstruction('fstp', g.memoryToString(MREAL, RSP, 0));
end;
(XMM0 + XPINT)..(XMM15 + XPINT), (XMM0 + XPLONG)..(XMM15 + XPLONG): begin
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -$10));
g.writeInstruction('movdqu', g.memoryToString(MNONE, RSP, 0), sr1);
end;
(XMM0 + XPFLOAT)..(XMM15 + XPFLOAT): begin
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -$10));
g.writeInstruction('movups', g.memoryToString(MNONE, RSP, 0), sr1);
end;
(XMM0 + XPDOUBLE)..(XMM15 + XPDOUBLE): begin
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -$10));
g.writeInstruction('movupd', g.memoryToString(MNONE, RSP, 0), sr1);
end;
(XMM0 + XSINT)..(XMM15 + XSINT): begin
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -$08));
g.writeInstruction('movd', g.memoryToString(MNONE, RSP, 0), sr1);
end;
(XMM0 + XSLONG)..(XMM15 + XSLONG): begin
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -$08));
g.writeInstruction('movq', g.memoryToString(MNONE, RSP, 0), sr1);
end;
(XMM0 + XSFLOAT)..(XMM15 + XSFLOAT): begin
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -$08));
g.writeInstruction('movss', g.memoryToString(MNONE, RSP, 0), sr1);
end;
(XMM0 + XSDOUBLE)..(XMM15 + XSDOUBLE): begin
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -$08));
g.writeInstruction('movsd', g.memoryToString(MNONE, RSP, 0), sr1);
end;
end;
current := node.parent as SyntaxNode;
repeat
if current.value = TranslatorTreeBuilder.OPERATOR_TRY_FINALLY then begin
gotoNode := (current.getChild(current.getChildrensCount() - 1) as SyntaxNode).
goAlwaysToNode as BuilderNode;
if gotoNode <> nil then begin
g.writeInstruction('call',
LABEL_LOCAL + intToString(gotoNode.assignedLabelNumber));
end;
end;
current := current.parent as SyntaxNode;
until current = nil;
case reg1 of
R0..R15, R0D..R15D: begin
g.writeInstruction('pop', g.registerToString(R0 + (reg1 and $0f)));
end;
ST: begin
g.writeInstruction('fld', g.memoryToString(MREAL, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, $10));
end;
(XMM0 + XPINT)..(XMM15 + XPINT), (XMM0 + XPLONG)..(XMM15 + XPLONG): begin
g.writeInstruction('movdqu', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, $10));
end;
(XMM0 + XPFLOAT)..(XMM15 + XPFLOAT): begin
g.writeInstruction('movups', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, $10));
end;
(XMM0 + XPDOUBLE)..(XMM15 + XPDOUBLE): begin
g.writeInstruction('movupd', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, $10));
end;
(XMM0 + XSINT)..(XMM15 + XSINT): begin
g.writeInstruction('movd', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, $08));
end;
(XMM0 + XSLONG)..(XMM15 + XSLONG): begin
g.writeInstruction('movq', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, $08));
end;
(XMM0 + XSFLOAT)..(XMM15 + XSFLOAT): begin
g.writeInstruction('movss', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, $08));
end;
(XMM0 + XSDOUBLE)..(XMM15 + XSDOUBLE): begin
g.writeInstruction('movsd', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, $08));
end;
end;
end;
if (goAlwaysTo <> nil) and (goAlwaysTo.labelNumber <> nodeLN + 1) then begin
g.writeInstruction('jmp', LABEL_LOCAL + intToString(goAlwaysTo.assignedLabelNumber));
end;
end;
TranslatorTreeBuilder.BLOCK_FINALLY_RETURN: begin
g.writeInstruction('ret');
end;
TranslatorTreeBuilder.EXPR_VALUE_NULL: begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('xor', sr1, sr1);
end;
TranslatorTreeBuilder.EXPR_VALUE_BOOLEAN: begin
if goAlwaysTo = nil then begin
reg1 := stack.allocateGPR32bit(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
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
buffer := (nodeAsoc as IntegerAsObject).intValue();
if buffer = 0 then begin
g.writeInstruction('xor', sr1, sr1);
end else begin
g.writeInstruction('mov', sr1, g.immediateToStringInt(buffer));
end;
end;
TranslatorTreeBuilder.EXPR_VALUE_LONG: begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
with (nodeAsoc as LongAsObject).longValue() do begin
buffer := ints[0];
buffer1 := ints[1];
end;
if (buffer or buffer1) = 0 then begin
g.writeInstruction('xor', sr1, sr1);
end else begin
g.writeInstruction('mov', sr1, g.memoryToString(MNONE, LABEL_POOL_LONG_CONTENT,
programmeLongs.indexAcquire(longBuild(buffer1, buffer)) * 8));
end;
end;
TranslatorTreeBuilder.EXPR_VALUE_ULTRA: begin
reg1 := stack.allocateXMM(XPINT, g);
sr1 := g.registerToString(reg1);
with (nodeAsoc as UltraAsObject).ultraValue() do begin
buffer := ints[0];
buffer1 := ints[1];
buffer2 := ints[2];
buffer3 := ints[3];
end;
if (buffer or buffer1 or buffer2 or buffer3) = 0 then begin
g.writeInstruction('pxor', sr1, sr1);
end else begin
g.writeInstruction('movdqu', sr1, g.memoryToString(MNONE,
LABEL_POOL_ULTRA_CONTENT, programmeXUltras.indexAcquire(
ultraBuild(buffer3, buffer2, buffer1, buffer)) * 16));
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_XVECTOR: begin
reg1 := stack.allocateXMM(XPFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movups', sr1, g.memoryToString(MNONE,
LABEL_POOL_XVECTOR_CONTENT, programmeXVectors.indexAcquire(
(nodeAsoc as XVectorAsObject).xvectorValue()) * 16));
end;
TranslatorTreeBuilder.EXPR_VALUE_STRING: begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('lea', sr1, g.memoryToString(MNONE,
LABEL_POOL_STRING_CONTENT, programmeStrings.indexAcquire(
(nodeAsoc as UnicodeStringAsObject).unicodeStringValue()) * 16));
end;
TranslatorTreeBuilder.EXPR_GLOBAL_FUNCTION: begin
reg1 := stack.allocateGPR64bit(g);
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);
smmw := mem.memoryToString(MWORD, 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', sR1I, smmb);
g.writeInstruction('test', sR1I, sR1I);
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.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movzx', sr1, smmb);
stack.restoreRegs(g);
end;
end;
TranslatorType.KIND_CHAR: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movzx', sr1, smmw);
stack.restoreRegs(g);
end;
TranslatorType.KIND_BYTE: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movsx', sr1, smmb);
stack.restoreRegs(g);
end;
TranslatorType.KIND_SHORT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movsx', sr1, smmw);
stack.restoreRegs(g);
end;
TranslatorType.KIND_INT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, smm);
stack.restoreRegs(g);
end;
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY,
TranslatorType.KIND_FUNC, TranslatorType.KIND_LONG: begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, smm);
stack.restoreRegs(g);
end;
TranslatorType.KIND_ULTRA: begin
reg1 := stack.allocateXMM(XPINT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movdqu', sr1, smm);
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_XVECTOR: begin
reg1 := stack.allocateXMM(XPFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movups', sr1, smm);
stack.restoreRegs(g);
end;
end;
end;
TranslatorTreeBuilder.EXPR_NEW_STRUCT: begin
stack.storeRegs(stack.base(), g);
buffer := (nodeType as TypeStructure).structureSize;
g.writeInstruction('pushq', g.immediateToString(buffer));
g.writeInstruction('call', FUNCTION_NEW_STRUCT);
reg1 := stack.allocateGPR64bit(g);
if reg1 <> R0 then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR0L);
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('pushq', g.immediateToString(count));
g.writeInstruction('pushq', g.immediateToString(buffer));
g.writeInstruction('call', FUNCTION_NEW_ARRAY);
reg1 := stack.allocateGPR64bit(g);
if reg1 <> R0 then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR0L);
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('pushq', g.immediateToString(buffer));
g.writeInstruction('call', FUNCTION_NEW_ARRAY);
reg1 := stack.allocateGPR64bit(g);
if reg1 <> R0 then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR0L);
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_NEW_ULTRA: begin
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -$10));
reg1 := stack.getRegAt(3);
g.writeInstruction('mov', g.memoryToString(MNONE, RSP, $00), g.registerToString(reg1));
reg1 := stack.getRegAt(2);
g.writeInstruction('mov', g.memoryToString(MNONE, RSP, $04), g.registerToString(reg1));
reg1 := stack.getRegAt(1);
g.writeInstruction('mov', g.memoryToString(MNONE, RSP, $08), g.registerToString(reg1));
reg1 := stack.getRegAt(0);
g.writeInstruction('mov', g.memoryToString(MNONE, RSP, $0c), g.registerToString(reg1));
stack.popRegs(4);
reg1 := stack.allocateXMM(XPINT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movdqu', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, $10));
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_NEW_XVECTOR: begin
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -$10));
reg1 := stack.getRegAt(3);
g.writeInstruction('movss', g.memoryToString(MNONE, RSP, $00), g.registerToString(reg1));
reg1 := stack.getRegAt(2);
g.writeInstruction('movss', g.memoryToString(MNONE, RSP, $04), g.registerToString(reg1));
reg1 := stack.getRegAt(1);
g.writeInstruction('movss', g.memoryToString(MNONE, RSP, $08), g.registerToString(reg1));
reg1 := stack.getRegAt(0);
g.writeInstruction('movss', g.memoryToString(MNONE, RSP, $0c), g.registerToString(reg1));
stack.popRegs(4);
reg1 := stack.allocateXMM(XPFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movups', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, $10));
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_FIELD_ASSIGN: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
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
sr2 := g.registerToString(R0B + (reg2 and $0f));
g.writeInstruction('mov', smm, sr2);
end;
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
sr2 := g.registerToString(R0W + (reg2 and $0f));
g.writeInstruction('mov', smm, sr2);
end;
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
TranslatorType.KIND_INT, TranslatorType.KIND_LONG:
g.writeInstruction('mov', smm, sr2);
TranslatorType.KIND_ULTRA:
g.writeInstruction('movdqu', 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);
TranslatorType.KIND_XVECTOR:
g.writeInstruction('movups', smm, sr2);
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_ARRAY_ASSIGN: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
g.writeInstruction('mov', sR1L, sr1);
if nodeIndex = 0 then begin
g.writeInstruction('xor', sR2I, sR2I);
end else begin
g.writeInstruction('mov', sR2I, g.immediateToStringInt(nodeIndex));
end;
g.writeInstruction('call', FUNCTION_CHECK_ARRAY_INDEX);
case nodeType.kind of
TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_BYTE: begin
sr2 := g.registerToString(R0B + (reg2 and $0f));
mem := MemoryLocationTfasm.create(g, reg2, R1, R2, 1, '');
smm := mem.memoryToString(MNONE, 0);
g.writeInstruction('mov', smm, sr2);
end;
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
sr2 := g.registerToString(R0W + (reg2 and $0f));
mem := MemoryLocationTfasm.create(g, reg2, R1, R2, 2, '');
smm := mem.memoryToString(MNONE, 0);
g.writeInstruction('mov', smm, sr2);
end;
TranslatorType.KIND_INT: begin
mem := MemoryLocationTfasm.create(g, reg2, R1, R2, 4, '');
smm := mem.memoryToString(MNONE, 0);
g.writeInstruction('mov', smm, sr2);
end;
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY,
TranslatorType.KIND_FUNC, TranslatorType.KIND_LONG: begin
mem := MemoryLocationTfasm.create(g, reg2, R1, R2, 8, '');
smm := mem.memoryToString(MNONE, 0);
g.writeInstruction('mov', smm, sr2);
end;
TranslatorType.KIND_ULTRA: begin
mem := MemoryLocationTfasm.create(g, reg2, R1, R2, 8, '');
smm := mem.memoryToString(MNONE, 0);
g.writeInstruction('shl', sR2L, g.immediateToString(1));
g.writeInstruction('movdqu', smm, sr2);
end;
TranslatorType.KIND_FLOAT: begin
mem := MemoryLocationTfasm.create(g, reg2, R1, R2, 4, '');
smm := mem.memoryToString(MNONE, 0);
g.writeInstruction('movss', smm, sr2);
end;
TranslatorType.KIND_DOUBLE: begin
mem := MemoryLocationTfasm.create(g, reg2, R1, R2, 8, '');
smm := mem.memoryToString(MNONE, 0);
g.writeInstruction('movsd', smm, sr2);
end;
TranslatorType.KIND_REAL: begin
mem := MemoryLocationTfasm.create(g, reg2, R1, R2, '');
smmt := mem.memoryToString(MREAL, 0);
g.writeInstruction('imul', sR2L, sR2L, g.immediateToString(10));
g.writeInstruction('fstp', smmt);
end;
TranslatorType.KIND_XVECTOR: begin
mem := MemoryLocationTfasm.create(g, reg2, R1, R2, 8, '');
smm := mem.memoryToString(MNONE, 0);
g.writeInstruction('shl', sR2L, g.immediateToString(1));
g.writeInstruction('movups', smm, 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', sR0I, sR0I);
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.allocateGPR32bit(g);
if reg1 <> R0D then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR0I);
end;
stack.restoreRegs(g);
end;
end;
TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
TranslatorType.KIND_SHORT, TranslatorType.KIND_INT: begin
reg1 := stack.allocateGPR32bit(g);
if reg1 <> R0D then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR0I);
end;
stack.restoreRegs(g);
end;
TranslatorType.KIND_LONG, TranslatorType.KIND_STRUCT,
TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC: begin
reg1 := stack.allocateGPR64bit(g);
if reg1 <> R0 then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR0L);
end;
stack.restoreRegs(g);
end;
TranslatorType.KIND_ULTRA: begin
reg1 := stack.allocateXMM(XPINT, g);
if reg1 <> XMM0 + XPINT then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('movdqu', sr1, sXMM0);
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_XVECTOR: begin
reg1 := stack.allocateXMM(XPFLOAT, g);
if reg1 <> XMM0 + XPFLOAT then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('movups', sr1, sXMM0);
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_COMPOUND: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(2);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_ULTRA: begin
g.writeInstruction('movdqu', sXMM12, sr1);
g.writeInstruction('mov', sR1I, sr2);
g.writeInstruction('call', FUNCTION_ULTRA_EXTRACT);
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR1I);
end;
TranslatorType.KIND_XVECTOR: begin
g.writeInstruction('movups', sXMM12, sr1);
g.writeInstruction('mov', sR1I, sr2);
g.writeInstruction('call', FUNCTION_XVECTOR_EXTRACT);
reg1 := stack.allocateXMM(XSFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sr1, sXMM12);
end;
end;
stack.restoreRegs(g);
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);
smmd := mem.memoryToString(MDWORD, 0);
smmq := mem.memoryToString(MQWORD, 0);
smmt := mem.memoryToString(MREAL, 0);
case child.dataType.kind of
TranslatorType.KIND_CHAR: begin
if nodeType <> nil then begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
if regInUse then begin
g.writeInstruction('movzx', sR3I, smmw);
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST:
g.writeInstruction('inc', smmw);
TranslatorTreeBuilder.EXPR_DECR_POST:
g.writeInstruction('dec', smmw);
end;
g.writeInstruction('mov', sr1, sR3I);
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('movzx', sr1, smmw);
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
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
if regInUse then begin
g.writeInstruction('movsx', sR3I, 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, sR3I);
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_SHORT: begin
if nodeType <> nil then begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
if regInUse then begin
g.writeInstruction('movsx', sR3I, smmw);
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST:
g.writeInstruction('inc', smmw);
TranslatorTreeBuilder.EXPR_DECR_POST:
g.writeInstruction('dec', smmw);
end;
g.writeInstruction('mov', sr1, sR3I);
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('movsx', sr1, smmw);
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_INT: begin
if nodeType <> nil then begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
if regInUse then begin
g.writeInstruction('mov', sR3I, smm);
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST:
g.writeInstruction('inc', smmd);
TranslatorTreeBuilder.EXPR_DECR_POST:
g.writeInstruction('dec', smmd);
end;
g.writeInstruction('mov', sr1, sR3I);
end else begin
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('inc', smmd);
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('dec', smmd);
end;
g.writeInstruction('mov', sr1, smm);
end;
end else begin
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST,
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('inc', smmd);
TranslatorTreeBuilder.EXPR_DECR_POST,
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('dec', smmd);
end;
end;
end;
TranslatorType.KIND_LONG: begin
if nodeType <> nil then begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
if regInUse then begin
g.writeInstruction('mov', sR3L, smm);
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST:
g.writeInstruction('inc', smmq);
TranslatorTreeBuilder.EXPR_DECR_POST:
g.writeInstruction('dec', smmq);
end;
g.writeInstruction('mov', sr1, sR3L);
end else begin
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('inc', smmq);
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('dec', smmq);
end;
g.writeInstruction('mov', sr1, smm);
end;
end else begin
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST,
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('inc', smmq);
TranslatorTreeBuilder.EXPR_DECR_POST,
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('dec', smmq);
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', sXMM12, sr1);
g.writeInstruction('movss', sXMM13, g.memoryToString(MNONE,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST:
g.writeInstruction('addss', sXMM12, sXMM13);
TranslatorTreeBuilder.EXPR_DECR_POST:
g.writeInstruction('subss', sXMM12, sXMM13);
end;
g.writeInstruction('movss', smm, sXMM12);
end else begin
g.writeInstruction('movss', sXMM12, g.memoryToString(MNONE,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('addss', sr1, sXMM12);
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('subss', sr1, sXMM12);
end;
g.writeInstruction('movss', smm, sr1);
end;
end else begin
g.writeInstruction('movss', sXMM12, smm);
g.writeInstruction('movss', sXMM13, 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', sXMM12, sXMM13);
TranslatorTreeBuilder.EXPR_DECR_POST,
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('subss', sXMM12, sXMM13);
end;
g.writeInstruction('movss', smm, sXMM12);
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', sXMM12, sr1);
g.writeInstruction('movsd', sXMM13, g.memoryToString(MNONE,
LABEL_POOL_DOUBLE_CONTENT, programmeDoubles.indexAcquire(1) * 8));
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_POST:
g.writeInstruction('addsd', sXMM12, sXMM13);
TranslatorTreeBuilder.EXPR_DECR_POST:
g.writeInstruction('subsd', sXMM12, sXMM13);
end;
g.writeInstruction('movsd', smm, sXMM12);
end else begin
g.writeInstruction('movsd', sXMM12, g.memoryToString(MNONE,
LABEL_POOL_DOUBLE_CONTENT, programmeDoubles.indexAcquire(1) * 8));
case nodeValue of
TranslatorTreeBuilder.EXPR_INCR_PRED:
g.writeInstruction('addsd', sr1, sXMM12);
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('subsd', sr1, sXMM12);
end;
g.writeInstruction('movsd', smm, sr1);
end;
end else begin
g.writeInstruction('movsd', sXMM12, smm);
g.writeInstruction('movsd', sXMM13, 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', sXMM12, sXMM13);
TranslatorTreeBuilder.EXPR_DECR_POST,
TranslatorTreeBuilder.EXPR_DECR_PRED:
g.writeInstruction('subsd', sXMM12, sXMM13);
end;
g.writeInstruction('movsd', smm, sXMM12);
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_CHAR, TranslatorType.KIND_BYTE, TranslatorType.KIND_SHORT,
TranslatorType.KIND_INT: {%region исходный тип данных – int}
case nodeType.kind of
TranslatorType.KIND_CHAR: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
srw := g.registerToString(R0W + (reg2 and $0f));
g.writeInstruction('movzx', sr1, srw);
end;
TranslatorType.KIND_BYTE: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
srb := g.registerToString(R0B + (reg2 and $0f));
g.writeInstruction('movsx', sr1, srb);
end;
TranslatorType.KIND_SHORT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
srw := g.registerToString(R0W + (reg2 and $0f));
g.writeInstruction('movsx', sr1, srw);
end;
TranslatorType.KIND_LONG: begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movsxd', sr1, sr2);
end;
TranslatorType.KIND_ULTRA: begin
reg1 := stack.allocateXMM(XPINT, g);
sr1 := g.registerToString(reg1);
srq := g.registerToString(R0 + (reg2 and $0f));
g.writeInstruction('movsxd', srq, sr2);
g.writeInstruction('movq', sr1, srq);
end;
TranslatorType.KIND_FLOAT: begin
reg1 := stack.allocateXMM(XSFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('cvtsi2ss', sr1, sr2);
end;
TranslatorType.KIND_DOUBLE: begin
reg1 := stack.allocateXMM(XSDOUBLE, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('cvtsi2sd', sr1, sr2);
end;
TranslatorType.KIND_REAL: begin
stack.allocateFPU(1, g);
srq := g.registerToString(R0 + (reg2 and $0f));
g.writeInstruction('push', srq);
g.writeInstruction('fild', g.memoryToString(MINT, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, 8));
end;
TranslatorType.KIND_XVECTOR: begin
reg1 := stack.allocateXMM(XPFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('pxor', sr1, sr1);
g.writeInstruction('cvtsi2ss', sr1, sr2);
end;
end;
{%endregion}
TranslatorType.KIND_LONG: {%region исходный тип данных – long}
case nodeType.kind of
TranslatorType.KIND_CHAR: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
srw := g.registerToString(R0W + (reg2 and $0f));
g.writeInstruction('movzx', sr1, srw);
end;
TranslatorType.KIND_BYTE: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
srb := g.registerToString(R0B + (reg2 and $0f));
g.writeInstruction('movsx', sr1, srb);
end;
TranslatorType.KIND_SHORT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
srw := g.registerToString(R0W + (reg2 and $0f));
g.writeInstruction('movsx', sr1, srw);
end;
TranslatorType.KIND_INT: begin
reg1 := stack.allocateGPR32bit(g);
if (reg1 and $0f) <> (reg2 and $0f) then begin
sr1 := g.registerToString(reg1);
srd := g.registerToString(R0D + (reg2 and $0f));
g.writeInstruction('mov', sr1, srd);
end;
end;
TranslatorType.KIND_ULTRA: begin
reg1 := stack.allocateXMM(XPINT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movq', sr1, sr2);
end;
TranslatorType.KIND_FLOAT: begin
reg1 := stack.allocateXMM(XSFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('cvtsi2ss', sr1, sr2);
end;
TranslatorType.KIND_DOUBLE: begin
reg1 := stack.allocateXMM(XSDOUBLE, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('cvtsi2sd', sr1, sr2);
end;
TranslatorType.KIND_REAL: begin
stack.allocateFPU(1, g);
g.writeInstruction('push', sr2);
g.writeInstruction('fild', g.memoryToString(MLONG, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, 8));
end;
TranslatorType.KIND_XVECTOR: begin
reg1 := stack.allocateXMM(XPFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('pxor', sr1, sr1);
g.writeInstruction('cvtsi2ss', sr1, sr2);
end;
end;
{%endregion}
TranslatorType.KIND_ULTRA: {%region исходный тип данных – ultra}
case nodeType.kind of
TranslatorType.KIND_CHAR: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
srw := g.registerToString(R0W + (reg1 and $0f));
g.writeInstruction('movd', sr1, sr2);
g.writeInstruction('movzx', sr1, srw);
end;
TranslatorType.KIND_BYTE: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
srb := g.registerToString(R0B + (reg1 and $0f));
g.writeInstruction('movd', sr1, sr2);
g.writeInstruction('movsx', sr1, srb);
end;
TranslatorType.KIND_SHORT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
srw := g.registerToString(R0W + (reg1 and $0f));
g.writeInstruction('movd', sr1, sr2);
g.writeInstruction('movsx', sr1, srw);
end;
TranslatorType.KIND_INT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movd', sr1, sr2);
end;
TranslatorType.KIND_LONG: begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movq', sr1, sr2);
end;
TranslatorType.KIND_FLOAT: begin
reg1 := stack.allocateXMM(XSFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movq', sR1L, sr2);
g.writeInstruction('cvtsi2ss', sr1, sR1L);
end;
TranslatorType.KIND_DOUBLE: begin
reg1 := stack.allocateXMM(XSDOUBLE, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movq', sR1L, sr2);
g.writeInstruction('cvtsi2sd', sr1, sR1L);
end;
TranslatorType.KIND_REAL: begin
stack.allocateFPU(1, g);
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -8));
g.writeInstruction('movq', g.memoryToString(MNONE, RSP, 0), sr2);
g.writeInstruction('fild', g.memoryToString(MLONG, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, 8));
end;
TranslatorType.KIND_XVECTOR: begin
reg1 := stack.allocateXMM(XPFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('cvtdq2ps', sr1, sr2);
end;
end;
{%endregion}
TranslatorType.KIND_FLOAT: {%region исходный тип данных – float}
case nodeType.kind of
TranslatorType.KIND_CHAR: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_FLOAT_TO_INT);
g.writeInstruction('movzx', sr1, sR2S);
end;
TranslatorType.KIND_BYTE: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_FLOAT_TO_INT);
g.writeInstruction('movsx', sr1, sR2B);
end;
TranslatorType.KIND_SHORT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_FLOAT_TO_INT);
g.writeInstruction('movsx', sr1, sR2S);
end;
TranslatorType.KIND_INT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_FLOAT_TO_INT);
g.writeInstruction('mov', sr1, sR2I);
end;
TranslatorType.KIND_LONG: begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_FLOAT_TO_LONG);
g.writeInstruction('mov', sr1, sR2L);
end;
TranslatorType.KIND_ULTRA: begin
reg1 := stack.allocateXMM(XPINT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_FLOAT_TO_LONG);
g.writeInstruction('movq', sr1, sR2L);
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);
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -8));
g.writeInstruction('movss', g.memoryToString(MNONE, RSP, 0), sr2);
g.writeInstruction('fld', g.memoryToString(MFLOAT, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, 8));
end;
TranslatorType.KIND_XVECTOR: begin
reg1 := stack.allocateXMM(XPFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -8));
g.writeInstruction('movss', g.memoryToString(MNONE, RSP, 0), sr2);
g.writeInstruction('movss', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, 8));
end;
end;
{%endregion}
TranslatorType.KIND_DOUBLE: {%region исходный тип данных – double}
case nodeType.kind of
TranslatorType.KIND_CHAR: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movsd', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_DOUBLE_TO_INT);
g.writeInstruction('movzx', sr1, sR2S);
end;
TranslatorType.KIND_BYTE: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movsd', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_DOUBLE_TO_INT);
g.writeInstruction('movsx', sr1, sR2B);
end;
TranslatorType.KIND_SHORT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movsd', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_DOUBLE_TO_INT);
g.writeInstruction('movsx', sr1, sR2S);
end;
TranslatorType.KIND_INT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movsd', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_DOUBLE_TO_INT);
g.writeInstruction('mov', sr1, sR2I);
end;
TranslatorType.KIND_LONG: begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movsd', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_DOUBLE_TO_LONG);
g.writeInstruction('mov', sr1, sR2L);
end;
TranslatorType.KIND_ULTRA: begin
reg1 := stack.allocateXMM(XPINT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movsd', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_DOUBLE_TO_LONG);
g.writeInstruction('movq', sr1, sR2L);
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);
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -8));
g.writeInstruction('movsd', g.memoryToString(MNONE, RSP, 0), sr2);
g.writeInstruction('fld', g.memoryToString(MDOUBLE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, 8));
end;
TranslatorType.KIND_XVECTOR: begin
reg1 := stack.allocateXMM(XPFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('cvtsd2ss', sr2, sr2);
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -8));
g.writeInstruction('movss', g.memoryToString(MNONE, RSP, 0), sr2);
g.writeInstruction('movss', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, 8));
end;
end;
{%endregion}
TranslatorType.KIND_REAL: {%region исходный тип данных – real}
case nodeType.kind of
TranslatorType.KIND_CHAR: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('call', FUNCTION_REAL_TO_INT);
g.writeInstruction('movzx', sr1, sR2S);
end;
TranslatorType.KIND_BYTE: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('call', FUNCTION_REAL_TO_INT);
g.writeInstruction('movsx', sr1, sR2B);
end;
TranslatorType.KIND_SHORT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('call', FUNCTION_REAL_TO_INT);
g.writeInstruction('movsx', sr1, sR2S);
end;
TranslatorType.KIND_INT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('call', FUNCTION_REAL_TO_INT);
g.writeInstruction('mov', sr1, sR2I);
end;
TranslatorType.KIND_LONG: begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('call', FUNCTION_REAL_TO_LONG);
g.writeInstruction('mov', sr1, sR2L);
end;
TranslatorType.KIND_ULTRA: begin
reg1 := stack.allocateXMM(XPINT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('call', FUNCTION_REAL_TO_LONG);
g.writeInstruction('movq', sr1, sR2L);
end;
TranslatorType.KIND_FLOAT: begin
reg1 := stack.allocateXMM(XSFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -8));
g.writeInstruction('fstp', g.memoryToString(MFLOAT, RSP, 0));
g.writeInstruction('movss', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, 8));
end;
TranslatorType.KIND_DOUBLE: begin
reg1 := stack.allocateXMM(XSDOUBLE, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -8));
g.writeInstruction('fstp', g.memoryToString(MDOUBLE, RSP, 0));
g.writeInstruction('movsd', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, 8));
end;
TranslatorType.KIND_XVECTOR: begin
reg1 := stack.allocateXMM(XPFLOAT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -8));
g.writeInstruction('fstp', g.memoryToString(MFLOAT, RSP, 0));
g.writeInstruction('movss', sr1, g.memoryToString(MNONE, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, 8));
end;
end;
{%endregion}
TranslatorType.KIND_XVECTOR: {%region исходный тип данных – xvector}
case nodeType.kind of
TranslatorType.KIND_CHAR: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_FLOAT_TO_INT);
g.writeInstruction('movzx', sr1, sR2S);
end;
TranslatorType.KIND_BYTE: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_FLOAT_TO_INT);
g.writeInstruction('movsx', sr1, sR2B);
end;
TranslatorType.KIND_SHORT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_FLOAT_TO_INT);
g.writeInstruction('movsx', sr1, sR2S);
end;
TranslatorType.KIND_INT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_FLOAT_TO_INT);
g.writeInstruction('mov', sr1, sR2I);
end;
TranslatorType.KIND_LONG: begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_FLOAT_TO_LONG);
g.writeInstruction('mov', sr1, sR2L);
end;
TranslatorType.KIND_ULTRA: begin
reg1 := stack.allocateXMM(XPINT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movups', sXMM12, sr2);
g.writeInstruction('call', FUNCTION_XVECTOR_TO_ULTRA);
g.writeInstruction('movdqu', sr1, sXMM12);
end;
TranslatorType.KIND_FLOAT: begin
reg1 := stack.allocateXMM(XSFLOAT, g);
if (reg1 and $1f) <> (reg2 and $1f) then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('movss', sr1, sr2);
end;
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);
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, -8));
g.writeInstruction('movss', g.memoryToString(MNONE, RSP, 0), sr2);
g.writeInstruction('fld', g.memoryToString(MFLOAT, RSP, 0));
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RSP, 8));
end;
end;
{%endregion}
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_SNOTB: begin
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
g.writeInstruction('not', sr1);
end;
TranslatorTreeBuilder.EXPR_SNEG: begin
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_INT, TranslatorType.KIND_LONG: begin
g.writeInstruction('neg', sr1);
end;
TranslatorType.KIND_FLOAT: begin
g.writeInstruction('movss', sXMM12, sr1);
g.writeInstruction('movss', sr1, g.memoryToString(MNONE,
LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(0) * 4));
g.writeInstruction('subss', sr1, sXMM12);
end;
TranslatorType.KIND_DOUBLE: begin
g.writeInstruction('movsd', sXMM12, sr1);
g.writeInstruction('movsd', sr1, g.memoryToString(MNONE,
LABEL_POOL_DOUBLE_CONTENT, programmeDoubles.indexAcquire(0) * 8));
g.writeInstruction('subsd', sr1, sXMM12);
end;
TranslatorType.KIND_REAL: begin
g.writeInstruction('fchs');
end;
end;
end;
TranslatorTreeBuilder.EXPR_QPACKUS: begin
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_LONG: begin
reg1 := stack.changeToGPR32bit(0);
srd := g.registerToString(reg1);
g.writeInstruction('movq', sXMM12, sr1);
g.writeInstruction('packuswb', sXMM12, sXMM12);
g.writeInstruction('movd', srd, sXMM12);
end;
TranslatorType.KIND_ULTRA: begin
{ SSE4.1-инструкция }
stack.popRegs(1);
reg2 := stack.allocateGPR64bit(g);
sr2 := g.registerToString(reg2);
g.writeInstruction('packusdw', sr1, sr1);
g.writeInstruction('movq', sr2, sr1);
stack.restoreRegs(g);
end;
end;
end;
TranslatorTreeBuilder.EXPR_QUNPCKL: begin
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_INT: begin
reg1 := stack.changeToGPR64bit(0);
srq := g.registerToString(reg1);
g.writeInstruction('movd', sXMM12, sr1);
g.writeInstruction('pxor', sXMM13, sXMM13);
g.writeInstruction('punpcklbw', sXMM12, sXMM13);
g.writeInstruction('movq', srq, sXMM12);
end;
TranslatorType.KIND_LONG: begin
stack.popRegs(1);
reg2 := stack.allocateXMM(XPINT, g);
sr2 := g.registerToString(reg2);
g.writeInstruction('movq', sr2, sr1);
g.writeInstruction('pxor', sXMM12, sXMM12);
g.writeInstruction('punpcklwd', sr2, sXMM12);
stack.restoreRegs(g);
end;
end;
end;
TranslatorTreeBuilder.EXPR_QUNPCKH: begin
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_INT: begin
reg1 := stack.changeToGPR64bit(0);
srq := g.registerToString(reg1);
g.writeInstruction('pxor', sXMM12, sXMM12);
g.writeInstruction('movd', sXMM13, sr1);
g.writeInstruction('punpcklbw', sXMM12, sXMM13);
g.writeInstruction('movq', srq, sXMM12);
end;
TranslatorType.KIND_LONG: begin
stack.popRegs(1);
reg2 := stack.allocateXMM(XPINT, g);
sr2 := g.registerToString(reg2);
g.writeInstruction('pxor', sr2, sr2);
g.writeInstruction('movq', sXMM12, sr1);
g.writeInstruction('punpcklwd', sr2, sXMM12);
stack.restoreRegs(g);
end;
end;
end;
TranslatorTreeBuilder.EXPR_QNEG: begin
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_LONG: begin
g.writeInstruction('pxor', sXMM12, sXMM12);
g.writeInstruction('movq', sXMM13, sr1);
g.writeInstruction('psubw', sXMM12, sXMM13);
g.writeInstruction('movq', sr1, sXMM12);
end;
TranslatorType.KIND_ULTRA: begin
g.writeInstruction('movdqu', sXMM12, sr1);
g.writeInstruction('pxor', sr1, sr1);
g.writeInstruction('psubd', sr1, sXMM12);
end;
TranslatorType.KIND_XVECTOR: begin
g.writeInstruction('movups', sXMM12, sr1);
g.writeInstruction('movups', sr1, g.memoryToString(MNONE,
LABEL_POOL_XVECTOR_CONTENT, programmeXVectors.indexAcquire(
xvectorBuild(0, 0, 0, 0)) * 16));
g.writeInstruction('subps', sr1, sXMM12);
end;
end;
end;
TranslatorTreeBuilder.EXPR_OPACKUS: begin
reg1 := stack.getRegAt(0);
stack.popRegs(1);
reg2 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
g.writeInstruction('packuswb', sr1, sr1);
g.writeInstruction('movq', sr2, sr1);
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_OUNPCKL: begin
reg1 := stack.getRegAt(0);
stack.popRegs(1);
reg2 := stack.allocateXMM(XPINT, g);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
g.writeInstruction('movq', sr2, sr1);
g.writeInstruction('pxor', sXMM12, sXMM12);
g.writeInstruction('punpcklbw', sr2, sXMM12);
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_OUNPCKH: begin
reg1 := stack.getRegAt(0);
stack.popRegs(1);
reg2 := stack.allocateXMM(XPINT, g);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
g.writeInstruction('pxor', sr2, sr2);
g.writeInstruction('movq', sXMM12, sr1);
g.writeInstruction('punpcklbw', sr2, sXMM12);
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_ONEG: begin
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
g.writeInstruction('movdqu', sXMM12, sr1);
g.writeInstruction('pxor', sr1, sr1);
g.writeInstruction('psubw', sr1, sXMM12);
end;
TranslatorTreeBuilder.EXPR_SADD,
TranslatorTreeBuilder.EXPR_SSUB,
TranslatorTreeBuilder.EXPR_SMULL: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_INT, TranslatorType.KIND_LONG:
case nodeValue of
TranslatorTreeBuilder.EXPR_SADD:
g.writeInstruction('add', sr1, sr2);
TranslatorTreeBuilder.EXPR_SSUB:
g.writeInstruction('sub', sr1, sr2);
TranslatorTreeBuilder.EXPR_SMULL:
g.writeInstruction('imul', sr1, sr2);
end;
TranslatorType.KIND_FLOAT:
case nodeValue of
TranslatorTreeBuilder.EXPR_SADD:
g.writeInstruction('addss', sr1, sr2);
TranslatorTreeBuilder.EXPR_SSUB:
g.writeInstruction('subss', sr1, sr2);
TranslatorTreeBuilder.EXPR_SMULL:
g.writeInstruction('mulss', sr1, sr2);
end;
TranslatorType.KIND_DOUBLE:
case nodeValue of
TranslatorTreeBuilder.EXPR_SADD:
g.writeInstruction('addsd', sr1, sr2);
TranslatorTreeBuilder.EXPR_SSUB:
g.writeInstruction('subsd', sr1, sr2);
TranslatorTreeBuilder.EXPR_SMULL:
g.writeInstruction('mulsd', sr1, sr2);
end;
TranslatorType.KIND_REAL:
case nodeValue of
TranslatorTreeBuilder.EXPR_SADD:
g.writeInstruction('faddp');
TranslatorTreeBuilder.EXPR_SSUB:
g.writeInstruction('fsubp');
TranslatorTreeBuilder.EXPR_SMULL:
g.writeInstruction('fmulp');
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_SDIVS,
TranslatorTreeBuilder.EXPR_SDIVU: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_INT: begin
stack.popRegs(1);
regInUse := stack.isUsedRegister(R0D);
stack.pushReg(reg1);
if reg2 = R0D then begin
g.writeInstruction('xchg', sr1, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_SDIVS: begin
g.writeInstruction('cdq');
g.writeInstruction('idiv', sr1);
end;
TranslatorTreeBuilder.EXPR_SDIVU: begin
g.writeInstruction('xor', sR2I, sR2I);
g.writeInstruction('div', sr1);
end;
end;
g.writeInstruction('mov', sr1, sr2);
end else begin
if regInUse then begin
g.writeInstruction('mov', sR3L, sR0L);
end;
if reg1 <> R0D then begin
g.writeInstruction('mov', sR0I, sr1);
end;
case nodeValue of
TranslatorTreeBuilder.EXPR_SDIVS: begin
g.writeInstruction('cdq');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.EXPR_SDIVU: begin
g.writeInstruction('xor', sR2I, sR2I);
g.writeInstruction('div', sr2);
end;
end;
if reg1 <> R0D then begin
g.writeInstruction('mov', sr1, sR0I);
end;
if regInUse then begin
g.writeInstruction('mov', sR0L, sR3L);
end;
end;
end;
TranslatorType.KIND_LONG: begin
stack.popRegs(1);
regInUse := stack.isUsedRegister(R0);
stack.pushReg(reg1);
if reg2 = R0 then begin
g.writeInstruction('xchg', sr1, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_SDIVS: begin
g.writeInstruction('cqo');
g.writeInstruction('idiv', sr1);
end;
TranslatorTreeBuilder.EXPR_SDIVU: begin
g.writeInstruction('xor', sR2L, sR2L);
g.writeInstruction('div', sr1);
end;
end;
g.writeInstruction('mov', sr1, sr2);
end else begin
if regInUse then begin
g.writeInstruction('mov', sR3L, sR0L);
end;
if reg1 <> R0 then begin
g.writeInstruction('mov', sR0L, sr1);
end;
case nodeValue of
TranslatorTreeBuilder.EXPR_SDIVS: begin
g.writeInstruction('cqo');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.EXPR_SDIVU: begin
g.writeInstruction('xor', sR2L, sR2L);
g.writeInstruction('div', sr2);
end;
end;
if reg1 <> R0 then begin
g.writeInstruction('mov', sr1, sR0L);
end;
if regInUse then begin
g.writeInstruction('mov', sR0L, sR3L);
end;
end;
end;
TranslatorType.KIND_FLOAT:
g.writeInstruction('divss', sr1, sr2);
TranslatorType.KIND_DOUBLE:
g.writeInstruction('divsd', sr1, sr2);
TranslatorType.KIND_REAL:
g.writeInstruction('fdivp');
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_SREMS,
TranslatorTreeBuilder.EXPR_SREMU: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_INT: begin
stack.popRegs(1);
regInUse := stack.isUsedRegister(R0D);
stack.pushReg(reg1);
if reg2 = R0D then begin
g.writeInstruction('xchg', sr1, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_SREMS: begin
g.writeInstruction('cdq');
g.writeInstruction('idiv', sr1);
end;
TranslatorTreeBuilder.EXPR_SREMU: begin
g.writeInstruction('xor', sR2I, sR2I);
g.writeInstruction('div', sr1);
end;
end;
g.writeInstruction('mov', sr1, sR2I);
end else begin
if regInUse then begin
g.writeInstruction('mov', sR3L, sR0L);
end;
if reg1 <> R0D then begin
g.writeInstruction('mov', sR0I, sr1);
end;
case nodeValue of
TranslatorTreeBuilder.EXPR_SREMS: begin
g.writeInstruction('cdq');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.EXPR_SREMU: begin
g.writeInstruction('xor', sR2I, sR2I);
g.writeInstruction('div', sr2);
end;
end;
g.writeInstruction('mov', sr1, sR2I);
if regInUse then begin
g.writeInstruction('mov', sR0L, sR3L);
end;
end;
end;
TranslatorType.KIND_LONG: begin
stack.popRegs(1);
regInUse := stack.isUsedRegister(R0);
stack.pushReg(reg1);
if reg2 = R0 then begin
g.writeInstruction('xchg', sr1, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_SREMS: begin
g.writeInstruction('cqo');
g.writeInstruction('idiv', sr1);
end;
TranslatorTreeBuilder.EXPR_SREMU: begin
g.writeInstruction('xor', sR2L, sR2L);
g.writeInstruction('div', sr1);
end;
end;
g.writeInstruction('mov', sr1, sR2L);
end else begin
if regInUse then begin
g.writeInstruction('mov', sR3L, sR0L);
end;
if reg1 <> R0 then begin
g.writeInstruction('mov', sR0L, sr1);
end;
case nodeValue of
TranslatorTreeBuilder.EXPR_SREMS: begin
g.writeInstruction('cqo');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.EXPR_SREMU: begin
g.writeInstruction('xor', sR2L, sR2L);
g.writeInstruction('div', sr2);
end;
end;
g.writeInstruction('mov', sr1, sR2L);
if regInUse then begin
g.writeInstruction('mov', sR0L, sR3L);
end;
end;
end;
TranslatorType.KIND_REAL: begin
regInUse := stack.isUsedRegister(R0W);
if regInUse then begin
g.writeInstruction('mov', sR3L, sR0L);
end;
g.writeInstruction('fxch');
g.writeLabelShort(LABEL_ANONYMOUS);
g.writeInstruction('fprem');
g.writeInstruction('fnstsw', sR0S);
g.writeInstruction('test', sR0I, g.immediateToStringShort($0400));
g.writeInstruction('jnz', LABEL_PRECEDING);
g.writeInstruction('fstp', sST1);
if regInUse then begin
g.writeInstruction('mov', sR0L, sR3L);
end;
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_QMULL: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_LONG: begin
g.writeInstruction('movq', sXMM12, sr1);
g.writeInstruction('movq', sXMM13, sr2);
g.writeInstruction('pmullw', sXMM12, sXMM13);
g.writeInstruction('movq', sr1, sXMM12);
end;
TranslatorType.KIND_ULTRA: begin
if extension < TranslatorTreeBuilder.EXTENSION_SSE4_1 then begin
g.writeInstruction('movdqu', sXMM12, sr1);
g.writeInstruction('movdqu', sXMM13, sr2);
g.writeInstruction('call', FUNCTION_ULTRA_QMULL);
g.writeInstruction('movdqu', sr1, sXMM12);
end else begin
g.writeInstruction('pmulld', sr1, sr2);
end;
end;
TranslatorType.KIND_XVECTOR: begin
g.writeInstruction('mulps', sr1, sr2);
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_QMULH: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_LONG: begin
g.writeInstruction('movq', sXMM12, sr1);
g.writeInstruction('movq', sXMM13, sr2);
g.writeInstruction('pmulhuw', sXMM12, sXMM13);
g.writeInstruction('movq', sr1, sXMM12);
end;
TranslatorType.KIND_ULTRA: begin
g.writeInstruction('movdqu', sXMM12, sr1);
g.writeInstruction('movdqu', sXMM13, sr2);
g.writeInstruction('call', FUNCTION_ULTRA_QMULH);
g.writeInstruction('movdqu', sr1, sXMM12);
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_QMULHS: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
g.writeInstruction('movq', sXMM12, sr1);
g.writeInstruction('movq', sXMM13, sr2);
if extension < TranslatorTreeBuilder.EXTENSION_SSSE3 then begin
g.writeInstruction('call', FUNCTION_LONG_QMULHS);
end else begin
g.writeInstruction('pmulhrsw', sXMM12, sXMM13);
end;
g.writeInstruction('movq', sr1, sXMM12);
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_QDIV: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
g.writeInstruction('divps', sr1, sr2);
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_QADD,
TranslatorTreeBuilder.EXPR_QSUB: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_LONG: begin
g.writeInstruction('movq', sXMM12, sr1);
g.writeInstruction('movq', sXMM13, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_QADD:
g.writeInstruction('paddw', sXMM12, sXMM13);
TranslatorTreeBuilder.EXPR_QSUB:
g.writeInstruction('psubw', sXMM12, sXMM13);
end;
g.writeInstruction('movq', sr1, sXMM12);
end;
TranslatorType.KIND_ULTRA: begin
case nodeValue of
TranslatorTreeBuilder.EXPR_QADD:
g.writeInstruction('paddd', sr1, sr2);
TranslatorTreeBuilder.EXPR_QSUB:
g.writeInstruction('psubd', sr1, sr2);
end;
end;
TranslatorType.KIND_XVECTOR: begin
case nodeValue of
TranslatorTreeBuilder.EXPR_QADD:
g.writeInstruction('addps', sr1, sr2);
TranslatorTreeBuilder.EXPR_QSUB:
g.writeInstruction('subps', sr1, sr2);
end;
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_QADDS,
TranslatorTreeBuilder.EXPR_QADDUS,
TranslatorTreeBuilder.EXPR_QSUBS,
TranslatorTreeBuilder.EXPR_QSUBUS: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
g.writeInstruction('movq', sXMM12, sr1);
g.writeInstruction('movq', sXMM13, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_QADDS:
g.writeInstruction('paddsw', sXMM12, sXMM13);
TranslatorTreeBuilder.EXPR_QADDUS:
g.writeInstruction('paddusw', sXMM12, sXMM13);
TranslatorTreeBuilder.EXPR_QSUBS:
g.writeInstruction('psubsw', sXMM12, sXMM13);
TranslatorTreeBuilder.EXPR_QSUBUS:
g.writeInstruction('psubusw', sXMM12, sXMM13);
end;
g.writeInstruction('movq', sr1, sXMM12);
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_OMULL,
TranslatorTreeBuilder.EXPR_OMULH,
TranslatorTreeBuilder.EXPR_OMULHS,
TranslatorTreeBuilder.EXPR_OADD,
TranslatorTreeBuilder.EXPR_OADDS,
TranslatorTreeBuilder.EXPR_OADDUS,
TranslatorTreeBuilder.EXPR_OSUB,
TranslatorTreeBuilder.EXPR_OSUBS,
TranslatorTreeBuilder.EXPR_OSUBUS,
TranslatorTreeBuilder.EXPR_OGT,
TranslatorTreeBuilder.EXPR_OGE,
TranslatorTreeBuilder.EXPR_OLT,
TranslatorTreeBuilder.EXPR_OLE,
TranslatorTreeBuilder.EXPR_OEQ,
TranslatorTreeBuilder.EXPR_ONE: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
case nodeValue of
TranslatorTreeBuilder.EXPR_OMULL: begin
g.writeInstruction('pmullw', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_OMULH: begin
g.writeInstruction('pmulhuw', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_OMULHS: begin
if extension < TranslatorTreeBuilder.EXTENSION_SSSE3 then begin
g.writeInstruction('movdqu', sXMM12, sr1);
g.writeInstruction('movdqu', sXMM13, sr2);
g.writeInstruction('call', FUNCTION_ULTRA_OMULHS);
g.writeInstruction('movdqu', sr1, sXMM12);
end else begin
g.writeInstruction('pmulhrsw', sr1, sr2);
end;
end;
TranslatorTreeBuilder.EXPR_OADD: begin
g.writeInstruction('paddw', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_OADDS: begin
g.writeInstruction('paddsw', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_OADDUS: begin
g.writeInstruction('paddusw', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_OSUB: begin
g.writeInstruction('psubw', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_OSUBS: begin
g.writeInstruction('psubsw', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_OSUBUS: begin
g.writeInstruction('psubusw', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_QGT: begin
g.writeInstruction('pcmpgtw', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_QGE: begin
g.writeInstruction('pcmpgtw', sr2, sr1);
g.writeInstruction('movdqu', sr1, sr2);
g.writeInstruction('movdqu', sr2, g.memoryToString(MNONE, LABEL_POOL_ULTRA_CONTENT,
programmeXUltras.indexAcquire(ultraBuild(-1, -1)) * 16));
g.writeInstruction('pxor', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_QLT: begin
g.writeInstruction('pcmpgtw', sr2, sr1);
g.writeInstruction('movdqu', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_QLE: begin
g.writeInstruction('pcmpgtw', sr1, sr2);
g.writeInstruction('movdqu', sr2, g.memoryToString(MNONE, LABEL_POOL_ULTRA_CONTENT,
programmeXUltras.indexAcquire(ultraBuild(-1, -1)) * 16));
g.writeInstruction('pxor', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_QEQ: begin
g.writeInstruction('pcmpeqw', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_QNE: begin
g.writeInstruction('pcmpeqw', sr1, sr2);
g.writeInstruction('movdqu', sr2, g.memoryToString(MNONE, LABEL_POOL_ULTRA_CONTENT,
programmeXUltras.indexAcquire(ultraBuild(-1, -1)) * 16));
g.writeInstruction('pxor', sr1, sr2);
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
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
g.writeInstruction('mov', sR1I, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_SSLL:
g.writeInstruction('shl', sr1, sR1B);
TranslatorTreeBuilder.EXPR_SSRA:
g.writeInstruction('sar', sr1, sR1B);
TranslatorTreeBuilder.EXPR_SSRL:
g.writeInstruction('shr', sr1, sR1B);
end;
stack.restoreRegs(g);
end else begin
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
buffer := (child.associate as IntegerAsObject).byteValue();
simm := g.immediateToStringByte(buffer);
case nodeValue of
TranslatorTreeBuilder.EXPR_SSLL:
g.writeInstruction('shl', sr1, simm);
TranslatorTreeBuilder.EXPR_SSRA:
g.writeInstruction('sar', sr1, simm);
TranslatorTreeBuilder.EXPR_SSRL:
g.writeInstruction('shr', sr1, simm);
end;
end;
end;
TranslatorTreeBuilder.EXPR_QSLL,
TranslatorTreeBuilder.EXPR_QSRA,
TranslatorTreeBuilder.EXPR_QSRL: begin
child := node.getChild(1) as SyntaxNode;
if child.value <> TranslatorTreeBuilder.EXPR_VALUE_INT then begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_LONG: begin
g.writeInstruction('movq', sXMM12, sr1);
g.writeInstruction('movd', sXMM13, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_QSLL:
g.writeInstruction('psllw', sXMM12, sXMM13);
TranslatorTreeBuilder.EXPR_QSRA:
g.writeInstruction('psraw', sXMM12, sXMM13);
TranslatorTreeBuilder.EXPR_QSRL:
g.writeInstruction('psrlw', sXMM12, sXMM13);
end;
g.writeInstruction('movq', sr1, sXMM12);
end;
TranslatorType.KIND_ULTRA: begin
g.writeInstruction('movd', sXMM12, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_QSLL:
g.writeInstruction('pslld', sr1, sXMM12);
TranslatorTreeBuilder.EXPR_QSRA:
g.writeInstruction('psrad', sr1, sXMM12);
TranslatorTreeBuilder.EXPR_QSRL:
g.writeInstruction('psrld', sr1, sXMM12);
end;
end;
end;
stack.restoreRegs(g);
end else begin
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
buffer := (child.associate as IntegerAsObject).byteValue();
simm := g.immediateToStringByte(buffer);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_LONG: begin
g.writeInstruction('movq', sXMM12, sr1);
case nodeValue of
TranslatorTreeBuilder.EXPR_QSLL:
g.writeInstruction('psllw', sXMM12, simm);
TranslatorTreeBuilder.EXPR_QSRA:
g.writeInstruction('psraw', sXMM12, simm);
TranslatorTreeBuilder.EXPR_QSRL:
g.writeInstruction('psrlw', sXMM12, simm);
end;
g.writeInstruction('movq', sr1, sXMM12);
end;
TranslatorType.KIND_ULTRA: begin
case nodeValue of
TranslatorTreeBuilder.EXPR_QSLL:
g.writeInstruction('pslld', sr1, simm);
TranslatorTreeBuilder.EXPR_QSRA:
g.writeInstruction('psrad', sr1, simm);
TranslatorTreeBuilder.EXPR_QSRL:
g.writeInstruction('psrld', sr1, simm);
end;
end;
end;
end;
end;
TranslatorTreeBuilder.EXPR_OSLL,
TranslatorTreeBuilder.EXPR_OSRA,
TranslatorTreeBuilder.EXPR_OSRL: begin
child := node.getChild(1) as SyntaxNode;
if child.value <> TranslatorTreeBuilder.EXPR_VALUE_INT then begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
g.writeInstruction('movd', sXMM12, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_QSLL:
g.writeInstruction('psllw', sr1, sXMM12);
TranslatorTreeBuilder.EXPR_QSRA:
g.writeInstruction('psraw', sr1, sXMM12);
TranslatorTreeBuilder.EXPR_QSRL:
g.writeInstruction('psrlw', sr1, sXMM12);
end;
stack.restoreRegs(g);
end else begin
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
buffer := (child.associate as IntegerAsObject).byteValue();
simm := g.immediateToStringByte(buffer);
case nodeValue of
TranslatorTreeBuilder.EXPR_QSLL:
g.writeInstruction('psllw', sr1, simm);
TranslatorTreeBuilder.EXPR_QSRA:
g.writeInstruction('psraw', sr1, simm);
TranslatorTreeBuilder.EXPR_QSRL:
g.writeInstruction('psrlw', sr1, simm);
end;
end;
end;
TranslatorTreeBuilder.EXPR_SGT,
TranslatorTreeBuilder.EXPR_SGE,
TranslatorTreeBuilder.EXPR_SLT,
TranslatorTreeBuilder.EXPR_SLE,
TranslatorTreeBuilder.EXPR_SEQ,
TranslatorTreeBuilder.EXPR_SNE: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(2);
buffer := (node.getChild(0) as SyntaxNode).dataType.kind;
case buffer of
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_INT, TranslatorType.KIND_LONG: begin
g.writeInstruction('cmp', sr1, sr2);
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 := R0D + (reg1 and $0f);
srb := g.registerToString(R0B + (reg1 and $0f));
sr1 := g.registerToString(reg1);
stack.pushReg(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_ULTRA, TranslatorType.KIND_XVECTOR: begin
case buffer of
TranslatorType.KIND_ULTRA:
g.writeInstruction('pcmpeqw', sr1, sr2);
TranslatorType.KIND_XVECTOR:
g.writeInstruction('cmpps', sr1, sr2, g.immediateToStringByte(0));
end;
g.writeInstruction('psrlw', sr1, g.immediateToString($08));
g.writeInstruction('packuswb', sr1, sr1);
g.writeInstruction('movq', sR3L, sr1);
g.writeInstruction('cmp', sR3L, g.immediateToString(-1));
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_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_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_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.allocateGPR32bit(g); { регистр флагов – без изменений }
srb := g.registerToString(R0B + (reg1 and $0f));
sr1 := g.registerToString(reg1);
case nodeValue of
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', sr2, sr1, g.immediateToStringByte(1));
g.writeInstruction('pmovmskb', sR3L, sr2);
end;
TranslatorTreeBuilder.EXPR_SGE: begin
g.writeInstruction('cmpss', sr2, sr1, g.immediateToStringByte(2));
g.writeInstruction('pmovmskb', sR3L, sr2);
end;
TranslatorTreeBuilder.EXPR_SLT: begin
g.writeInstruction('cmpss', sr1, sr2, g.immediateToStringByte(1));
g.writeInstruction('pmovmskb', sR3L, sr1);
end;
TranslatorTreeBuilder.EXPR_SLE: begin
g.writeInstruction('cmpss', sr1, sr2, g.immediateToStringByte(2));
g.writeInstruction('pmovmskb', sR3L, sr1);
end;
TranslatorTreeBuilder.EXPR_SEQ: begin
g.writeInstruction('cmpss', sr1, sr2, g.immediateToStringByte(0));
g.writeInstruction('pmovmskb', sR3L, sr1);
end;
TranslatorTreeBuilder.EXPR_SNE: begin
g.writeInstruction('cmpss', sr1, sr2, g.immediateToStringByte(4));
g.writeInstruction('pmovmskb', sR3L, sr1);
end;
end;
g.writeInstruction('test', sR3I, 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.allocateGPR32bit(g); { регистр флагов – без изменений }
srb := g.registerToString(R0B + (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', sr2, sr1, g.immediateToStringByte(1));
g.writeInstruction('pmovmskb', sR3L, sr2);
end;
TranslatorTreeBuilder.EXPR_SGE: begin
g.writeInstruction('cmpsd', sr2, sr1, g.immediateToStringByte(2));
g.writeInstruction('pmovmskb', sR3L, sr2);
end;
TranslatorTreeBuilder.EXPR_SLT: begin
g.writeInstruction('cmpsd', sr1, sr2, g.immediateToStringByte(1));
g.writeInstruction('pmovmskb', sR3L, sr1);
end;
TranslatorTreeBuilder.EXPR_SLE: begin
g.writeInstruction('cmpsd', sr1, sr2, g.immediateToStringByte(2));
g.writeInstruction('pmovmskb', sR3L, sr1);
end;
TranslatorTreeBuilder.EXPR_SEQ: begin
g.writeInstruction('cmpsd', sr1, sr2, g.immediateToStringByte(0));
g.writeInstruction('pmovmskb', sR3L, sr1);
end;
TranslatorTreeBuilder.EXPR_SNE: begin
g.writeInstruction('cmpsd', sr1, sr2, g.immediateToStringByte(4));
g.writeInstruction('pmovmskb', sR3L, sr1);
end;
end;
g.writeInstruction('test', sR3I, 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.allocateGPR32bit(g); { регистр флагов – без изменений }
srb := g.registerToString(R0B + (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', sR1B, g.immediateToStringByte($ff));
g.writeInstruction('or', sR1I, sR1I);
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.allocateGPR32bit(g); { регистр флагов – без изменений }
srb := g.registerToString(R0B + (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_QGT,
TranslatorTreeBuilder.EXPR_QGE,
TranslatorTreeBuilder.EXPR_QLT,
TranslatorTreeBuilder.EXPR_QLE,
TranslatorTreeBuilder.EXPR_QEQ,
TranslatorTreeBuilder.EXPR_QNE: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_LONG: begin
g.writeInstruction('movq', sXMM12, sr1);
g.writeInstruction('movq', sXMM13, sr2);
case nodeValue of
TranslatorTreeBuilder.EXPR_QGT: begin
g.writeInstruction('pcmpgtw', sXMM12, sXMM13);
g.writeInstruction('movq', sr1, sXMM12);
end;
TranslatorTreeBuilder.EXPR_QGE: begin
g.writeInstruction('pcmpgtw', sXMM13, sXMM12);
g.writeInstruction('movq', sr1, sXMM13);
g.writeInstruction('xor', sr1, g.immediateToString(-1));
end;
TranslatorTreeBuilder.EXPR_QLT: begin
g.writeInstruction('pcmpgtw', sXMM13, sXMM12);
g.writeInstruction('movq', sr1, sXMM13);
end;
TranslatorTreeBuilder.EXPR_QLE: begin
g.writeInstruction('pcmpgtw', sXMM12, sXMM13);
g.writeInstruction('movq', sr1, sXMM12);
g.writeInstruction('xor', sr1, g.immediateToString(-1));
end;
TranslatorTreeBuilder.EXPR_QEQ: begin
g.writeInstruction('pcmpeqw', sXMM12, sXMM13);
g.writeInstruction('movq', sr1, sXMM12);
end;
TranslatorTreeBuilder.EXPR_QNE: begin
g.writeInstruction('pcmpeqw', sXMM12, sXMM13);
g.writeInstruction('movq', sr1, sXMM12);
g.writeInstruction('xor', sr1, g.immediateToString(-1));
end;
end;
end;
TranslatorType.KIND_ULTRA: begin
case nodeValue of
TranslatorTreeBuilder.EXPR_QGT: begin
g.writeInstruction('pcmpgtd', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_QGE: begin
g.writeInstruction('pcmpgtd', sr2, sr1);
g.writeInstruction('movdqu', sr1, sr2);
g.writeInstruction('movdqu', sr2, g.memoryToString(MNONE, LABEL_POOL_ULTRA_CONTENT,
programmeXUltras.indexAcquire(ultraBuild(-1, -1)) * 16));
g.writeInstruction('pxor', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_QLT: begin
g.writeInstruction('pcmpgtd', sr2, sr1);
g.writeInstruction('movdqu', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_QLE: begin
g.writeInstruction('pcmpgtd', sr1, sr2);
g.writeInstruction('movdqu', sr2, g.memoryToString(MNONE, LABEL_POOL_ULTRA_CONTENT,
programmeXUltras.indexAcquire(ultraBuild(-1, -1)) * 16));
g.writeInstruction('pxor', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_QEQ: begin
g.writeInstruction('pcmpeqd', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_QNE: begin
g.writeInstruction('pcmpeqd', sr1, sr2);
g.writeInstruction('movdqu', sr2, g.memoryToString(MNONE, LABEL_POOL_ULTRA_CONTENT,
programmeXUltras.indexAcquire(ultraBuild(-1, -1)) * 16));
g.writeInstruction('pxor', sr1, sr2);
end;
end;
end;
TranslatorType.KIND_XVECTOR: begin
stack.changeToXMM(0, XPINT);
case nodeValue of
TranslatorTreeBuilder.EXPR_SGT: begin
g.writeInstruction('cmpps', sr2, sr1, g.immediateToStringByte(1));
g.writeInstruction('movdqu', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_SGE: begin
g.writeInstruction('cmpps', sr2, sr1, g.immediateToStringByte(2));
g.writeInstruction('movdqu', sr1, sr2);
end;
TranslatorTreeBuilder.EXPR_SLT: begin
g.writeInstruction('cmpps', sr1, sr2, g.immediateToStringByte(1));
end;
TranslatorTreeBuilder.EXPR_SLE: begin
g.writeInstruction('cmpps', sr1, sr2, g.immediateToStringByte(2));
end;
TranslatorTreeBuilder.EXPR_SEQ: begin
g.writeInstruction('cmpps', sr1, sr2, g.immediateToStringByte(0));
end;
TranslatorTreeBuilder.EXPR_SNE: begin
g.writeInstruction('cmpps', sr1, sr2, g.immediateToStringByte(4));
end;
end;
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.EXPR_SANDB,
TranslatorTreeBuilder.EXPR_SXORB,
TranslatorTreeBuilder.EXPR_SORB: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.popRegs(1);
case nodeValue of
TranslatorTreeBuilder.EXPR_SANDB:
g.writeInstruction('test', sr1, sr2);
TranslatorTreeBuilder.EXPR_SXORB:
g.writeInstruction('xor', sr1, sr2);
TranslatorTreeBuilder.EXPR_SORB:
g.writeInstruction('or', sr1, sr2);
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
case (node.getChild(0) as SyntaxNode).dataType.kind of
TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_INT, TranslatorType.KIND_LONG: begin
case nodeValue of
TranslatorTreeBuilder.EXPR_SANDB:
g.writeInstruction('and', sr1, sr2);
TranslatorTreeBuilder.EXPR_SXORB:
g.writeInstruction('xor', sr1, sr2);
TranslatorTreeBuilder.EXPR_SORB:
g.writeInstruction('or', sr1, sr2);
end;
end;
TranslatorType.KIND_ULTRA: begin
case nodeValue of
TranslatorTreeBuilder.EXPR_SANDB:
g.writeInstruction('pand', sr1, sr2);
TranslatorTreeBuilder.EXPR_SXORB:
g.writeInstruction('pxor', sr1, sr2);
TranslatorTreeBuilder.EXPR_SORB:
g.writeInstruction('por', sr1, sr2);
end;
end;
end;
stack.restoreRegs(g);
end;
end;
TranslatorTreeBuilder.EXPR_SZR_TEST: begin
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
g.writeInstruction('test', sr1, sr2);
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.popRegs(1);
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.changeToGPR32bit(0);
srb := g.registerToString(R0B + (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
reg1 := stack.getRegAt(1);
reg2 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
sr2 := g.registerToString(reg2);
stack.popRegs(1);
g.writeInstruction('test', sr1, sr2);
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.popRegs(1);
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.changeToGPR32bit(0);
srb := g.registerToString(R0B + (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
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
g.writeInstruction('test', sr1, sr1);
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.popRegs(1);
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.changeToGPR32bit(0);
srb := g.registerToString(R0B + (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
reg1 := stack.getRegAt(0);
sr1 := g.registerToString(reg1);
g.writeInstruction('test', sr1, sr1);
if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
stack.popRegs(1);
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.changeToGPR32bit(0);
srb := g.registerToString(R0B + (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(R0B + (reg2 and $0f));
srw := g.registerToString(R0W + (reg2 and $0f));
sr2 := g.registerToString(reg2);
buffer := child.dataType.kind;
case buffer 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.allocateGPR32bit(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_BYTE,
TranslatorType.KIND_SHORT, TranslatorType.KIND_INT: begin
case buffer of
TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT:
g.writeInstruction('mov', smm, srw);
TranslatorType.KIND_BYTE:
g.writeInstruction('mov', smm, srb);
TranslatorType.KIND_INT:
g.writeInstruction('mov', smm, sr2);
end;
if nodeType <> nil then begin
reg1 := stack.allocateGPR32bit(g);
if reg1 <> reg2 then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sr2);
end;
end;
stack.restoreRegs(g);
end;
TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY,
TranslatorType.KIND_FUNC, TranslatorType.KIND_LONG: begin
g.writeInstruction('mov', smm, sr2);
if nodeType <> nil then begin
reg1 := stack.allocateGPR64bit(g);
if reg1 <> reg2 then begin
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sr2);
end;
end;
stack.restoreRegs(g);
end;
TranslatorType.KIND_ULTRA: begin
g.writeInstruction('movdqu', smm, sr2);
if nodeType <> nil then begin
stack.pushReg(reg2);
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_XVECTOR: begin
g.writeInstruction('movups', smm, sr2);
if nodeType <> nil then begin
stack.pushReg(reg2);
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);
smmw := mem.memoryToString(MWORD, 0);
smmt := mem.memoryToString(MREAL, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
buffer := child.dataType.kind;
case buffer of
TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
TranslatorType.KIND_SHORT, TranslatorType.KIND_INT: begin
case buffer of
TranslatorType.KIND_CHAR:
g.writeInstruction('movzx', sR3I, smmw);
TranslatorType.KIND_BYTE:
g.writeInstruction('movsx', sR3I, smmb);
TranslatorType.KIND_SHORT:
g.writeInstruction('movsx', sR3I, smmw);
TranslatorType.KIND_INT:
g.writeInstruction('mov', sR3I, smm);
end;
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SADD:
g.writeInstruction('add', sR3I, sr2);
TranslatorTreeBuilder.ASSIGN_SSUB:
g.writeInstruction('sub', sR3I, sr2);
TranslatorTreeBuilder.ASSIGN_SMULL:
g.writeInstruction('imul', sR3I, sr2);
end;
case buffer of
TranslatorType.KIND_BYTE:
g.writeInstruction('mov', smm, sR3B);
TranslatorType.KIND_SHORT, TranslatorType.KIND_CHAR:
g.writeInstruction('mov', smm, sR3S);
TranslatorType.KIND_INT:
g.writeInstruction('mov', smm, sR3I);
end;
if nodeType <> nil then begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR3I);
end;
end;
TranslatorType.KIND_LONG: begin
g.writeInstruction('mov', sR3L, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SADD:
g.writeInstruction('add', sR3L, sr2);
TranslatorTreeBuilder.ASSIGN_SSUB:
g.writeInstruction('sub', sR3L, sr2);
TranslatorTreeBuilder.ASSIGN_SMULL:
g.writeInstruction('imul', sR3L, sr2);
end;
g.writeInstruction('mov', smm, sR3L);
if nodeType <> nil then begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR3L);
end;
end;
TranslatorType.KIND_FLOAT: begin
g.writeInstruction('movss', sXMM12, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SADD:
g.writeInstruction('addss', sXMM12, sr2);
TranslatorTreeBuilder.ASSIGN_SSUB:
g.writeInstruction('subss', sXMM12, sr2);
TranslatorTreeBuilder.ASSIGN_SMULL:
g.writeInstruction('mulss', sXMM12, sr2);
end;
g.writeInstruction('movss', smm, sXMM12);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movss', sr2, sXMM12);
end;
end;
TranslatorType.KIND_DOUBLE: begin
g.writeInstruction('movsd', sXMM12, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SADD:
g.writeInstruction('addsd', sXMM12, sr2);
TranslatorTreeBuilder.ASSIGN_SSUB:
g.writeInstruction('subsd', sXMM12, sr2);
TranslatorTreeBuilder.ASSIGN_SMULL:
g.writeInstruction('mulsd', sXMM12, sr2);
end;
g.writeInstruction('movsd', smm, sXMM12);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movsd', sr2, sXMM12);
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);
smmw := mem.memoryToString(MWORD, 0);
smmt := mem.memoryToString(MREAL, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
buffer := child.dataType.kind;
case buffer of
TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
TranslatorType.KIND_SHORT, TranslatorType.KIND_INT: begin
g.writeInstruction('mov', sR3L, sR0L);
if reg2 = R0D then begin
reg2 := R3D;
sr2 := g.registerToString(reg2);
end;
case buffer of
TranslatorType.KIND_CHAR:
g.writeInstruction('movzx', sR0I, smmw);
TranslatorType.KIND_BYTE:
g.writeInstruction('movsx', sR0I, smmb);
TranslatorType.KIND_SHORT:
g.writeInstruction('movsx', sR0I, smmw);
TranslatorType.KIND_INT:
g.writeInstruction('mov', sR0I, smm);
end;
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SDIVS: begin
g.writeInstruction('cdq');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.ASSIGN_SDIVU: begin
g.writeInstruction('xor', sR2I, sR2I);
g.writeInstruction('div', sr2);
end;
end;
case buffer of
TranslatorType.KIND_BYTE:
g.writeInstruction('mov', smm, sR0B);
TranslatorType.KIND_SHORT, TranslatorType.KIND_CHAR:
g.writeInstruction('mov', smm, sR0S);
TranslatorType.KIND_INT:
g.writeInstruction('mov', smm, sR0I);
end;
if nodeType <> nil then begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR0I);
end;
g.writeInstruction('mov', sR0L, sR3L);
end;
TranslatorType.KIND_LONG: begin
g.writeInstruction('mov', sR3L, sR0L);
if reg2 = R0 then begin
reg2 := R3;
sr2 := g.registerToString(reg2);
end;
g.writeInstruction('mov', sR0L, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SDIVS: begin
g.writeInstruction('cqo');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.ASSIGN_SDIVU: begin
g.writeInstruction('xor', sR2L, sR2L);
g.writeInstruction('div', sr2);
end;
end;
g.writeInstruction('mov', smm, sR0L);
if nodeType <> nil then begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR0L);
end;
g.writeInstruction('mov', sR0L, sR3L);
end;
TranslatorType.KIND_FLOAT: begin
g.writeInstruction('movss', sXMM12, smm);
g.writeInstruction('divss', sXMM12, sr2);
g.writeInstruction('movss', smm, sXMM12);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movss', sr2, sXMM12);
end;
end;
TranslatorType.KIND_DOUBLE: begin
g.writeInstruction('movsd', sXMM12, smm);
g.writeInstruction('divsd', sXMM12, sr2);
g.writeInstruction('movsd', smm, sXMM12);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movsd', sr2, sXMM12);
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);
smmw := mem.memoryToString(MWORD, 0);
smmt := mem.memoryToString(MREAL, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
buffer := child.dataType.kind;
case buffer of
TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
TranslatorType.KIND_SHORT, TranslatorType.KIND_INT: begin
g.writeInstruction('mov', sR3L, sR0L);
if reg2 = R0D then begin
reg2 := R3D;
sr2 := g.registerToString(reg2);
end;
case buffer of
TranslatorType.KIND_CHAR:
g.writeInstruction('movzx', sR0I, smmw);
TranslatorType.KIND_BYTE:
g.writeInstruction('movsx', sR0I, smmb);
TranslatorType.KIND_SHORT:
g.writeInstruction('movsx', sR0I, smmw);
TranslatorType.KIND_INT:
g.writeInstruction('mov', sR0I, smm);
end;
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SREMS: begin
g.writeInstruction('cdq');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.ASSIGN_SREMU: begin
g.writeInstruction('xor', sR2I, sR2I);
g.writeInstruction('div', sr2);
end;
end;
case buffer of
TranslatorType.KIND_BYTE:
g.writeInstruction('mov', smm, sR2B);
TranslatorType.KIND_SHORT, TranslatorType.KIND_CHAR:
g.writeInstruction('mov', smm, sR2S);
TranslatorType.KIND_INT:
g.writeInstruction('mov', smm, sR2I);
end;
if nodeType <> nil then begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR2I);
end;
g.writeInstruction('mov', sR0L, sR3L);
end;
TranslatorType.KIND_LONG: begin
g.writeInstruction('mov', sR3L, sR0L);
if reg2 = R0 then begin
reg2 := R3;
sr2 := g.registerToString(reg2);
end;
g.writeInstruction('mov', sR0L, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SREMS: begin
g.writeInstruction('cqo');
g.writeInstruction('idiv', sr2);
end;
TranslatorTreeBuilder.ASSIGN_SREMU: begin
g.writeInstruction('xor', sR2L, sR2L);
g.writeInstruction('div', sr2);
end;
end;
g.writeInstruction('mov', smm, sR2L);
if nodeType <> nil then begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR2L);
end;
g.writeInstruction('mov', sR0L, sR3L);
end;
TranslatorType.KIND_FLOAT, TranslatorType.KIND_DOUBLE, TranslatorType.KIND_REAL: begin
regInUse := stack.isUsedRegister(R0D);
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', sR3L, sR0L);
end;
g.writeInstruction('fld', smmt);
g.writeLabelShort(LABEL_ANONYMOUS);
g.writeInstruction('fprem');
g.writeInstruction('fnstsw', sR0S);
g.writeInstruction('test', sR0I, 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', sR0L, sR3L);
end;
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.ASSIGN_QMULL,
TranslatorTreeBuilder.ASSIGN_QADD,
TranslatorTreeBuilder.ASSIGN_QSUB: begin
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, true);
smm := mem.memoryToString(MNONE, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
case child.dataType.kind of
TranslatorType.KIND_LONG: begin
g.writeInstruction('movq', sXMM12, smm);
g.writeInstruction('movq', sXMM13, sr2);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_QMULL:
g.writeInstruction('pmullw', sXMM12, sXMM13);
TranslatorTreeBuilder.ASSIGN_QADD:
g.writeInstruction('paddw', sXMM12, sXMM13);
TranslatorTreeBuilder.ASSIGN_QSUB:
g.writeInstruction('psubw', sXMM12, sXMM13);
end;
g.writeInstruction('movq', smm, sXMM12);
if nodeType <> nil then begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movq', sr1, sXMM12);
end;
end;
TranslatorType.KIND_ULTRA: begin
g.writeInstruction('movdqu', sXMM12, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_QMULL:
if extension < TranslatorTreeBuilder.EXTENSION_SSE4_1 then begin
g.writeInstruction('movdqu', sXMM13, sr2);
g.writeInstruction('call', FUNCTION_ULTRA_QMULL);
end else begin
g.writeInstruction('pmulld', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_QADD:
g.writeInstruction('paddd', sXMM12, sr2);
TranslatorTreeBuilder.ASSIGN_QSUB:
g.writeInstruction('psubd', sXMM12, sr2);
end;
g.writeInstruction('movdqu', smm, sXMM12);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movdqu', sr2, sXMM12);
end;
end;
TranslatorType.KIND_XVECTOR: begin
g.writeInstruction('movups', sXMM12, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_QMULL:
g.writeInstruction('mulps', sXMM12, sr2);
TranslatorTreeBuilder.ASSIGN_QADD:
g.writeInstruction('addps', sXMM12, sr2);
TranslatorTreeBuilder.ASSIGN_QSUB:
g.writeInstruction('subps', sXMM12, sr2);
end;
g.writeInstruction('movups', smm, sXMM12);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movups', sr2, sXMM12);
end;
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.ASSIGN_QMULH: begin
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, true);
smm := mem.memoryToString(MNONE, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
case child.dataType.kind of
TranslatorType.KIND_LONG: begin
g.writeInstruction('movq', sXMM12, smm);
g.writeInstruction('movq', sXMM13, sr2);
g.writeInstruction('pmulhuw', sXMM12, sXMM13);
g.writeInstruction('movq', smm, sXMM12);
if nodeType <> nil then begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movq', sr1, sXMM12);
end;
end;
TranslatorType.KIND_ULTRA: begin
g.writeInstruction('movdqu', sXMM12, smm);
g.writeInstruction('movdqu', sXMM13, sr2);
g.writeInstruction('call', FUNCTION_ULTRA_QMULH);
g.writeInstruction('movdqu', smm, sXMM12);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movdqu', sr2, sXMM12);
end;
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.ASSIGN_QDIV: begin
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, true);
smm := mem.memoryToString(MNONE, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
g.writeInstruction('movups', sXMM12, smm);
g.writeInstruction('divps', sXMM12, sr2);
g.writeInstruction('movups', smm, sXMM12);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movups', sr2, sXMM12);
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.ASSIGN_QMULHS,
TranslatorTreeBuilder.ASSIGN_QADDS,
TranslatorTreeBuilder.ASSIGN_QADDUS,
TranslatorTreeBuilder.ASSIGN_QSUBS,
TranslatorTreeBuilder.ASSIGN_QSUBUS: begin
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, true);
smm := mem.memoryToString(MNONE, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
g.writeInstruction('movq', sXMM12, smm);
g.writeInstruction('movq', sXMM13, sr2);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_QMULHS:
if extension < TranslatorTreeBuilder.EXTENSION_SSSE3 then begin
g.writeInstruction('call', FUNCTION_LONG_QMULHS);
end else begin
g.writeInstruction('pmulhrsw', sXMM12, sXMM13);
end;
TranslatorTreeBuilder.EXPR_QADDS:
g.writeInstruction('paddsw', sXMM12, sXMM13);
TranslatorTreeBuilder.EXPR_QADDUS:
g.writeInstruction('paddusw', sXMM12, sXMM13);
TranslatorTreeBuilder.EXPR_QSUBS:
g.writeInstruction('psubsw', sXMM12, sXMM13);
TranslatorTreeBuilder.EXPR_QSUBUS:
g.writeInstruction('psubusw', sXMM12, sXMM13);
end;
g.writeInstruction('movq', smm, sXMM12);
if nodeType <> nil then begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movq', sr1, sXMM12);
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.ASSIGN_OMULL,
TranslatorTreeBuilder.ASSIGN_OMULH,
TranslatorTreeBuilder.ASSIGN_OMULHS,
TranslatorTreeBuilder.ASSIGN_OADD,
TranslatorTreeBuilder.ASSIGN_OADDS,
TranslatorTreeBuilder.ASSIGN_OADDUS,
TranslatorTreeBuilder.ASSIGN_OSUB,
TranslatorTreeBuilder.ASSIGN_OSUBS,
TranslatorTreeBuilder.ASSIGN_OSUBUS,
TranslatorTreeBuilder.ASSIGN_OGT,
TranslatorTreeBuilder.ASSIGN_OGE,
TranslatorTreeBuilder.ASSIGN_OLT,
TranslatorTreeBuilder.ASSIGN_OLE,
TranslatorTreeBuilder.ASSIGN_OEQ,
TranslatorTreeBuilder.ASSIGN_ONE: begin
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, true);
smm := mem.memoryToString(MNONE, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
g.writeInstruction('movdqu', sXMM12, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_OMULL: begin
g.writeInstruction('pmullw', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_OMULH: begin
g.writeInstruction('pmulhuw', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_OMULHS: begin
if extension < TranslatorTreeBuilder.EXTENSION_SSSE3 then begin
g.writeInstruction('movdqu', sXMM13, sr2);
g.writeInstruction('call', FUNCTION_ULTRA_OMULHS);
end else begin
g.writeInstruction('pmulhrsw', sXMM12, sr2);
end;
end;
TranslatorTreeBuilder.ASSIGN_OADD: begin
g.writeInstruction('paddw', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_OADDS: begin
g.writeInstruction('paddsw', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_OADDUS: begin
g.writeInstruction('paddusw', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_OSUB: begin
g.writeInstruction('psubw', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_OSUBS: begin
g.writeInstruction('psubsw', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_OSUBUS: begin
g.writeInstruction('psubusw', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_OGT: begin
g.writeInstruction('pcmpgtw', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_OGE: begin
g.writeInstruction('pcmpgtw', sr2, sXMM12);
g.writeInstruction('movdqu', sXMM12, sr2);
g.writeInstruction('movdqu', sr2, g.memoryToString(MNONE, LABEL_POOL_ULTRA_CONTENT,
programmeXUltras.indexAcquire(ultraBuild(-1, -1)) * 16));
g.writeInstruction('pxor', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_OLT: begin
g.writeInstruction('pcmpgtw', sr2, sXMM12);
g.writeInstruction('movdqu', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_OLE: begin
g.writeInstruction('pcmpgtw', sXMM12, sr2);
g.writeInstruction('movdqu', sr2, g.memoryToString(MNONE, LABEL_POOL_ULTRA_CONTENT,
programmeXUltras.indexAcquire(ultraBuild(-1, -1)) * 16));
g.writeInstruction('pxor', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_OEQ: begin
g.writeInstruction('pcmpeqw', sXMM12, sr2);
end;
TranslatorTreeBuilder.ASSIGN_ONE: begin
g.writeInstruction('pcmpeqw', sXMM12, sr2);
g.writeInstruction('movdqu', sr2, g.memoryToString(MNONE, LABEL_POOL_ULTRA_CONTENT,
programmeXUltras.indexAcquire(ultraBuild(-1, -1)) * 16));
g.writeInstruction('pxor', sXMM12, sr2);
end;
end;
g.writeInstruction('movdqu', smm, sXMM12);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movdqu', sr2, sXMM12);
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);
smmw := mem.memoryToString(MWORD, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
buffer := child.dataType.kind;
g.writeInstruction('mov', sR1I, sr2);
case buffer of
TranslatorType.KIND_CHAR:
g.writeInstruction('movzx', sR3I, smmw);
TranslatorType.KIND_BYTE:
g.writeInstruction('movsx', sR3I, smmb);
TranslatorType.KIND_SHORT:
g.writeInstruction('movsx', sR3I, smmw);
TranslatorType.KIND_INT:
g.writeInstruction('mov', sR3I, smm);
TranslatorType.KIND_LONG:
g.writeInstruction('mov', sR3L, smm);
end;
if buffer <> TranslatorType.KIND_LONG then begin
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SSLL:
g.writeInstruction('shl', sR3I, sR1B);
TranslatorTreeBuilder.ASSIGN_SSRA:
g.writeInstruction('sar', sR3I, sR1B);
TranslatorTreeBuilder.ASSIGN_SSRL:
g.writeInstruction('shr', sR3I, sR1B);
end;
end else begin
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SSLL:
g.writeInstruction('shl', sR3L, sR1B);
TranslatorTreeBuilder.ASSIGN_SSRA:
g.writeInstruction('sar', sR3L, sR1B);
TranslatorTreeBuilder.ASSIGN_SSRL:
g.writeInstruction('shr', sR3L, sR1B);
end;
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);
smmw := mem.memoryToString(MWORD, 0);
simm := g.immediateToStringByte(buffer);
buffer := child.dataType.kind;
case buffer of
TranslatorType.KIND_CHAR:
g.writeInstruction('movzx', sR3I, smmw);
TranslatorType.KIND_BYTE:
g.writeInstruction('movsx', sR3I, smmb);
TranslatorType.KIND_SHORT:
g.writeInstruction('movsx', sR3I, smmw);
TranslatorType.KIND_INT:
g.writeInstruction('mov', sR3I, smm);
TranslatorType.KIND_LONG:
g.writeInstruction('mov', sR3L, smm);
end;
if buffer <> TranslatorType.KIND_LONG then begin
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SSLL:
g.writeInstruction('shl', sR3I, simm);
TranslatorTreeBuilder.ASSIGN_SSRA:
g.writeInstruction('sar', sR3I, simm);
TranslatorTreeBuilder.ASSIGN_SSRL:
g.writeInstruction('shr', sR3I, simm);
end;
end else begin
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SSLL:
g.writeInstruction('shl', sR3L, simm);
TranslatorTreeBuilder.ASSIGN_SSRA:
g.writeInstruction('sar', sR3L, simm);
TranslatorTreeBuilder.ASSIGN_SSRL:
g.writeInstruction('shr', sR3L, simm);
end;
end;
end;
case buffer of
TranslatorType.KIND_BYTE:
g.writeInstruction('mov', smm, sR3B);
TranslatorType.KIND_SHORT, TranslatorType.KIND_CHAR:
g.writeInstruction('mov', smm, sR3S);
TranslatorType.KIND_INT:
g.writeInstruction('mov', smm, sR3I);
TranslatorType.KIND_LONG:
g.writeInstruction('mov', smm, sR3L);
end;
if nodeType <> nil then begin
if buffer <> TranslatorType.KIND_LONG then begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR3I);
end else begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR3L);
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.ASSIGN_QSLL,
TranslatorTreeBuilder.ASSIGN_QSRA,
TranslatorTreeBuilder.ASSIGN_QSRL: 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);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
buffer := child.dataType.kind;
g.writeInstruction('movd', sXMM13, sr2);
case buffer of
TranslatorType.KIND_LONG: begin
g.writeInstruction('movq', sXMM12, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_QSLL:
g.writeInstruction('psllw', sXMM12, sXMM13);
TranslatorTreeBuilder.ASSIGN_QSRA:
g.writeInstruction('psraw', sXMM12, sXMM13);
TranslatorTreeBuilder.ASSIGN_QSRL:
g.writeInstruction('psrlw', sXMM12, sXMM13);
end;
end;
TranslatorType.KIND_ULTRA: begin
g.writeInstruction('movdqu', sXMM12, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_QSLL:
g.writeInstruction('pslld', sXMM12, sXMM13);
TranslatorTreeBuilder.ASSIGN_QSRA:
g.writeInstruction('psrad', sXMM12, sXMM13);
TranslatorTreeBuilder.ASSIGN_QSRL:
g.writeInstruction('psrld', sXMM12, sXMM13);
end;
end;
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);
simm := g.immediateToStringByte(buffer);
buffer := child.dataType.kind;
case buffer of
TranslatorType.KIND_LONG: begin
g.writeInstruction('movq', sXMM12, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_QSLL:
g.writeInstruction('psllw', sXMM12, simm);
TranslatorTreeBuilder.ASSIGN_QSRA:
g.writeInstruction('psraw', sXMM12, simm);
TranslatorTreeBuilder.ASSIGN_QSRL:
g.writeInstruction('psrlw', sXMM12, simm);
end;
end;
TranslatorType.KIND_ULTRA: begin
g.writeInstruction('movdqu', sXMM12, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_QSLL:
g.writeInstruction('pslld', sXMM12, simm);
TranslatorTreeBuilder.ASSIGN_QSRA:
g.writeInstruction('psrad', sXMM12, simm);
TranslatorTreeBuilder.ASSIGN_QSRL:
g.writeInstruction('psrld', sXMM12, simm);
end;
end;
end;
end;
case buffer of
TranslatorType.KIND_LONG:
g.writeInstruction('movq', smm, sXMM12);
TranslatorType.KIND_ULTRA:
g.writeInstruction('movdqu', smm, sXMM12);
end;
if nodeType <> nil then begin
if buffer <> TranslatorType.KIND_LONG then begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movq', sr1, sXMM12);
end else begin
reg1 := stack.allocateXMM(XPINT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movdqu', sr1, sXMM12);
end;
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.ASSIGN_OSLL,
TranslatorTreeBuilder.ASSIGN_OSRA,
TranslatorTreeBuilder.ASSIGN_OSRL: 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);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
buffer := child.dataType.kind;
g.writeInstruction('movd', sXMM13, sr2);
g.writeInstruction('movdqu', sXMM12, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_OSLL:
g.writeInstruction('psllw', sXMM12, sXMM13);
TranslatorTreeBuilder.ASSIGN_OSRA:
g.writeInstruction('psraw', sXMM12, sXMM13);
TranslatorTreeBuilder.ASSIGN_OSRL:
g.writeInstruction('psrlw', sXMM12, sXMM13);
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);
simm := g.immediateToStringByte(buffer);
g.writeInstruction('movdqu', sXMM12, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_OSLL:
g.writeInstruction('psllw', sXMM12, simm);
TranslatorTreeBuilder.ASSIGN_OSRA:
g.writeInstruction('psraw', sXMM12, simm);
TranslatorTreeBuilder.ASSIGN_OSRL:
g.writeInstruction('psrlw', sXMM12, simm);
end;
end;
g.writeInstruction('movdqu', smm, sXMM12);
if nodeType <> nil then begin
reg1 := stack.allocateXMM(XPINT, g);
sr1 := g.registerToString(reg1);
g.writeInstruction('movdqu', sr1, sXMM12);
end;
stack.restoreRegs(g);
end;
TranslatorTreeBuilder.ASSIGN_QGT,
TranslatorTreeBuilder.ASSIGN_QGE,
TranslatorTreeBuilder.ASSIGN_QLT,
TranslatorTreeBuilder.ASSIGN_QLE,
TranslatorTreeBuilder.ASSIGN_QEQ,
TranslatorTreeBuilder.ASSIGN_QNE: begin
child := node.getChild(0) as SyntaxNode;
mem := getMemoryLocation(child, stack, true);
smm := mem.memoryToString(MNONE, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
case child.dataType.kind of
TranslatorType.KIND_LONG: begin
g.writeInstruction('movq', sXMM12, smm);
g.writeInstruction('movq', sXMM13, sr2);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_QGT: begin
g.writeInstruction('pcmpgtw', sXMM12, sXMM13);
g.writeInstruction('movq', sR3L, sXMM12);
end;
TranslatorTreeBuilder.ASSIGN_QGE: begin
g.writeInstruction('pcmpgtw', sXMM13, sXMM12);
g.writeInstruction('movq', sR3L, sXMM13);
g.writeInstruction('xor', sR3L, g.immediateToString(-1));
end;
TranslatorTreeBuilder.ASSIGN_QLT: begin
g.writeInstruction('pcmpgtw', sXMM13, sXMM12);
g.writeInstruction('movq', sR3L, sXMM13);
end;
TranslatorTreeBuilder.ASSIGN_QLE: begin
g.writeInstruction('pcmpgtw', sXMM12, sXMM13);
g.writeInstruction('movq', sR3L, sXMM12);
g.writeInstruction('xor', sR3L, g.immediateToString(-1));
end;
TranslatorTreeBuilder.ASSIGN_QEQ: begin
g.writeInstruction('pcmpeqw', sXMM12, sXMM13);
g.writeInstruction('movq', sR3L, sXMM12);
end;
TranslatorTreeBuilder.ASSIGN_QNE: begin
g.writeInstruction('pcmpeqw', sXMM12, sXMM13);
g.writeInstruction('movq', sR3L, sXMM12);
g.writeInstruction('xor', sR3L, g.immediateToString(-1));
end;
end;
g.writeInstruction('mov', smm, sR3L);
if nodeType <> nil then begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR3L);
end;
end;
TranslatorType.KIND_ULTRA: begin
g.writeInstruction('movdqu', sXMM12, smm);
case nodeValue of
TranslatorTreeBuilder.ASSIGN_QGT: begin
g.writeInstruction('pcmpgtd', sXMM12, sr2);
end;
TranslatorTreeBuilder.EXPR_QGE: begin
g.writeInstruction('pcmpgtd', sr2, sXMM12);
g.writeInstruction('movdqu', sXMM12, sr2);
g.writeInstruction('movdqu', sr2, g.memoryToString(MNONE, LABEL_POOL_ULTRA_CONTENT,
programmeXUltras.indexAcquire(ultraBuild(-1, -1)) * 16));
g.writeInstruction('pxor', sXMM12, sr2);
end;
TranslatorTreeBuilder.EXPR_QLT: begin
g.writeInstruction('pcmpgtd', sr2, sXMM12);
g.writeInstruction('movdqu', sXMM12, sr2);
end;
TranslatorTreeBuilder.EXPR_QLE: begin
g.writeInstruction('pcmpgtd', sXMM12, sr2);
g.writeInstruction('movdqu', sr2, g.memoryToString(MNONE, LABEL_POOL_ULTRA_CONTENT,
programmeXUltras.indexAcquire(ultraBuild(-1, -1)) * 16));
g.writeInstruction('pxor', sXMM12, sr2);
end;
TranslatorTreeBuilder.EXPR_QEQ: begin
g.writeInstruction('pcmpeqd', sXMM12, sr2);
end;
TranslatorTreeBuilder.EXPR_QNE: begin
g.writeInstruction('pcmpeqd', sXMM12, sr2);
g.writeInstruction('movdqu', sr2, g.memoryToString(MNONE, LABEL_POOL_ULTRA_CONTENT,
programmeXUltras.indexAcquire(ultraBuild(-1, -1)) * 16));
g.writeInstruction('pxor', sXMM12, sr2);
end;
end;
g.writeInstruction('movdqu', smm, sXMM12);
if nodeType <> nil then begin
stack.pushReg(reg2);
g.writeInstruction('movdqu', sr2, sXMM12);
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);
smmw := mem.memoryToString(MWORD, 0);
reg2 := mem.getRegisterSource();
sr2 := g.registerToString(reg2);
buffer := child.dataType.kind;
case buffer of
TranslatorType.KIND_BOOLEAN:
g.writeInstruction('movzx', sR3I, smmb);
TranslatorType.KIND_CHAR:
g.writeInstruction('movzx', sR3I, smmw);
TranslatorType.KIND_BYTE:
g.writeInstruction('movsx', sR3I, smmb);
TranslatorType.KIND_SHORT:
g.writeInstruction('movsx', sR3I, smmw);
TranslatorType.KIND_INT:
g.writeInstruction('mov', sR3I, smm);
TranslatorType.KIND_LONG:
g.writeInstruction('mov', sR3L, smm);
TranslatorType.KIND_ULTRA:
g.writeInstruction('movdqu', sXMM12, smm);
end;
case buffer of
TranslatorType.KIND_BOOLEAN,
TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
TranslatorType.KIND_SHORT, TranslatorType.KIND_INT:
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SANDB:
g.writeInstruction('and', sR3I, sr2);
TranslatorTreeBuilder.ASSIGN_SXORB:
g.writeInstruction('xor', sR3I, sr2);
TranslatorTreeBuilder.ASSIGN_SORB:
g.writeInstruction('or', sR3I, sr2);
end;
TranslatorType.KIND_LONG:
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SANDB:
g.writeInstruction('and', sR3L, sr2);
TranslatorTreeBuilder.ASSIGN_SXORB:
g.writeInstruction('xor', sR3L, sr2);
TranslatorTreeBuilder.ASSIGN_SORB:
g.writeInstruction('or', sR3L, sr2);
end;
TranslatorType.KIND_ULTRA:
case nodeValue of
TranslatorTreeBuilder.ASSIGN_SANDB:
g.writeInstruction('pand', sXMM12, sr2);
TranslatorTreeBuilder.ASSIGN_SXORB:
g.writeInstruction('pxor', sXMM12, sr2);
TranslatorTreeBuilder.ASSIGN_SORB:
g.writeInstruction('por', sXMM12, sr2);
end;
end;
case buffer of
TranslatorType.KIND_BYTE, TranslatorType.KIND_BOOLEAN:
g.writeInstruction('mov', smm, sR3B);
TranslatorType.KIND_SHORT, TranslatorType.KIND_CHAR:
g.writeInstruction('mov', smm, sR3S);
TranslatorType.KIND_INT:
g.writeInstruction('mov', smm, sR3I);
TranslatorType.KIND_LONG:
g.writeInstruction('mov', smm, sR3L);
TranslatorType.KIND_ULTRA:
g.writeInstruction('movdqu', smm, sXMM12);
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
case buffer of
TranslatorType.KIND_BOOLEAN,
TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
TranslatorType.KIND_SHORT, TranslatorType.KIND_INT: begin
reg1 := stack.allocateGPR32bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR3I);
end;
TranslatorType.KIND_LONG: begin
reg1 := stack.allocateGPR64bit(g);
sr1 := g.registerToString(reg1);
g.writeInstruction('mov', sr1, sR3L);
end;
TranslatorType.KIND_ULTRA: begin
stack.pushReg(reg2);
g.writeInstruction('movdqu', sr2, sXMM12);
end;
end;
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;
TranslatorTreeBuilder.TF_JUMP: begin
child := TranslatorTreeBuilder.getCommonParent(node, goAlwaysTo) as SyntaxNode;
current := node.parent as SyntaxNode;
repeat
if current.value = TranslatorTreeBuilder.OPERATOR_TRY_FINALLY then begin
gotoNode := (current.getChild(current.getChildrensCount() - 1) as SyntaxNode).
goAlwaysToNode as BuilderNode;
if gotoNode <> nil then begin
g.writeInstruction('call',
LABEL_LOCAL + intToString(gotoNode.assignedLabelNumber));
end;
end;
current := current.parent as SyntaxNode;
until (current = nil) or (current = child);
g.writeInstruction('jmp', LABEL_LOCAL + intToString(goAlwaysTo.assignedLabelNumber));
end;
end;
end;
procedure TranslatorBuilderOf64bitCode.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;
sr1d: String;
sR1L: String;
sR2L: String;
sR3L: 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 := R0 + (stack.getRegAt(0) and $0f);
sr1d := g.registerToString(R0D + (reg1 and $0f));
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).intValue(),
(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 }
sR1L := g.registerToString(R1);
sR2L := g.registerToString(R2);
sR3L := g.registerToString(R3);
g.writeInstruction('sub', sr1d, g.immediateToStringInt(caseS));
g.writeInstruction('jl', sdef);
g.writeInstruction('cmp', sr1d, g.immediateToStringInt(caseF - caseS));
g.writeInstruction('ja', sdef);
g.writeInstruction('lea', sR1L, g.memoryToString(MNONE, LABEL_FOLLOWING, 0));
g.writeInstruction('movsxd', sR2L, sr1d);
g.writeInstruction('movsxd', sR3L, g.memoryToString(MNONE, R1, R2, 4, 0));
g.writeInstruction('lea', sR3L, g.memoryToString(MNONE, R1, R3, 0));
g.writeInstruction('jmp', sR3L);
g.writeAlignLocal(4);
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] := g.labelRelativeAnotherToString(
LABEL_LOCAL + intToString(current.ints[1]), LABEL_PRECEDING, 0);
inc(i);
end else begin
slabels[k] := g.labelRelativeAnotherToString(sdef, LABEL_PRECEDING, 0);
end;
inc(k);
if k = 8 then begin
g.writeInstruction('dd', slabels);
k := 0;
end;
end;
if k > 0 then begin
setLabelsLength(k);
g.writeInstruction('dd', 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', sr1d, g.immediateToStringInt(delta));
g.writeInstruction('jz', LABEL_LOCAL + intToString(current.ints[1]));
end;
g.writeInstruction('jmp', sdef);
end;
end;
procedure TranslatorBuilderOf64bitCode.translateExceptionHandler(root: SyntaxNode;
argums, locals: int);
var
intr: boolean;
i: int;
j: int;
esize: int;
limit: int;
node: SyntaxNode;
last: SyntaxNode;
ftyp: TypeFunction;
func: GlobalFunction;
enum: NodeEnumerator;
exhn: Vector;
g: TextGenerator;
sR0I: String;
sR1L: String;
sR2L: String;
sR3L: String;
sRSP: String;
sR15L: String;
begin
g := self.generator;
sR0I := g.registerToString(R0D);
sR1L := g.registerToString(R1);
sR2L := g.registerToString(R2);
sR3L := g.registerToString(R3);
sRSP := g.registerToString(RSP);
sR15L := g.registerToString(R15);
func := root.associate as GlobalFunction;
enum := root.enumerateChildrens();
exhn := Vector.create();
try
intr := func.isInterrupt();
g.writeLabelShort(LABEL_EXCEPTION_HANDLER);
if intr = false then begin
g.writeInstruction('emms');
end;
node := root;
repeat
case node.value of
TranslatorTreeBuilder.OPERATOR_TRY_CATCH,
TranslatorTreeBuilder.OPERATOR_TRY_FINALLY: begin
exhn.addElement(node);
end;
end;
node := enum.nextChild() as SyntaxNode;
until node = nil;
esize := exhn.size();
if esize > 0 then begin
g.writeInstruction('lea', sRSP, g.memoryToString(MNONE, RBP, -locals));
end;
for i := esize downto 1 do begin
if i < esize then begin
g.writeLabelShort(LABEL_ANONYMOUS);
end;
node := exhn.elementAt(i - 1) as SyntaxNode;
g.writeInstruction('lea', sR3L, g.memoryToString(MNONE, LABEL_LOCAL + intToString(
(node.goIfTrueToNode as BuilderNode).assignedLabelNumber), 0));
g.writeInstruction('cmp', sR2L, sR3L);
g.writeInstruction('jl', LABEL_FOLLOWING);
g.writeInstruction('lea', sR3L, g.memoryToString(MNONE, LABEL_LOCAL + intToString(
(node.goIfFalseToNode as BuilderNode).assignedLabelNumber), 0));
g.writeInstruction('cmp', sR2L, sR3L);
g.writeInstruction('jge', LABEL_FOLLOWING);
case node.value of
TranslatorTreeBuilder.OPERATOR_TRY_CATCH: begin
limit := node.getChildrensCount() - 1;
for j := 0 to limit do begin
last := node.getChild(j) as SyntaxNode;
if last.value <> TranslatorTreeBuilder.BLOCK_CATCH then begin
continue;
end;
g.writeInstruction('lea', sR3L, g.memoryToString(MNONE,
getEntryFullName(last.associate as NamespaceEntry), 0));
g.writeInstruction('call', FUNCTION_EXCEPTION_INHERITED_FROM);
g.writeInstruction('test', sR0I, sR0I);
g.writeInstruction('jnz', LABEL_LOCAL + intToString(
(last.goAlwaysToNode as BuilderNode).assignedLabelNumber));
end;
end;
TranslatorTreeBuilder.OPERATOR_TRY_FINALLY: begin
last := node.getChild(node.getChildrensCount() - 1) as SyntaxNode;
g.writeInstruction('push', sR1L);
g.writeInstruction('push', sR2L);
g.writeInstruction('call', LABEL_LOCAL + intToString(
(last.goAlwaysToNode as BuilderNode).assignedLabelNumber));
g.writeInstruction('pop', sR2L);
g.writeInstruction('pop', sR1L);
end;
end;
end;
if esize > 0 then begin
g.writeLabelShort(LABEL_ANONYMOUS);
end;
if intr then begin
g.writeInstruction('leave');
g.writeInstruction('pop', g.registerToString(R15));
g.writeInstruction('pop', g.registerToString(R14));
g.writeInstruction('pop', g.registerToString(R13));
g.writeInstruction('pop', g.registerToString(R12));
g.writeInstruction('pop', g.registerToString(R11));
g.writeInstruction('pop', g.registerToString(R10));
g.writeInstruction('pop', g.registerToString(R9));
g.writeInstruction('pop', g.registerToString(R8));
g.writeInstruction('pop', g.registerToString(R7));
g.writeInstruction('pop', g.registerToString(R6));
g.writeInstruction('pop', g.registerToString(R3));
g.writeInstruction('pop', g.registerToString(R2));
g.writeInstruction('pop', g.registerToString(R1));
g.writeInstruction('pop', g.registerToString(R0));
ftyp := func.functionType;
if (ftyp.getArgumentsCount() > 5) and
stringStartsWith(UnicodeString('error'), ftyp.getArgument(5).name) then begin
g.writeInstruction('lea', g.registerToString(RSP),
g.memoryToString(MNONE, RSP, $10));
end else begin
g.writeInstruction('lea', g.registerToString(RSP),
g.memoryToString(MNONE, RSP, $08));
end;
g.writeInstruction('iretq');
end else begin
g.writeInstruction('leave');
g.writeInstruction('pop', sR15L);
if length(func.owner.name) > 0 then begin
g.writeInstruction('pop', sR2L);
g.writeInstruction('dec', sR2L);
g.writeInstruction('jmp', sR15L);
end else begin
case g.exitMethod of
TextGenerator.EXIT_RETF: begin
if argums > 0 then begin
g.writeInstruction('retf', g.immediateToString(argums));
end else begin
g.writeInstruction('retf');
end;
end;
TextGenerator.EXIT_CALL: begin
g.writeInstruction('push', sR1L);
g.writeInstruction('call', FUNCTION_EXIT);
end;
else
if argums > 0 then begin
g.writeInstruction('ret', g.immediateToString(argums));
end else begin
g.writeInstruction('ret');
end;
end;
end;
end;
finally
exhn.free();
end;
end;
procedure TranslatorBuilderOf64bitCode.writePools();
var
i: int;
j: int;
k: int;
l: int;
len: int;
limit: int;
exponent: int;
significand: long;
longValue: long;
ultraValue: ultra;
floatValue: float;
doubleValue: double;
realValue: real;
xvectorValue: xvector;
funcValue: GlobalFunction;
poolOfLong: PoolLong;
poolOfUltra: PoolUltra;
poolOfReal: PoolReal;
poolOfXVector: PoolXVector;
poolOfString: PoolString;
poolOfFunctions: Vector;
representer: RealValueRepresenter;
g: TextGenerator;
schars: String_Array1d;
stringValue: UnicodeString;
funcOwner: UnicodeString;
shex: String;
sdec: String;
begin
g := self.generator;
{%region открытые функции, имеющиеся в программе}
poolOfFunctions := programmeFunctions;
poolOfString := programmeStrings;
limit := poolOfFunctions.size() - 1;
g.writeEmptyLine();
g.writeCommentToLineEnd('pool of functions');
g.writeAlignGlobal(4);
g.writeLabelLong(LABEL_POOL_FUNCS_LENGTH);
g.writeInstruction('dd', g.immediateToStringInt(limit + 1));
g.writeLabelLong(LABEL_POOL_FUNCS_CONTENT);
for i := 0 to limit do begin
funcValue := poolOfFunctions.elementAt(i) as GlobalFunction;
stringValue := funcValue.name;
funcOwner := funcValue.owner.name;
if length(funcOwner) > 0 then begin
stringValue := funcOwner + '.' + stringValue;
end;
g.writeInstruction('dd', g.immediateToStringInt(poolOfString.indexAcquire(stringValue)),
g.labelRelativeToString(getEntryFullName(funcValue), 4));
end;
g.writeEmptyLine();
{%endregion}
{%region числа типа long, используемые программой }
poolOfLong := programmeLongs;
limit := poolOfLong.getLength() - 1;
g.writeEmptyLine();
g.writeCommentToLineEnd('pool of long');
g.writeAlignGlobal(8);
g.writeLabelLong(LABEL_POOL_LONG_LENGTH);
g.writeInstruction('dq', g.immediateToStringInt(limit + 1), g.immediateToStringLong(0));
g.writeLabelLong(LABEL_POOL_LONG_CONTENT);
for i := 0 to limit do begin
longValue := poolOfLong.getValue(i);
shex := g.immediateToStringLong(longValue);
sdec := longToString(longValue);
g.writeInstruction('dq', shex);
g.writeCommentToLineEnd(sdec);
end;
g.writeEmptyLine();
{%endregion}
{%region векторы типа ultra, используемые программой }
poolOfUltra := programmeXUltras;
limit := poolOfUltra.getLength() - 1;
g.writeEmptyLine();
g.writeCommentToLineEnd('pool of ultra');
g.writeLabelLong(LABEL_POOL_ULTRA_LENGTH);
g.writeInstruction('dq', g.immediateToStringInt(limit + 1), g.immediateToStringLong(0));
g.writeLabelLong(LABEL_POOL_ULTRA_CONTENT);
for i := 0 to limit do begin
ultraValue := poolOfUltra.getValue(i);
g.writeInstruction('dd',
g.immediateToStringInt(ultraValue.ints[0]),
g.immediateToStringInt(ultraValue.ints[1]),
g.immediateToStringInt(ultraValue.ints[2]),
g.immediateToStringInt(ultraValue.ints[3]));
g.writeCommentToLineEnd('new ultra { ' +
intToString(ultraValue.ints[0]) + ', ' +
intToString(ultraValue.ints[1]) + ', ' +
intToString(ultraValue.ints[2]) + ', ' +
intToString(ultraValue.ints[3]) + ' }');
end;
g.writeEmptyLine();
{%endregion}
{%region числа типа float, используемые программой }
poolOfReal := programmeFloats;
limit := poolOfReal.getLength() - 1;
g.writeEmptyLine();
g.writeCommentToLineEnd('pool of float');
g.writeLabelLong(LABEL_POOL_FLOAT_LENGTH);
g.writeInstruction('dq', g.immediateToStringInt(limit + 1), g.immediateToStringLong(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.writeAlignGlobal(8);
g.writeLabelLong(LABEL_POOL_DOUBLE_LENGTH);
g.writeInstruction('dq', g.immediateToStringInt(limit + 1), g.immediateToStringLong(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('dq', g.immediateToStringInt(limit + 1), g.immediateToStringLong(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 векторы типа xvector, используемые программой }
poolOfXVector := programmeXVectors;
limit := poolOfXVector.getLength() - 1;
g.writeEmptyLine();
g.writeCommentToLineEnd('pool of xvector');
g.writeAlignGlobal(8);
g.writeLabelLong(LABEL_POOL_XVECTOR_LENGTH);
g.writeInstruction('dq', g.immediateToStringInt(limit + 1), g.immediateToStringLong(0));
g.writeLabelLong(LABEL_POOL_XVECTOR_CONTENT);
representer := RealValueRepresenter.create(RealValueRepresenter.FLOAT_SIGNIFICAND_DIGITS,
RealValueRepresenter.FLOAT_ORDER_DIGITS);
try
for i := 0 to limit do begin
xvectorValue := poolOfXVector.getValue(i);
g.writeInstruction('dd',
g.immediateToStringInt(floatToIntBits(xvectorValue.floats[0])),
g.immediateToStringInt(floatToIntBits(xvectorValue.floats[1])),
g.immediateToStringInt(floatToIntBits(xvectorValue.floats[2])),
g.immediateToStringInt(floatToIntBits(xvectorValue.floats[3])));
g.writeCommentToLineEnd('new xvector { ' +
representer.toString(xvectorValue.floats[0]) + ', ' +
representer.toString(xvectorValue.floats[1]) + ', ' +
representer.toString(xvectorValue.floats[2]) + ', ' +
representer.toString(xvectorValue.floats[3]) + ' }');
end;
finally
representer.free();
end;
g.writeEmptyLine();
{%endregion}
{%region строки типа char[], используемые программой }
limit := poolOfString.getLength() - 1;
g.writeEmptyLine();
g.writeCommentToLineEnd('pool of string');
g.writeLabelLong(LABEL_POOL_STRING_LENGTH);
g.writeInstruction('dd', g.immediateToStringInt(limit + 1), g.immediateToStringInt(0));
g.writeLabelLong(LABEL_POOL_STRING_CONTENT);
for i := 0 to limit do begin
g.writeInstruction('dq', g.immediateToStringInt(length(poolOfString.getValue(i))),
g.labelRelativeToString(LABEL_POOL_STRING_ENTRY + intToString(i), -8))
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 TranslatorBuilderOf64bitCode.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), RBP, offset);
delta := dataType.getAlignedSize(TranslatorType.SIZE_64_BIT);
inc(offset, delta);
inc(result, delta);
end;
end;
function TranslatorBuilderOf64bitCode.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_64_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), RBP, offset);
end;
finally
locals.free();
end;
end;
function TranslatorBuilderOf64bitCode.getMemoryLocation(node: SyntaxNode; stack: RegisterStack;
hasValueForWrite: boolean): MemoryLocation;
var
regPtr: int;
regIdx: int;
regSrc: int;
scale: 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('mov', g.registerToString(R1), g.registerToString(regPtr));
g.writeInstruction('mov', g.registerToString(R2D), g.registerToString(regIdx));
g.writeInstruction('call', FUNCTION_CHECK_ARRAY_INDEX);
regIdx := R0 + (regIdx and $0f);
srIdx := g.registerToString(regIdx);
size := node.dataType.size;
case size of
1, 2, 4, 8: begin
scale := size;
g.writeInstruction('lea', srIdx, g.memoryToString(MNONE, '', R2, 1, 0));
end;
16: begin
scale := 8;
g.writeInstruction('lea', srIdx, g.memoryToString(MNONE, '', R2, 2, 0));
end;
32: begin
scale := 8;
g.writeInstruction('lea', srIdx, g.memoryToString(MNONE, '', R2, 4, 0));
end;
64: begin
scale := 8;
g.writeInstruction('lea', srIdx, g.memoryToString(MNONE, '', R2, 8, 0));
end;
else
scale := 1;
g.writeInstruction('imul', srIdx, g.registerToString(R2), g.immediateToString(size));
end;
result := MemoryLocationTfasm.create(g, regSrc, R1, regIdx, scale, '');
end;
else
result := nil;
end;
end;
end.