TakePrevAsm; {Берем предыдущую команду и значение из eax}
{ Запоминаем имена первого и второго операндов }
sReg1:= GetOpName(i,listTriad,1);
sReg2:= GetOpName(i,listTriad,2);
{ Если имя первого операнда пустое, значит, он уже
есть в регистре eax от выполнения предыдущей триады -
вызываем функцию генерации кода для второго операнда }
if (sReg1 = ) or (sReg1 = sVal) then
listCode.Add(MakeOpCode(i,listTriad,sOp,sReg2,
sPrev,sVal,flagOpt))
else { Если имя второго операнда пустое, значит он уже
есть в регистре eax от выполнения предыдущей триады -
вызываем функцию генерации кода для первого операнда }
if (sReg2 = ) or (sReg2 = sVal) then
begin
listCode.Add(MakeOpCode(i,listTriad,sOp,sReg1,
sPrev,sVal,flagOpt));
{ Если есть дополнительная операция, генерируем ее код
(когда операция несимметричная – например "-") }
if sAddOp <> then
listCode.Add(Format(#9 %s'#9'eax',[sAddOp]));
end
else { Если оба операнда не пустые, то надо:
– сначала загрузить в eax первый операнд;
– сгенерировать код для обработки второго операнда.}
begin
sReg1:= MakeMove(sReg1,sPrev,sVal,flagOpt);
if sReg1 <> then listCode.Add(sReg1);
listCode.Add(MakeOpCode(i,listTriad,sOp,sReg2,
sPrev,sVal,flagOpt));
end;
if listTriad[i].Info <> 0 then { Если триада связана с
begin { регистром, запоминаем результат в этом регистре }
sReg1:= GetRegName(listTriad[i].Info);
{ При этом запоминаем, что сейчас находится в eax }
listCode.AddObject(Format(#9'mov'#9 %s,eax',[sReg1]),
TObject(PChar(sReg1)));
end;
end;
procedure MakeCompare(const sOp: string
{флаг операции сравнения});
{ Функция генерации кода для операций сравнения }
var sReg1,sReg2{строки для имен регистров}: string;
begin
TakePrevAsm; {Берем предыдущую команду и значение из eax}
{ Запоминаем имена первого и второго операндов }
sReg1:= GetOpName(i,listTriad,1);
sReg2:= GetOpName(i,listTriad,2);
{ Если имя первого операнда пустое, значит он уже
есть в регистре eax от выполнения предыдущей триады -
сравниваем eax со вторым операндом }
if sReg1 = then
listCode.Add(Format(#9'cmp'#9'eax,%s'#9 { %s },
[sReg2,listTriad[i].MakeString(i)]))
else { Если имя второго операнда пустое, значит он уже
есть в регистре eax от выполнения предыдущей триады -
сравниваем eax с первым операндом в обратном порядке }
if sReg2 = then
listCode.Add(Format(#9'cmp'#9 %s,eax'#9 { %s },
[sReg1,listTriad[i].MakeString(i)]))
else { Если оба операнда не пустые, то надо:
– сначала загрузить в eax первый операнд;
– сравнить eax со вторым операндом. }
begin
sReg1:= MakeMove(sReg1,sPrev,sVal,flagOpt);
if sReg1 <> then listCode.Add(sReg1);
listCode.Add(Format(#9'cmp'#9'eax,%s'#9 { %s },
[sReg2,listTriad[i].MakeString(i)]));
end; { Загружаем в младший бит eax 1 или 0
в зависимости от флага сравнения }
listCode.Add(Format(#9'set%s'#9'al',[sOp]));
listCode.Add(#9'and'#9'eax,1); {очищаем остальные биты}
if listTriad[i].Info <> 0 then { Если триада связана с
begin { регистром, запоминаем результат в этом регистре }
sReg1:= GetRegName(listTriad[i].Info);
{ При этом запоминаем, что сейчас находится в eax }
listCode.AddObject(Format(#9'mov'#9 %s,eax',[sReg1]),
TObject(PChar(sReg1)));
end;
end;
begin { Тело главной функции }
iCnt:= listTriad.Count-1; { Количество триад в списке }
for i:=0 to iCnt do
begin { Цикл по всем триадам от начала списка }
{ Если триада помечена, создаем локальную метку
в списке команд ассемблера }
if listTriad[i].IsLinked then
listCode.Add(Format(@M%d:,[i+1]));
{ Генерация кода в зависимости от типа триады }
case listTriad[i].TrdType of
{ Код для триады IF }
TRD_IF: { Если операнд – константа, }
begin {(это возможно в результате оптимизации)}
if listTriad[i][1].OpType = OP_CONST then
begin { Условный переход превращается
в безусловный, если константа = 0,}
if listTriad[i][1].ConstVal = 0 then
listCode.Add(Format(#9'jmp'#9 @M%d'#9 { %s },
[listTriad[i][2].TriadNum+1,
listTriad[i].MakeString(i)]));
end { а иначе вообще генерировать код не нужно.}
else { Если операнд – не константа }
begin { Берем имя первого операнда }
sR:= GetOpName(i,listTriad,1);
{ Если имя первого операнда пустое,
значит он уже есть в регистре eax
от выполнения предыдущей триады, }
if sR = then
{ тогда надо выставить флаг «Z», сравнив eax
с ним самим, но учитывая, что предыдущая
триада для IF – это либо сравнение, либо
логическая операция, это можно опустить}
else { иначе надо сравнить eax с операндом }
listCode.Add(Format(#9'cmp'#9 %s,0,[sR]));
{Переход по условию «NOT Z» на ближайшую метку}
listCode.Add(Format(#9'jnz'#9 @F%d'#9 { %s },
[i,listTriad[i].MakeString(i)]));
{ Переход по прямому условию на дальнюю метку }
listCode.Add(Format(#9'jmp'#9 @M%d',
[listTriad[i][2].TriadNum+1]));
{ Метка для ближнего перехода }
listCode.Add(Format(@F%d:,[i]));
end;
end;
{ Код для бинарных логических операций }
TRD_OR: MakeOper2('or', );
TRD_XOR: MakeOper2('xor', );
TRD_AND: MakeOper2('and', );
{ Код для операции NOT (так как NOT(0)=FFFFFFFF,
то нужна еще операция: AND eax,1 }
TRD_NOT: MakeOper1('not','and',1);
{ Код для операций сравнения по их флагам }
TRD_LT: MakeCompare('l');
TRD_GT: MakeCompare('g');
TRD_EQ: MakeCompare('e');
TRD_NEQ: MakeCompare('ne');