Generate more efficient code for indirect function calls.

This commit is contained in:
Stephen Heumann 2022-10-11 21:14:40 -05:00
parent 4fe9c90942
commit ca21e33ba7
3 changed files with 56 additions and 32 deletions

View File

@ -37,8 +37,8 @@ const
{65816 native code generation}
{----------------------------}
{instruction modifier flags}
shift8 = 1; {shift operand left 8 bits}
shift16 = 2; {shift operand left 16 bits}
shift8 = 1; {shift operand right 8 bits}
shift16 = 2; {shift operand right 16 bits}
toolCall = 4; {generate a tool call}
stringReference = 8; {generate a string reference}
isPrivate = 32; {is the label private?}
@ -46,6 +46,7 @@ const
localLab = 128; {the operand is a local lab}
forFlags = 256; {instruction used for effect on flags only}
subtract1 = 512; {subtract 1 from address operand}
shiftLeft8 = 1024; {shift operand left 8 bits}
m_adc_abs = $6D; {op code #s for 65816 instructions}
m_adc_dir = $65;

59
Gen.pas
View File

@ -5502,41 +5502,42 @@ procedure GenTree {op: icptr};
GenTree(op^.left);
{get the address to call}
gLong.preference := onStack;
gLong.preference := A_X;
GenTree(op^.right);
gLong := lLong;
gQuad := lQuad;
{For functions returning cg(U)Quad, x = address to store result in}
if op^.optype in [cgQuad,cgUQuad] then
if gQuad.preference = localAddress then begin
GenImplied(m_tdc);
GenImplied(m_clc);
GenNative(m_adc_imm, immediate, gQuad.disp, nil, 0);
GenImplied(m_tax);
end {if}
else begin
GenImplied(m_tsc);
GenImplied(m_clc);
GenNative(m_adc_imm, immediate, argsSize+extraStackSize+4+1, nil, 0);
GenImplied(m_tax);
end; {else}
{create a return label}
lab1 := GenLabel;
{place the call/return addrs on stack}
GenNative(m_lda_s, direct, 1, nil, 0);
GenImplied(m_dea);
if gLong.where = A_X then begin
GenImplied(m_tay);
GenImplied(m_txa);
end {if}
else {if gLong.where = onStack then} begin
GenImplied(m_ply);
GenImplied(m_pla);
end; {else}
GenNative(m_and_imm, immediate, $00ff, nil, 0);
GenNative(m_ora_imm, genAddress, lab1, nil, subtract1+shiftLeft8);
GenNative(m_pea, genAddress, lab1, nil, subtract1+shift8);
GenImplied(m_pha);
GenNative(m_sep, immediate, 32, nil, 0);
GenNative(m_lda_s, direct, 5, nil, 0);
GenNative(m_sta_s, direct, 3, nil, 0);
GenNative(m_lda_imm, genAddress, lab1, nil, shift16);
GenNative(m_sta_s, direct, 6, nil, 0);
GenNative(m_rep, immediate, 32, nil, 0);
GenNative(m_lda_imm, genAddress, lab1, nil, subtract1);
GenNative(m_sta_s, direct, 4, nil, 0);
GenImplied(m_dey);
GenImplied(m_phy);
{For functions returning cg(U)Quad, x = address to store result in}
if op^.optype in [cgQuad,cgUQuad] then
if lQuad.preference = localAddress then begin
GenImplied(m_tdc);
GenImplied(m_clc);
GenNative(m_adc_imm, immediate, lQuad.disp, nil, 0);
GenImplied(m_tax);
end {if}
else begin
GenImplied(m_tsc);
GenImplied(m_clc);
GenNative(m_adc_imm, immediate, argsSize+extraStackSize+6+1, nil, 0);
GenImplied(m_tax);
end; {else}
{indirect call}
GenImplied(m_rtl);
@ -5569,6 +5570,8 @@ procedure GenTree {op: icptr};
end; {else}
{save the returned value}
gLong := lLong;
gQuad := lQuad;
gLong.where := A_X;
if gQuad.preference = localAddress then
gQuad.where := localAddress

View File

@ -293,7 +293,7 @@ else begin
end; {if}
if shift <> 0 then begin
Out(129); {shift the address}
Out2(-shift); Out2(-1);
Out2(-shift); if (shift > 0) then Out2(-1) else Out2(0);
Out(7);
end; {if}
if lab <> maxlabel then {if not a string, end the expression}
@ -458,6 +458,26 @@ var
end; {DefGlobal}
function ShiftSize (flags: integer): integer;
{ Determine the shift size specified by flags. }
{ (Positive means right shift, negative means left shift.) }
{ }
{ parameters: }
{ flags - the flags }
begin {ShiftSize}
if (flags & shift8) <> 0 then
ShiftSize := 8
else if (flags & shift16) <> 0 then
ShiftSize := 16
else if (flags & shiftLeft8) <> 0 then
ShiftSize := -8
else
ShiftSize := 0;
end; {ShiftSize}
begin {WriteNative}
{ writeln('WriteNative: ',opcode:4, ', mode=', ord(mode):1,
' operand=', operand:1); {debug}
@ -732,7 +752,7 @@ case mode of
else
LabelSearch(operand, 1, 16, 0)
else if (flags & subtract1) <> 0 then
LabelSearch(operand, 0, 0, 0)
LabelSearch(operand, 0, ShiftSize(flags), 0)
else
LabelSearch(operand, 2, 0, 0);
end;