mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-22 00:29:33 +02:00
m68k/n68kadd.pas:
+ add support for 64-bit comparisons; the code is based on the code of mips/ncpuadd.pas, but heavily adjusted for m68k git-svn-id: trunk@22913 -
This commit is contained in:
parent
9e35bfa252
commit
9d4d7d748c
@ -26,13 +26,21 @@ unit n68kadd;
|
||||
interface
|
||||
|
||||
uses
|
||||
node,nadd,ncgadd,cpubase;
|
||||
node,nadd,ncgadd,cpubase,cgbase;
|
||||
|
||||
|
||||
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;
|
||||
@ -40,6 +48,8 @@ interface
|
||||
procedure second_cmpsmallset;override;
|
||||
procedure second_cmp64bit;override;
|
||||
procedure second_cmpboolean;override;
|
||||
public
|
||||
function pass_1:tnode;override;
|
||||
end;
|
||||
|
||||
|
||||
@ -48,9 +58,9 @@ implementation
|
||||
uses
|
||||
globtype,systems,
|
||||
cutils,verbose,globals,
|
||||
symconst,symdef,paramgr,
|
||||
symconst,symdef,paramgr,symtype,
|
||||
aasmbase,aasmtai,aasmdata,aasmcpu,defutil,htypechk,
|
||||
cgbase,cpuinfo,pass_1,pass_2,regvars,
|
||||
cpuinfo,pass_1,pass_2,regvars,
|
||||
cpupara,cgutils,procinfo,
|
||||
ncon,nset,
|
||||
ncgutil,tgobj,rgobj,rgcpu,cgobj,hlcgobj,cg64f32;
|
||||
@ -59,6 +69,193 @@ implementation
|
||||
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" }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_const_reg(A_MOVE,S_L,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_L,labelcmp64_2));
|
||||
|
||||
{ are left_reg.reghi and right_reg.reghi equal? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_NE,S_L,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_L,labelcmp64_2));
|
||||
|
||||
current_asmdata.currasmlist.concat(Taicpu.op_sym(A_BRA,S_L,labelcmp64_1));
|
||||
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64_2);
|
||||
|
||||
{ load the value for "true" }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_const_reg(A_MOVE,S_L,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" }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_const_reg(A_MOVE,S_L,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_L,labelcmp64_1));
|
||||
|
||||
{ are left_reg.reghi and right_reg.reghi equal? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_NE,S_L,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_L,labelcmp64_1));
|
||||
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64_2);
|
||||
|
||||
{ load the value for "true" }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_const_reg(A_MOVE,S_L,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" }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_const_reg(A_MOVE,S_L,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_L,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_L,labelcmp64));
|
||||
|
||||
{ load the value for "true" }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_const_reg(A_MOVE,S_L,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" }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_const_reg(A_MOVE,S_L,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_L,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_L,labelcmp64));
|
||||
|
||||
{ load the value for "false" }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_const_reg(A_MOVE,S_L,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" }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_const_reg(A_MOVE,S_L,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_L,labelcmp64_2));
|
||||
|
||||
{ are left_reg.reghi and right_reg.reghi equal? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_NE,S_L,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_L,labelcmp64_2));
|
||||
|
||||
current_asmdata.currasmlist.concat(Taicpu.op_sym(A_BRA,S_L,labelcmp64_1));
|
||||
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64_2);
|
||||
|
||||
{ load the value for "true" }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_const_reg(A_MOVE,S_L,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" }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_const_reg(A_MOVE,S_L,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_L,labelcmp64_1));
|
||||
|
||||
{ are left_reg.reghi and right_reg.reghi equal? }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_cond_sym(A_BXX,C_NE,S_L,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_L,labelcmp64_1));
|
||||
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64_2);
|
||||
|
||||
{ load the value for "true" }
|
||||
current_asmdata.currasmlist.concat(taicpu.op_const_reg(A_MOVE,S_L,1,tmpreg));
|
||||
|
||||
cg.a_label(current_asmdata.currasmlist,labelcmp64_1);
|
||||
result:=tmpreg;
|
||||
end;
|
||||
|
||||
function t68kaddnode.getresflags(unsigned : boolean) : tresflags;
|
||||
begin
|
||||
@ -103,6 +300,67 @@ 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
|
||||
*****************************************************************************}
|
||||
@ -459,15 +717,50 @@ implementation
|
||||
//release_reg_left_right;
|
||||
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
|
||||
*****************************************************************************}
|
||||
|
||||
procedure t68kaddnode.second_cmp64bit;
|
||||
begin
|
||||
var
|
||||
unsigned : boolean;
|
||||
tmp_left_reg : tregister;
|
||||
begin
|
||||
pass_left_right;
|
||||
force_reg_left_right(false,false);
|
||||
|
||||
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;
|
||||
// pass_left_right;
|
||||
|
||||
|
||||
// load_left_right(true,false);
|
||||
@ -565,7 +858,7 @@ implementation
|
||||
not(nodetype in [equaln,unequaln]) then
|
||||
location_reset(location,LOC_JUMP,OS_NO);
|
||||
*)
|
||||
location_reset(location,LOC_JUMP,OS_NO);
|
||||
// location_reset(location,LOC_JUMP,OS_NO);
|
||||
// writeln('second_cmp64_exit');
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user