|
@@ -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;
|
|
|
|