mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-08 03:48:07 +02:00
* m68k: completely replaced 64-bit comparison code with a clone of i386 implementation. No optimizations yet, but it already makes system unit about 300 instructions shorter due to changing node location to LOC_JUMP.
* Cleaned up 32-bit comparison code and implemented one of the optimizations (TST instruction for comparison with constant zero which can act directly on references). This makes system unit shorter by about 1000 instructions. git-svn-id: trunk@28260 -
This commit is contained in:
parent
86726a5dc8
commit
bd5ce35130
@ -32,23 +32,13 @@ interface
|
||||
type
|
||||
t68kaddnode = class(tcgaddnode)
|
||||
private
|
||||
function cmp64_lt(left_reg,right_reg:tregister64):tregister;
|
||||
function cmp64_le(left_reg,right_reg:tregister64):tregister;
|
||||
function cmp64_eq(left_reg,right_reg:tregister64):tregister;
|
||||
function cmp64_ne(left_reg,right_reg:tregister64):tregister;
|
||||
function cmp64_ltu(left_reg,right_reg:tregister64):tregister;
|
||||
function cmp64_leu(left_reg,right_reg:tregister64):tregister;
|
||||
|
||||
function getresflags(unsigned: boolean) : tresflags;
|
||||
function getres64_register(unsigned:boolean;left_reg,right_reg:tregister64):tregister;
|
||||
protected
|
||||
procedure second_addfloat;override;
|
||||
procedure second_cmpfloat;override;
|
||||
procedure second_cmpordinal;override;
|
||||
procedure second_cmpsmallset;override;
|
||||
procedure second_cmp64bit;override;
|
||||
public
|
||||
function pass_1:tnode;override;
|
||||
end;
|
||||
|
||||
|
||||
@ -62,198 +52,12 @@ implementation
|
||||
cpuinfo,pass_1,pass_2,regvars,
|
||||
cpupara,cgutils,procinfo,
|
||||
ncon,nset,
|
||||
ncgutil,tgobj,rgobj,rgcpu,cgobj,hlcgobj,cg64f32;
|
||||
ncgutil,tgobj,rgobj,rgcpu,cgobj,cgcpu,hlcgobj,cg64f32;
|
||||
|
||||
{*****************************************************************************
|
||||
Helpers
|
||||
*****************************************************************************}
|
||||
|
||||
function t68kaddnode.cmp64_lt(left_reg,right_reg:tregister64):tregister;
|
||||
var
|
||||
labelcmp64_1,labelcmp64_2 : tasmlabel;
|
||||
tmpreg : tregister;
|
||||
begin
|
||||
tmpreg:=cg.getintregister(current_asmdata.currasmlist,OS_INT);
|
||||
|
||||
{ load the value for "false" }
|
||||
cg.a_load_const_reg(current_asmdata.currasmlist,OS_INT,0,tmpreg);
|
||||
|
||||
current_asmdata.getjumplabel(labelcmp64_1);
|
||||
current_asmdata.getjumplabel(labelcmp64_2);
|
||||
|
||||
{ check whether left_reg.reghi is less than right_reg.reghi }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,right_reg.reghi,left_reg.reghi));
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_LT,S_NO,labelcmp64_2));
|
||||
|
||||
{ are left_reg.reghi and right_reg.reghi equal? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_NE,S_NO,labelcmp64_1));
|
||||
|
||||
{ is left_reg.reglo less than right_reg.reglo? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,right_reg.reglo,left_reg.reglo));
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_CS,S_NO,labelcmp64_2));
|
||||
|
||||
current_asmdata.currasmlist.concat(Taicpu.op_sym(A_BRA,S_NO,labelcmp64_1));
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64_2);
|
||||
|
||||
{ load the value for "true" }
|
||||
cg.a_load_const_reg(current_asmdata.currasmlist,OS_INT,1,tmpreg);
|
||||
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64_1);
|
||||
result:=tmpreg;
|
||||
end;
|
||||
|
||||
function t68kaddnode.cmp64_le(left_reg,right_reg:tregister64):tregister;
|
||||
var
|
||||
labelcmp64_1,labelcmp64_2 : tasmlabel;
|
||||
tmpreg : tregister;
|
||||
begin
|
||||
tmpreg:=cg.getintregister(current_asmdata.currasmlist,OS_INT);
|
||||
|
||||
{ load the value for "false" }
|
||||
cg.a_load_const_reg(current_asmdata.currasmlist,OS_INT,0,tmpreg);
|
||||
|
||||
current_asmdata.getjumplabel(labelcmp64_1);
|
||||
current_asmdata.getjumplabel(labelcmp64_2);
|
||||
|
||||
{ check whether right_reg.reghi is less than left_reg.reghi }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,left_reg.reghi,right_reg.reghi));
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_LT,S_NO,labelcmp64_1));
|
||||
|
||||
{ are left_reg.reghi and right_reg.reghi equal? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_NE,S_NO,labelcmp64_2));
|
||||
|
||||
{ is right_reg.reglo less than left_reg.reglo? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,left_reg.reglo,right_reg.reglo));
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_CS,S_NO,labelcmp64_1));
|
||||
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64_2);
|
||||
|
||||
{ load the value for "true" }
|
||||
cg.a_load_const_reg(current_asmdata.currasmlist,OS_INT,1,tmpreg);
|
||||
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64_1);
|
||||
result:=tmpreg;
|
||||
end;
|
||||
|
||||
function t68kaddnode.cmp64_eq(left_reg,right_reg:tregister64):tregister;
|
||||
var
|
||||
labelcmp64 : tasmlabel;
|
||||
tmpreg : tregister;
|
||||
begin
|
||||
tmpreg:=cg.getintregister(current_asmdata.currasmlist,OS_INT);
|
||||
current_asmdata.getjumplabel(labelcmp64);
|
||||
|
||||
{ load the value for "false" }
|
||||
cg.a_load_const_reg(current_asmdata.currasmlist,OS_INT,0,tmpreg);
|
||||
|
||||
{ is the high order longword equal? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,left_reg.reghi,right_reg.reghi));
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_NE,S_NO,labelcmp64));
|
||||
|
||||
{ is the low order longword equal? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,left_reg.reglo,right_reg.reglo));
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_NE,S_NO,labelcmp64));
|
||||
|
||||
{ load the value for "true" }
|
||||
cg.a_load_const_reg(current_asmdata.currasmlist,OS_INT,1,tmpreg);
|
||||
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64);
|
||||
result:=tmpreg;
|
||||
end;
|
||||
|
||||
function t68kaddnode.cmp64_ne(left_reg,right_reg:tregister64):tregister;
|
||||
var
|
||||
labelcmp64 : tasmlabel;
|
||||
tmpreg : tregister;
|
||||
begin
|
||||
tmpreg:=cg.getintregister(current_asmdata.currasmlist,OS_INT);
|
||||
current_asmdata.getjumplabel(labelcmp64);
|
||||
|
||||
{ load the value for "true" }
|
||||
cg.a_load_const_reg(current_asmdata.currasmlist,OS_INT,1,tmpreg);
|
||||
|
||||
{ is the high order longword equal? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,left_reg.reghi,right_reg.reghi));
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_NE,S_NO,labelcmp64));
|
||||
|
||||
{ is the low order longword equal? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,left_reg.reglo,right_reg.reglo));
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_NE,S_NO,labelcmp64));
|
||||
|
||||
{ load the value for "false" }
|
||||
cg.a_load_const_reg(current_asmdata.currasmlist,OS_INT,0,tmpreg);
|
||||
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64);
|
||||
result:=tmpreg;
|
||||
end;
|
||||
|
||||
function t68kaddnode.cmp64_ltu(left_reg,right_reg:tregister64):tregister;
|
||||
var
|
||||
labelcmp64_1,labelcmp64_2 : tasmlabel;
|
||||
tmpreg : tregister;
|
||||
begin
|
||||
tmpreg:=cg.getintregister(current_asmdata.currasmlist,OS_INT);
|
||||
|
||||
{ load the value for "false" }
|
||||
cg.a_load_const_reg(current_asmdata.currasmlist,OS_INT,0,tmpreg);
|
||||
|
||||
current_asmdata.getjumplabel(labelcmp64_1);
|
||||
current_asmdata.getjumplabel(labelcmp64_2);
|
||||
|
||||
{ check whether left_reg.reghi is less than right_reg.reghi }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,right_reg.reghi,left_reg.reghi));
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_CS,S_NO,labelcmp64_2));
|
||||
|
||||
{ are left_reg.reghi and right_reg.reghi equal? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_NE,S_NO,labelcmp64_1));
|
||||
|
||||
{ is left_reg.reglo less than right_reg.reglo? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,right_reg.reglo,left_reg.reglo));
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_CS,S_NO,labelcmp64_2));
|
||||
|
||||
current_asmdata.currasmlist.concat(Taicpu.op_sym(A_BRA,S_NO,labelcmp64_1));
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64_2);
|
||||
|
||||
{ load the value for "true" }
|
||||
cg.a_load_const_reg(current_asmdata.currasmlist,OS_INT,1,tmpreg);
|
||||
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64_1);
|
||||
result:=tmpreg;
|
||||
end;
|
||||
|
||||
function t68kaddnode.cmp64_leu(left_reg,right_reg:tregister64):tregister;
|
||||
var
|
||||
labelcmp64_1,labelcmp64_2 : tasmlabel;
|
||||
tmpreg : tregister;
|
||||
begin
|
||||
tmpreg:=cg.getintregister(current_asmdata.currasmlist,OS_INT);
|
||||
|
||||
{ load the value for "false" }
|
||||
cg.a_load_const_reg(current_asmdata.currasmlist,OS_INT,0,tmpreg);
|
||||
|
||||
current_asmdata.getjumplabel(labelcmp64_1);
|
||||
current_asmdata.getjumplabel(labelcmp64_2);
|
||||
|
||||
{ check whether right_reg.reghi is less than left_reg.reghi }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,left_reg.reghi,right_reg.reghi));
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_CS,S_NO,labelcmp64_1));
|
||||
|
||||
{ are left_reg.reghi and right_reg.reghi equal? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_NE,S_NO,labelcmp64_2));
|
||||
|
||||
{ is right_reg.reglo less than left_reg.reglo? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,left_reg.reglo,right_reg.reglo));
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_CS,S_NO,labelcmp64_1));
|
||||
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64_2);
|
||||
|
||||
{ load the value for "true" }
|
||||
cg.a_load_const_reg(current_asmdata.currasmlist,OS_INT,1,tmpreg);
|
||||
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64_1);
|
||||
result:=tmpreg;
|
||||
end;
|
||||
|
||||
function t68kaddnode.getresflags(unsigned : boolean) : tresflags;
|
||||
begin
|
||||
case nodetype of
|
||||
@ -297,66 +101,6 @@ implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
function t68kaddnode.getres64_register(unsigned:boolean;left_reg,right_reg:tregister64):tregister;
|
||||
begin
|
||||
case nodetype of
|
||||
equaln:
|
||||
result:=cmp64_eq(left_reg,right_reg);
|
||||
unequaln:
|
||||
result:=cmp64_ne(left_reg,right_reg);
|
||||
else
|
||||
if not unsigned then
|
||||
begin
|
||||
if nf_swapped in flags then
|
||||
case nodetype of
|
||||
ltn:
|
||||
result:=cmp64_lt(right_reg,left_reg);
|
||||
lten:
|
||||
result:=cmp64_le(right_reg,left_reg);
|
||||
gtn:
|
||||
result:=cmp64_lt(left_reg,right_reg);
|
||||
gten:
|
||||
result:=cmp64_le(left_reg,right_reg);
|
||||
end
|
||||
else
|
||||
case nodetype of
|
||||
ltn:
|
||||
result:=cmp64_lt(left_reg,right_reg);
|
||||
lten:
|
||||
result:=cmp64_le(left_reg,right_reg);
|
||||
gtn:
|
||||
result:=cmp64_lt(right_reg,left_reg);
|
||||
gten:
|
||||
result:=cmp64_le(right_reg,left_reg);
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if nf_swapped in Flags then
|
||||
case nodetype of
|
||||
ltn:
|
||||
result:=cmp64_ltu(right_reg,left_reg);
|
||||
lten:
|
||||
result:=cmp64_leu(right_reg,left_reg);
|
||||
gtn:
|
||||
result:=cmp64_ltu(left_reg,right_reg);
|
||||
gten:
|
||||
result:=cmp64_leu(left_reg,right_reg);
|
||||
end
|
||||
else
|
||||
case nodetype of
|
||||
ltn:
|
||||
result:=cmp64_ltu(left_reg,right_reg);
|
||||
lten:
|
||||
result:=cmp64_leu(left_reg,right_reg);
|
||||
gtn:
|
||||
result:=cmp64_ltu(right_reg,left_reg);
|
||||
gten:
|
||||
result:=cmp64_leu(right_reg,left_reg);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{*****************************************************************************
|
||||
AddFloat
|
||||
@ -504,10 +248,40 @@ implementation
|
||||
tmpreg : tregister;
|
||||
opsize : topsize;
|
||||
cmpsize : tcgsize;
|
||||
href: treference;
|
||||
begin
|
||||
{ determine if the comparison will be unsigned }
|
||||
unsigned:=not(is_signed(left.resultdef)) or
|
||||
not(is_signed(right.resultdef));
|
||||
{ this puts constant operand (if any) to the right }
|
||||
pass_left_right;
|
||||
{ tentatively assume left size (correct for possible TST/CMPI, will fix later) }
|
||||
cmpsize:=def_cgsize(left.resultdef);
|
||||
opsize:=tcgsize2opsize[cmpsize];
|
||||
|
||||
{ set result location }
|
||||
location_reset(location,LOC_JUMP,OS_NO);
|
||||
location_reset(location,LOC_FLAGS,OS_NO);
|
||||
location.resflags := getresflags(unsigned);
|
||||
|
||||
{ see if we can optimize into TST }
|
||||
if (right.location.loc=LOC_CONSTANT) and (right.location.value=0) and
|
||||
((nodetype in [equaln,unequaln]) or (not unsigned)) then
|
||||
begin
|
||||
case left.location.loc of
|
||||
LOC_REFERENCE,
|
||||
LOC_CREFERENCE:
|
||||
begin
|
||||
href:=left.location.reference;
|
||||
tcg68k(cg).fixref(current_asmdata.CurrAsmList,href);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_TST,opsize,href));
|
||||
location_freetemp(current_asmdata.CurrAsmList,left.location);
|
||||
end;
|
||||
else
|
||||
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_TST,opsize,left.location.register));
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ ToDo : set "allowconstants" to True, but this seems to upset Coldfire
|
||||
a bit for the CMP instruction => check manual and implement
|
||||
@ -515,49 +289,8 @@ implementation
|
||||
{ load values into registers (except constants) }
|
||||
force_reg_left_right(true, false);
|
||||
|
||||
{ determine if the comparison will be unsigned }
|
||||
unsigned:=not(is_signed(left.resultdef)) or
|
||||
not(is_signed(right.resultdef));
|
||||
useconst := false;
|
||||
|
||||
// get the constant on the right if there is one
|
||||
if (left.location.loc = LOC_CONSTANT) then
|
||||
swapleftright;
|
||||
// can we use an immediate, or do we have to load the
|
||||
// constant in a register first?
|
||||
if (right.location.loc = LOC_CONSTANT) then
|
||||
begin
|
||||
{$ifdef extdebug}
|
||||
if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.value64)<>0) and ((hi(right.location.value64)<>-1) or unsigned) then
|
||||
internalerror(2002080301);
|
||||
{$endif extdebug}
|
||||
if (nodetype in [equaln,unequaln]) then
|
||||
if (unsigned and
|
||||
(right.location.value > high(word))) or
|
||||
(not unsigned and
|
||||
(longint(right.location.value) < low(smallint)) or
|
||||
(longint(right.location.value) > high(smallint))) then
|
||||
{ we can then maybe use a constant in the 'othersigned' case
|
||||
(the sign doesn't matter for // equal/unequal)}
|
||||
unsigned := not unsigned;
|
||||
|
||||
if (unsigned and
|
||||
((right.location.value) <= high(word))) or
|
||||
(not(unsigned) and
|
||||
(longint(right.location.value) >= low(smallint)) and
|
||||
(longint(right.location.value) <= high(smallint))) then
|
||||
useconst := true
|
||||
else
|
||||
begin
|
||||
useconst := false;
|
||||
tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
|
||||
cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,
|
||||
aword(right.location.value),tmpreg);
|
||||
end
|
||||
end
|
||||
else
|
||||
useconst := false;
|
||||
location.loc := LOC_FLAGS;
|
||||
location.resflags := getresflags(unsigned);
|
||||
if tcgsize2size[right.location.size]=tcgsize2size[left.location.size] then
|
||||
cmpsize:=left.location.size
|
||||
else
|
||||
@ -571,7 +304,7 @@ implementation
|
||||
internalerror(2013090301);
|
||||
{ Attention: The RIGHT(!) operand is substracted from and must be a
|
||||
register! }
|
||||
if (right.location.loc = LOC_CONSTANT) then
|
||||
{if (right.location.loc = LOC_CONSTANT) then
|
||||
if useconst then
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,opsize,
|
||||
longint(right.location.value),left.location.register))
|
||||
@ -580,33 +313,12 @@ implementation
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,opsize,
|
||||
tmpreg,left.location.register));
|
||||
end
|
||||
else
|
||||
else}
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,opsize,
|
||||
right.location.register,left.location.register));
|
||||
end;
|
||||
|
||||
|
||||
function t68kaddnode.pass_1:tnode;
|
||||
var
|
||||
ld,rd : tdef;
|
||||
begin
|
||||
result:=inherited pass_1;
|
||||
|
||||
{ for 64 bit operations we return the resulting value in a register }
|
||||
if not assigned(result) then
|
||||
begin
|
||||
rd:=right.resultdef;
|
||||
ld:=left.resultdef;
|
||||
if (nodetype in [ltn,lten,gtn,gten,equaln,unequaln]) and
|
||||
(
|
||||
((ld.typ=orddef) and (torddef(ld).ordtype in [u64bit,s64bit,scurrency])) or
|
||||
((rd.typ=orddef) and (torddef(rd).ordtype in [u64bit,s64bit,scurrency]))
|
||||
) then
|
||||
expectloc:=LOC_REGISTER;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
64-bit
|
||||
*****************************************************************************}
|
||||
@ -614,7 +326,64 @@ implementation
|
||||
procedure t68kaddnode.second_cmp64bit;
|
||||
var
|
||||
unsigned : boolean;
|
||||
tmp_left_reg : tregister;
|
||||
|
||||
procedure firstjmp64bitcmp;
|
||||
var
|
||||
oldnodetype : tnodetype;
|
||||
begin
|
||||
case nodetype of
|
||||
ltn,gtn:
|
||||
begin
|
||||
cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
|
||||
{ cheat a little bit for the negative test }
|
||||
toggleflag(nf_swapped);
|
||||
cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrFalseLabel);
|
||||
toggleflag(nf_swapped);
|
||||
end;
|
||||
lten,gten:
|
||||
begin
|
||||
oldnodetype:=nodetype;
|
||||
if nodetype=lten then
|
||||
nodetype:=ltn
|
||||
else
|
||||
nodetype:=gtn;
|
||||
cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
|
||||
{ cheat for the negative test }
|
||||
if nodetype=ltn then
|
||||
nodetype:=gtn
|
||||
else
|
||||
nodetype:=ltn;
|
||||
cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrFalseLabel);
|
||||
nodetype:=oldnodetype;
|
||||
end;
|
||||
equaln:
|
||||
cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrFalseLabel);
|
||||
unequaln:
|
||||
cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrTrueLabel);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure secondjmp64bitcmp;
|
||||
begin
|
||||
case nodetype of
|
||||
ltn,gtn,lten,gten:
|
||||
begin
|
||||
cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(true),current_procinfo.CurrTrueLabel);
|
||||
cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
|
||||
end;
|
||||
equaln:
|
||||
begin
|
||||
cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrFalseLabel);
|
||||
cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
|
||||
end;
|
||||
unequaln:
|
||||
begin
|
||||
cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrTrueLabel);
|
||||
cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
pass_left_right;
|
||||
force_reg_left_right(false,false);
|
||||
@ -622,113 +391,11 @@ implementation
|
||||
unsigned:=not(is_signed(left.resultdef)) or
|
||||
not(is_signed(right.resultdef));
|
||||
|
||||
location_reset(location,LOC_REGISTER,OS_INT);
|
||||
location.register:=getres64_register(unsigned,left.location.register64,right.location.register64);
|
||||
|
||||
{ keep the below code for now, as we could optimize the =/<> code later
|
||||
on based on it }
|
||||
|
||||
// writeln('second_cmp64bit');
|
||||
// pass_left_right;
|
||||
|
||||
|
||||
// load_left_right(true,false);
|
||||
(*
|
||||
case nodetype of
|
||||
ltn,lten,
|
||||
gtn,gten:
|
||||
begin
|
||||
emit_cmp64_hi;
|
||||
firstjmp64bitcmp;
|
||||
emit_cmp64_lo;
|
||||
secondjmp64bitcmp;
|
||||
end;
|
||||
equaln,unequaln:
|
||||
begin
|
||||
// instead of doing a complicated compare, do
|
||||
// (left.hi xor right.hi) or (left.lo xor right.lo)
|
||||
// (somewhate optimized so that no superfluous 'mr's are
|
||||
// generated)
|
||||
if (left.location.loc = LOC_CONSTANT) then
|
||||
swapleftright;
|
||||
if (right.location.loc = LOC_CONSTANT) then
|
||||
begin
|
||||
if left.location.loc = LOC_REGISTER then
|
||||
begin
|
||||
tempreg64.reglo := left.location.register64.reglo;
|
||||
tempreg64.reghi := left.location.register64.reghi;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (aword(right.location.valueqword) <> 0) then
|
||||
tempreg64.reglo := cg.getintregister(current_asmdata.CurrAsmList)
|
||||
else
|
||||
tempreg64.reglo := left.location.register64.reglo;
|
||||
if ((right.location.valueqword shr 32) <> 0) then
|
||||
tempreg64.reghi := cg.getintregister(current_asmdata.CurrAsmList)
|
||||
else
|
||||
tempreg64.reghi := left.location.register64.reghi;
|
||||
end;
|
||||
|
||||
if (aword(right.location.valueqword) <> 0) then
|
||||
{ negative values can be handled using SUB, }
|
||||
{ positive values < 65535 using XOR. }
|
||||
if (longint(right.location.valueqword) >= -32767) and
|
||||
(longint(right.location.valueqword) < 0) then
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,
|
||||
aword(right.location.valueqword),
|
||||
left.location.register64.reglo,tempreg64.reglo)
|
||||
else
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_XOR,OS_INT,
|
||||
aword(right.location.valueqword),
|
||||
left.location.register64.reglo,tempreg64.reglo);
|
||||
|
||||
if ((right.location.valueqword shr 32) <> 0) then
|
||||
if (longint(right.location.valueqword shr 32) >= -32767) and
|
||||
(longint(right.location.valueqword shr 32) < 0) then
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,
|
||||
aword(right.location.valueqword shr 32),
|
||||
left.location.register64.reghi,tempreg64.reghi)
|
||||
else
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_XOR,OS_INT,
|
||||
aword(right.location.valueqword shr 32),
|
||||
left.location.register64.reghi,tempreg64.reghi);
|
||||
end
|
||||
else
|
||||
begin
|
||||
tempreg64.reglo := cg.getintregister(current_asmdata.CurrAsmList);
|
||||
tempreg64.reghi := cg.getintregister(current_asmdata.CurrAsmList);
|
||||
cg64.a_op64_reg_reg_reg(current_asmdata.CurrAsmList,OP_XOR,
|
||||
left.location.register64,right.location.register64,
|
||||
tempreg64);
|
||||
end;
|
||||
|
||||
cg.a_reg_alloc(current_asmdata.CurrAsmList,R_0);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR_,R_0,
|
||||
tempreg64.reglo,tempreg64.reghi));
|
||||
cg.a_reg_dealloc(current_asmdata.CurrAsmList,R_0);
|
||||
if (tempreg64.reglo <> left.location.register64.reglo) then
|
||||
cg.ungetregister(current_asmdata.CurrAsmList,tempreg64.reglo);
|
||||
if (tempreg64.reghi <> left.location.register64.reghi) then
|
||||
cg.ungetregister(current_asmdata.CurrAsmList,tempreg64.reghi);
|
||||
|
||||
location_reset(location,LOC_FLAGS,OS_NO);
|
||||
location.resflags := getresflags;
|
||||
end;
|
||||
else
|
||||
internalerror(2002072803);
|
||||
end;
|
||||
|
||||
|
||||
{ set result location }
|
||||
{ (emit_compare sets it to LOC_FLAGS for compares, so set the }
|
||||
{ real location only now) (JM) }
|
||||
if cmpop and
|
||||
not(nodetype in [equaln,unequaln]) then
|
||||
location_reset(location,LOC_JUMP,OS_NO);
|
||||
*)
|
||||
// location_reset(location,LOC_JUMP,OS_NO);
|
||||
// writeln('second_cmp64_exit');
|
||||
location_reset(location,LOC_JUMP,OS_NO);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,S_L,right.location.register64.reghi,left.location.register64.reghi));
|
||||
firstjmp64bitcmp;
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,S_L,right.location.register64.reglo,left.location.register64.reglo));
|
||||
secondjmp64bitcmp;
|
||||
end;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user