From 9e825bdc76556c34799e1f1d7b8a4b6805955bae Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sun, 15 Oct 2006 15:43:29 +0000 Subject: [PATCH] * moved common code for ppc32/ppc64 from nppcadd to shared unit git-svn-id: trunk@4930 - --- .gitattributes | 1 + compiler/powerpc/nppcadd.pas | 473 +---------------------------- compiler/powerpc64/nppcadd.pas | 486 +----------------------------- compiler/ppcgen/ngppcadd.pas | 534 +++++++++++++++++++++++++++++++++ 4 files changed, 541 insertions(+), 953 deletions(-) create mode 100644 compiler/ppcgen/ngppcadd.pas diff --git a/.gitattributes b/.gitattributes index cc564f170d..fd9ab355bb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -378,6 +378,7 @@ compiler/ppc.conf -text compiler/ppc.dof -text compiler/ppc.dpr -text compiler/ppcgen/cgppc.pas svneol=native#text/plain +compiler/ppcgen/ngppcadd.pas svneol=native#text/plain compiler/ppheap.pas svneol=native#text/plain compiler/ppu.pas svneol=native#text/plain compiler/procinfo.pas svneol=native#text/plain diff --git a/compiler/powerpc/nppcadd.pas b/compiler/powerpc/nppcadd.pas index b7911abba6..a99a60d706 100644 --- a/compiler/powerpc/nppcadd.pas +++ b/compiler/powerpc/nppcadd.pas @@ -26,22 +26,15 @@ unit nppcadd; interface uses - node,nadd,ncgadd,cpubase; + node,nadd,ncgadd,ngppcadd,cpubase; type - tppcaddnode = class(tcgaddnode) - function pass_1: tnode; override; + tppcaddnode = class(tgenppcaddnode) procedure pass_2;override; protected function use_generic_mul32to64: boolean; override; private - procedure pass_left_and_right; - procedure load_left_right(cmpop, load_constants: boolean); - function getresflags : tresflags; - procedure emit_compare(unsigned : boolean); - procedure second_addfloat;override; - procedure second_addboolean;override; - procedure second_addsmallset;override; + procedure emit_compare(unsigned : boolean); override; {$ifdef SUPPORT_MMX} procedure second_addmmx;override; {$endif SUPPORT_MMX} @@ -65,24 +58,6 @@ interface Pass 1 *****************************************************************************} - function tppcaddnode.pass_1: tnode; - begin - resulttypepass(left); - if (nodetype in [equaln,unequaln]) and - (left.resulttype.def.deftype = orddef) and - is_64bit(left.resulttype.def) then - begin - result := nil; - firstpass(left); - firstpass(right); - expectloc := LOC_FLAGS; - calcregisters(self,2,0,0); - exit; - end; - result := inherited pass_1; - end; - - function tppcaddnode.use_generic_mul32to64: boolean; begin result := false; @@ -92,80 +67,6 @@ interface Helpers *****************************************************************************} - procedure tppcaddnode.pass_left_and_right; - begin - { calculate the operator which is more difficult } - firstcomplex(self); - - { in case of constant put it to the left } - if (left.nodetype=ordconstn) then - swapleftright; - - secondpass(left); - secondpass(right); - end; - - - procedure tppcaddnode.load_left_right(cmpop, load_constants: boolean); - - procedure load_node(var n: tnode); - begin - case n.location.loc of - LOC_REGISTER, - LOC_CREGISTER: - ; - LOC_REFERENCE,LOC_CREFERENCE: - location_force_reg(current_asmdata.CurrAsmList,n.location,def_cgsize(n.resulttype.def),false); - LOC_CONSTANT: - begin - if load_constants then - location_force_reg(current_asmdata.CurrAsmList,n.location,def_cgsize(n.resulttype.def),false); - end; - else - location_force_reg(current_asmdata.CurrAsmList,n.location,def_cgsize(n.resulttype.def),false); - end; - end; - - begin - load_node(left); - load_node(right); - if not(cmpop) then - begin - location.register := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); - if is_64bit(resulttype.def) then - location.register64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); - end; - end; - - - function tppcaddnode.getresflags : tresflags; - begin - if (left.resulttype.def.deftype <> floatdef) then - result.cr := RS_CR0 - else - result.cr := RS_CR1; - case nodetype of - equaln : result.flag:=F_EQ; - unequaln : result.flag:=F_NE; - else - if nf_swaped in flags then - case nodetype of - ltn : result.flag:=F_GT; - lten : result.flag:=F_GE; - gtn : result.flag:=F_LT; - gten : result.flag:=F_LE; - end - else - case nodetype of - ltn : result.flag:=F_LT; - lten : result.flag:=F_LE; - gtn : result.flag:=F_GT; - gten : result.flag:=F_GE; - end; - end - end; - - procedure tppcaddnode.emit_compare(unsigned: boolean); var op : tasmop; @@ -235,374 +136,6 @@ interface end; -{***************************************************************************** - AddBoolean -*****************************************************************************} - - procedure tppcaddnode.second_addboolean; - var - cgop : TOpCg; - cgsize : TCgSize; - cmpop, - isjump : boolean; - otl,ofl : tasmlabel; - begin - { calculate the operator which is more difficult } - firstcomplex(self); - - cmpop:=false; - if (torddef(left.resulttype.def).typ=bool8bit) or - (torddef(right.resulttype.def).typ=bool8bit) then - cgsize:=OS_8 - else - if (torddef(left.resulttype.def).typ=bool16bit) or - (torddef(right.resulttype.def).typ=bool16bit) then - cgsize:=OS_16 - else - cgsize:=OS_32; - - if ((cs_full_boolean_eval in aktlocalswitches) and - not(nf_short_bool in flags)) or - (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then - begin - if left.nodetype in [ordconstn,realconstn] then - swapleftright; - - isjump:=(left.expectloc=LOC_JUMP); - if isjump then - begin - otl:=current_procinfo.CurrTrueLabel; - current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel); - ofl:=current_procinfo.CurrFalseLabel; - current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel); - end; - secondpass(left); - if left.location.loc in [LOC_FLAGS,LOC_JUMP] then - location_force_reg(current_asmdata.CurrAsmList,left.location,cgsize,false); - if isjump then - begin - current_procinfo.CurrTrueLabel:=otl; - current_procinfo.CurrFalseLabel:=ofl; - end - else if left.location.loc=LOC_JUMP then - internalerror(2003122901); - - isjump:=(right.expectloc=LOC_JUMP); - if isjump then - begin - otl:=current_procinfo.CurrTrueLabel; - current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel); - ofl:=current_procinfo.CurrFalseLabel; - current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel); - end; - secondpass(right); - if right.location.loc in [LOC_FLAGS,LOC_JUMP] then - location_force_reg(current_asmdata.CurrAsmList,right.location,cgsize,false); - if isjump then - begin - current_procinfo.CurrTrueLabel:=otl; - current_procinfo.CurrFalseLabel:=ofl; - end - else if right.location.loc=LOC_JUMP then - internalerror(200312292); - - cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln]; - - { set result location } - if not cmpop then - location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def)) - else - location_reset(location,LOC_FLAGS,OS_NO); - - load_left_right(cmpop,false); - - if (left.location.loc = LOC_CONSTANT) then - swapleftright; - - { compare the } - case nodetype of - ltn,lten,gtn,gten, - equaln,unequaln : - begin - if (right.location.loc <> LOC_CONSTANT) then - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMPLW, - left.location.register,right.location.register)) - else - current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMPLWI, - left.location.register,longint(right.location.value))); - location.resflags := getresflags; - end; - else - begin - case nodetype of - xorn : - cgop:=OP_XOR; - orn : - cgop:=OP_OR; - andn : - cgop:=OP_AND; - else - internalerror(200203247); - end; - - if right.location.loc <> LOC_CONSTANT then - cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT, - left.location.register,right.location.register, - location.register) - else - cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT, - right.location.value,left.location.register, - location.register); - end; - end; - end - else - inherited second_addboolean; - end; - - -{***************************************************************************** - AddFloat -*****************************************************************************} - - procedure tppcaddnode.second_addfloat; - var - op : TAsmOp; - cmpop, - singleprec : boolean; - begin - pass_left_and_right; - - cmpop:=false; - singleprec:=tfloatdef(left.resulttype.def).typ=s32real; - case nodetype of - addn : - if singleprec then - op:=A_FADDS - else - op:=A_FADD; - muln : - if singleprec then - op:=A_FMULS - else - op:=A_FMUL; - subn : - if singleprec then - op:=A_FSUBS - else - op:=A_FSUB; - slashn : - if singleprec then - op:=A_FDIVS - else - op:=A_FDIV; - ltn,lten,gtn,gten, - equaln,unequaln : - begin - op:=A_FCMPO; - cmpop:=true; - end; - else - internalerror(200403182); - end; - - // get the operands in the correct order, there are no special cases - // here, everything is register-based - if nf_swaped in flags then - swapleftright; - - // put both operands in a register - location_force_fpureg(current_asmdata.CurrAsmList,right.location,true); - location_force_fpureg(current_asmdata.CurrAsmList,left.location,true); - - // initialize de result - if not cmpop then - begin - location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def)); - location.register := cg.getfpuregister(current_asmdata.CurrAsmList,location.size); - end - else - begin - location_reset(location,LOC_FLAGS,OS_NO); - location.resflags := getresflags; - end; - - // emit the actual operation - if not cmpop then - begin - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op, - location.register,left.location.register, - right.location.register)) - end - else - begin - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op, - newreg(R_SPECIALREGISTER,location.resflags.cr,R_SUBNONE),left.location.register,right.location.register)) - end; - end; - -{***************************************************************************** - AddSmallSet -*****************************************************************************} - - procedure tppcaddnode.second_addsmallset; - var - cgop : TOpCg; - tmpreg : tregister; - opdone, - cmpop : boolean; - begin - pass_left_and_right; - - { when a setdef is passed, it has to be a smallset } - if ((left.resulttype.def.deftype=setdef) and - (tsetdef(left.resulttype.def).settype<>smallset)) or - ((right.resulttype.def.deftype=setdef) and - (tsetdef(right.resulttype.def).settype<>smallset)) then - internalerror(200203301); - - opdone := false; - cmpop:=nodetype in [equaln,unequaln,lten,gten]; - - { set result location } - if not cmpop then - location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def)) - else - location_reset(location,LOC_FLAGS,OS_NO); - - load_left_right(cmpop,false); - - if not(cmpop) then - location.register := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); - - case nodetype of - addn : - begin - if (nf_swaped in flags) and (left.nodetype=setelementn) then - swapleftright; - { are we adding set elements ? } - if right.nodetype=setelementn then - begin - { no range support for smallsets! } - if assigned(tsetelementnode(right).right) then - internalerror(43244); - if (right.location.loc = LOC_CONSTANT) then - cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT, - aint(aword(1) shl aword(right.location.value)), - left.location.register,location.register) - else - begin - tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); - cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,1,tmpreg); - cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_INT, - right.location.register,tmpreg); - if left.location.loc <> LOC_CONSTANT then - cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT,tmpreg, - left.location.register,location.register) - else - cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT, - left.location.value,tmpreg,location.register); - end; - opdone := true; - end - else - cgop := OP_OR; - end; - symdifn : - cgop:=OP_XOR; - muln : - cgop:=OP_AND; - subn : - begin - cgop:=OP_AND; - if (not(nf_swaped in flags)) then - if (right.location.loc=LOC_CONSTANT) then - right.location.value := not(right.location.value) - else - opdone := true - else if (left.location.loc=LOC_CONSTANT) then - left.location.value := not(left.location.value) - else - begin - swapleftright; - opdone := true; - end; - if opdone then - begin - if left.location.loc = LOC_CONSTANT then - begin - tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); - cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT, - left.location.value,tmpreg); - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC, - location.register,tmpreg,right.location.register)); - end - else - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC, - location.register,left.location.register, - right.location.register)); - end; - end; - equaln, - unequaln : - begin - emit_compare(true); - opdone := true; - end; - lten,gten: - begin - If (not(nf_swaped in flags) and - (nodetype = lten)) or - ((nf_swaped in flags) and - (nodetype = gten)) then - swapleftright; - // now we have to check whether left >= right - tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); - if left.location.loc = LOC_CONSTANT then - begin - cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_AND,OS_INT, - not(left.location.value),right.location.register,tmpreg); - current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0)); - // the two instructions above should be folded together by - // the peepholeoptimizer - end - else - begin - if right.location.loc = LOC_CONSTANT then - begin - cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT, - right.location.value,tmpreg); - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg, - tmpreg,left.location.register)); - end - else - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg, - right.location.register,left.location.register)); - end; - location.resflags.cr := RS_CR0; - location.resflags.flag := F_EQ; - opdone := true; - end; - else - internalerror(2002072701); - end; - - if not opdone then - begin - // these are all commutative operations - if (left.location.loc = LOC_CONSTANT) then - swapleftright; - if (right.location.loc = LOC_CONSTANT) then - cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT, - right.location.value,left.location.register, - location.register) - else - cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT, - right.location.register,left.location.register, - location.register); - end; - end; - {***************************************************************************** Add64bit *****************************************************************************} diff --git a/compiler/powerpc64/nppcadd.pas b/compiler/powerpc64/nppcadd.pas index 170454abaf..eec91a68d8 100644 --- a/compiler/powerpc64/nppcadd.pas +++ b/compiler/powerpc64/nppcadd.pas @@ -26,20 +26,13 @@ unit nppcadd; interface uses - node, nadd, ncgadd, cpubase; + node, nadd, ncgadd, ngppcadd, cpubase; type - tppcaddnode = class(tcgaddnode) - function pass_1: tnode; override; + tppcaddnode = class(tgenppcaddnode) procedure pass_2; override; private - procedure pass_left_and_right; - procedure load_left_right(cmpop, load_constants: boolean); - function getresflags: tresflags; - procedure emit_compare(unsigned: boolean); - procedure second_addfloat; override; - procedure second_addboolean; override; - procedure second_addsmallset; override; + procedure emit_compare(unsigned: boolean); override; end; implementation @@ -56,108 +49,10 @@ uses ncon, nset, ncgutil, tgobj, rgobj, rgcpu, cgobj; -{***************************************************************************** - Pass 1 -*****************************************************************************} - -function tppcaddnode.pass_1: tnode; -begin - resulttypepass(left); - if (nodetype in [equaln, unequaln]) and - (left.resulttype.def.deftype = orddef) {and - is_64bit(left.resulttype.def)}then - begin - result := nil; - firstpass(left); - firstpass(right); - expectloc := LOC_FLAGS; - calcregisters(self, 2, 0, 0); - exit; - end; - result := inherited pass_1; -end; - {***************************************************************************** Helpers *****************************************************************************} -procedure tppcaddnode.pass_left_and_right; -begin - { calculate the operator which is more difficult } - firstcomplex(self); - - { in case of constant put it to the left } - if (left.nodetype = ordconstn) then - swapleftright; - - secondpass(left); - secondpass(right); -end; - -procedure tppcaddnode.load_left_right(cmpop, load_constants: boolean); - - procedure load_node(var n: tnode); - begin - case n.location.loc of - LOC_CREGISTER: - ; - LOC_REGISTER: - if not cmpop then - begin - location.register := n.location.register; - end; - LOC_REFERENCE, LOC_CREFERENCE: - begin - location_force_reg(current_asmdata.CurrAsmList, n.location, - def_cgsize(n.resulttype.def), false); - end; - LOC_CONSTANT: - begin - if load_constants then begin - location_force_reg(current_asmdata.CurrAsmList, n.location, - def_cgsize(n.resulttype.def), false); - end; - end; - else - location_force_reg(current_asmdata.CurrAsmList,n.location,def_cgsize(n.resulttype.def),false); - end; - end; - -begin - load_node(left); - load_node(right); - if not (cmpop) then begin - location.register := cg.getintregister(current_asmdata.CurrAsmList, OS_INT); - end; -end; - -function tppcaddnode.getresflags: tresflags; -begin - if (left.resulttype.def.deftype <> floatdef) then - result.cr := RS_CR0 - else - result.cr := RS_CR1; - case nodetype of - equaln: result.flag := F_EQ; - unequaln: result.flag := F_NE; - else - if nf_swaped in flags then - case nodetype of - ltn: result.flag := F_GT; - lten: result.flag := F_GE; - gtn: result.flag := F_LT; - gten: result.flag := F_LE; - end - else - case nodetype of - ltn: result.flag := F_LT; - lten: result.flag := F_LE; - gtn: result.flag := F_GT; - gten: result.flag := F_GE; - end; - end -end; - procedure tppcaddnode.emit_compare(unsigned: boolean); const { unsigned useconst 32bit-op } @@ -238,381 +133,6 @@ begin right.location.register)); end; -{***************************************************************************** - AddBoolean -*****************************************************************************} - -procedure tppcaddnode.second_addboolean; -var - cgop: TOpCg; - cgsize: TCgSize; - cmpop, - isjump: boolean; - otl, ofl: tasmlabel; -begin - { calculate the operator which is more difficult } - firstcomplex(self); - - cmpop := false; - if (torddef(left.resulttype.def).typ = bool8bit) or - (torddef(right.resulttype.def).typ = bool8bit) then - cgsize := OS_8 - else if (torddef(left.resulttype.def).typ = bool16bit) or - (torddef(right.resulttype.def).typ = bool16bit) then - cgsize := OS_16 - else - cgsize := OS_32; - - if ((cs_full_boolean_eval in aktlocalswitches) and - not(nf_short_bool in flags)) or - (nodetype in [unequaln, ltn, lten, gtn, gten, equaln, xorn]) then - begin - if left.nodetype in [ordconstn, realconstn] then - swapleftright; - - isjump := (left.expectloc = LOC_JUMP); - if isjump then - begin - otl := current_procinfo.CurrTrueLabel; - current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel); - ofl := current_procinfo.CurrFalseLabel; - current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel); - end; - secondpass(left); - if left.location.loc in [LOC_FLAGS, LOC_JUMP] then - location_force_reg(current_asmdata.CurrAsmList, left.location, cgsize, false); - if isjump then - begin - current_procinfo.CurrTrueLabel := otl; - current_procinfo.CurrFalseLabel := ofl; - end - else if left.location.loc = LOC_JUMP then - internalerror(2003122901); - - isjump := (right.expectloc = LOC_JUMP); - if isjump then - begin - otl := current_procinfo.CurrTrueLabel; - current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel); - ofl := current_procinfo.CurrFalseLabel; - current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel); - end; - secondpass(right); - if right.location.loc in [LOC_FLAGS, LOC_JUMP] then - location_force_reg(current_asmdata.CurrAsmList, right.location, cgsize, false); - if isjump then - begin - current_procinfo.CurrTrueLabel := otl; - current_procinfo.CurrFalseLabel := ofl; - end - else if right.location.loc = LOC_JUMP then - internalerror(200312292); - - cmpop := nodetype in [ltn, lten, gtn, gten, equaln, unequaln]; - - { set result location } - if not cmpop then - location_reset(location, LOC_REGISTER, def_cgsize(resulttype.def)) - else - location_reset(location, LOC_FLAGS, OS_NO); - - load_left_right(cmpop, false); - - if (left.location.loc = LOC_CONSTANT) then - swapleftright; - - { compare the } - case nodetype of - ltn, lten, gtn, gten, - equaln, unequaln: - begin - if (right.location.loc <> LOC_CONSTANT) then - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMPLW, - left.location.register, right.location.register)) - else - current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMPLWI, - left.location.register, longint(right.location.value))); - location.resflags := getresflags; - end; - else - begin - case nodetype of - xorn: - cgop := OP_XOR; - orn: - cgop := OP_OR; - andn: - cgop := OP_AND; - else - internalerror(200203247); - end; - - if right.location.loc <> LOC_CONSTANT then - cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, cgop, OS_INT, - left.location.register, right.location.register, - location.register) - else - cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, cgop, OS_INT, - right.location.value, left.location.register, - location.register); - end; - end; - end - else - inherited second_addboolean; -end; - -{***************************************************************************** - AddFloat -*****************************************************************************} - -procedure tppcaddnode.second_addfloat; -var - op: TAsmOp; - cmpop: boolean; - singleprec: boolean; -begin - pass_left_and_right; - - singleprec := tfloatdef(left.resulttype.def).typ = s32real; - cmpop := false; - case nodetype of - addn: - if (singleprec) then - op := A_FADDS - else - op := A_FADD; - muln: - if (singleprec) then - op := A_FMULS - else - op := A_FMUL; - subn: - if (singleprec) then - op := A_FSUBS - else - op := A_FSUB; - slashn: - if (singleprec) then - op := A_FDIVS - else - op := A_FDIV; - ltn, lten, gtn, gten, - equaln, unequaln: - begin - op := A_FCMPO; - cmpop := true; - end; - else - internalerror(200403182); - end; - - { get the operands in the correct order, there are no special cases - here, everything is register-based } - if nf_swaped in flags then - swapleftright; - - { put both operands in a register } - location_force_fpureg(current_asmdata.CurrAsmList, right.location, true); - location_force_fpureg(current_asmdata.CurrAsmList, left.location, true); - - { initialize the result } - if not cmpop then begin - location_reset(location, LOC_FPUREGISTER, def_cgsize(resulttype.def)); - location.register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size); - end else begin - location_reset(location, LOC_FLAGS, OS_NO); - location.resflags := getresflags; - end; - - { emit the actual operation } - if not cmpop then begin - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op, - location.register, left.location.register, - right.location.register)) - end else begin - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op, - newreg(R_SPECIALREGISTER, location.resflags.cr, R_SUBNONE), - left.location.register, right.location.register)) - end; -end; - -{***************************************************************************** - AddSmallSet -*****************************************************************************} - -procedure tppcaddnode.second_addsmallset; -var - cgop: TOpCg; - tmpreg: tregister; - opdone, - cmpop: boolean; - - astring : string; - // ts: todo - speed up by using 32 bit compares/adds/ands here -begin - pass_left_and_right; - - { when a setdef is passed, it has to be a smallset } - if ((left.resulttype.def.deftype = setdef) and - (tsetdef(left.resulttype.def).settype <> smallset)) or - ((right.resulttype.def.deftype = setdef) and - (tsetdef(right.resulttype.def).settype <> smallset)) then - internalerror(200203301); - - opdone := false; - cmpop := nodetype in [equaln, unequaln, lten, gten]; - - { set result location } - if not cmpop then - location_reset(location, LOC_REGISTER, def_cgsize(resulttype.def)) - else - location_reset(location, LOC_FLAGS, OS_NO); - - load_left_right(cmpop, false); - - if not (cmpop) then - location.register := cg.getintregister(current_asmdata.CurrAsmList, OS_64); - {$ifdef extdebug} - astring := 'addsmallset0 ' + inttostr(aword(1) shl aword(right.location.value)) + ' ' + inttostr(right.location.value); - current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew(astring))); - {$endif extdebug} - - case nodetype of - addn: - begin - if (nf_swaped in flags) and (left.nodetype = setelementn) then - swapleftright; - { are we adding set elements ? } - if right.nodetype = setelementn then begin - { no range support for smallsets! } - if assigned(tsetelementnode(right).right) then - internalerror(43244); - if (right.location.loc = LOC_CONSTANT) then begin - {$ifdef extdebug} - astring := 'addsmallset1 ' + inttostr(aword(1) shl aword(right.location.value)) + ' ' + inttostr(right.location.value); - current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew(astring))); - {$endif extdebug} - - cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_64, - aint(1) shl aint(right.location.value), - left.location.register, location.register) - end else - begin - tmpreg := cg.getintregister(current_asmdata.CurrAsmList, OS_64); - cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_64, 1, tmpreg); - cg.a_op_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_64, - right.location.register, tmpreg); - if left.location.loc <> LOC_CONSTANT then begin - cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_64, tmpreg, - left.location.register, location.register) - end else begin - {$ifdef extdebug} - astring := 'addsmallset2 ' + inttostr(left.location.value); - current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew(astring))); - {$endif extdebug} - cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_64, - left.location.value, tmpreg, location.register); - end; - end; - opdone := true; - end else begin - cgop := OP_OR; - end; - end; - symdifn: - cgop := OP_XOR; - muln: - cgop := OP_AND; - subn: - begin - cgop := OP_AND; - if (not (nf_swaped in flags)) then - if (right.location.loc = LOC_CONSTANT) then - right.location.value := not (right.location.value) - else - opdone := true - else if (left.location.loc = LOC_CONSTANT) then - left.location.value := not (left.location.value) - else begin - swapleftright; - opdone := true; - end; - if opdone then begin - if left.location.loc = LOC_CONSTANT then - begin - tmpreg := cg.getintregister(current_asmdata.CurrAsmList, OS_64); - cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_64, - left.location.value, tmpreg); - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC, - location.register, tmpreg, right.location.register)); - end - else - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC, - location.register, left.location.register, - right.location.register)); - end; - end; - equaln, - unequaln: - begin - emit_compare(true); - opdone := true; - end; - lten, gten: - begin - if (not (nf_swaped in flags) and - (nodetype = lten)) or - ((nf_swaped in flags) and - (nodetype = gten)) then - swapleftright; - { now we have to check whether left >= right } - tmpreg := cg.getintregister(current_asmdata.CurrAsmList, OS_64); - if left.location.loc = LOC_CONSTANT then begin - cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_64, - not (left.location.value), right.location.register, tmpreg); - current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMPDI, tmpreg, 0)); - { the two instructions above should be folded together by - the peepholeoptimizer } - end else begin - if right.location.loc = LOC_CONSTANT then begin - cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_64, - right.location.value, tmpreg); - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC_, tmpreg, - tmpreg, left.location.register)); - end else - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC_, tmpreg, - right.location.register, left.location.register)); - end; - location.resflags.cr := RS_CR0; - location.resflags.flag := F_EQ; - opdone := true; - end; - else - internalerror(2002072701); - end; - - if not opdone then begin - { these are all commutative operations } - if (left.location.loc = LOC_CONSTANT) then - swapleftright; - if (right.location.loc = LOC_CONSTANT) then begin - {$ifdef extdebug} - astring := 'addsmallset4 ' + inttostr(right.location.value); - current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew(astring))); - {$endif extdebug} - - cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, cgop, OS_64, - right.location.value, left.location.register, - location.register) - end else begin - cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, cgop, OS_64, - right.location.register, left.location.register, - location.register); - end; - end; -end; - {***************************************************************************** pass_2 *****************************************************************************} diff --git a/compiler/ppcgen/ngppcadd.pas b/compiler/ppcgen/ngppcadd.pas new file mode 100644 index 0000000000..3934c6ec7f --- /dev/null +++ b/compiler/ppcgen/ngppcadd.pas @@ -0,0 +1,534 @@ +{ + Copyright (c) 2000-2006 by Florian Klaempfl and Jonas Maebe + + Code generation for add nodes on the PowerPC (32 and 64 bit generic) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + **************************************************************************** +} + +unit ngppcadd; + + +{$i fpcdefs.inc} + +interface + + uses + node,nadd,ncgadd,cpubase; + + type + tgenppcaddnode = class(tcgaddnode) + function pass_1: tnode; override; + protected + procedure pass_left_and_right; + procedure load_left_right(cmpop, load_constants: boolean); + function getresflags : tresflags; + procedure emit_compare(unsigned: boolean); virtual; abstract; + procedure second_addfloat;override; + procedure second_addboolean;override; + procedure second_addsmallset;override; + end; + + +implementation + +{***************************************************************************** + Pass 1 +*****************************************************************************} + + uses + globtype,systems, + cutils,verbose,globals, + symconst,symdef,paramgr, + aasmbase,aasmtai,aasmdata,aasmcpu,defutil,htypechk, + cgbase,cpuinfo,pass_1,pass_2,regvars, + cpupara,cgcpu,cgutils,procinfo, + ncon,nset, + ncgutil,tgobj,rgobj,rgcpu,cgobj; + + +{***************************************************************************** + Pass 1 +*****************************************************************************} + + function tgenppcaddnode.pass_1: tnode; + begin + resulttypepass(left); + if (nodetype in [equaln,unequaln]) and + (left.resulttype.def.deftype = orddef) and + is_64bit(left.resulttype.def) then + begin + result := nil; + firstpass(left); + firstpass(right); + expectloc := LOC_FLAGS; + calcregisters(self,2,0,0); + exit; + end; + result := inherited pass_1; + end; + +{***************************************************************************** + Helpers +*****************************************************************************} + + procedure tgenppcaddnode.pass_left_and_right; + begin + { calculate the operator which is more difficult } + firstcomplex(self); + + { in case of constant put it to the left } + if (left.nodetype=ordconstn) then + swapleftright; + + secondpass(left); + secondpass(right); + end; + + + procedure tgenppcaddnode.load_left_right(cmpop, load_constants: boolean); + + procedure load_node(var n: tnode); + begin + case n.location.loc of + LOC_REGISTER, + LOC_CREGISTER: + ; + LOC_REFERENCE,LOC_CREFERENCE: + location_force_reg(current_asmdata.CurrAsmList,n.location,def_cgsize(n.resulttype.def),false); + LOC_CONSTANT: + begin + if load_constants then + location_force_reg(current_asmdata.CurrAsmList,n.location,def_cgsize(n.resulttype.def),false); + end; + else + location_force_reg(current_asmdata.CurrAsmList,n.location,def_cgsize(n.resulttype.def),false); + end; + end; + + begin + load_node(left); + load_node(right); + if not(cmpop) then + begin + location.register := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); +{$ifndef cpu64bit} + if is_64bit(resulttype.def) then + location.register64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); +{$endif cpu64bit} + end; + end; + + + function tgenppcaddnode.getresflags : tresflags; + begin + if (left.resulttype.def.deftype <> floatdef) then + result.cr := RS_CR0 + else + result.cr := RS_CR1; + case nodetype of + equaln : result.flag:=F_EQ; + unequaln : result.flag:=F_NE; + else + if nf_swaped in flags then + case nodetype of + ltn : result.flag:=F_GT; + lten : result.flag:=F_GE; + gtn : result.flag:=F_LT; + gten : result.flag:=F_LE; + end + else + case nodetype of + ltn : result.flag:=F_LT; + lten : result.flag:=F_LE; + gtn : result.flag:=F_GT; + gten : result.flag:=F_GE; + end; + end + end; + + +{***************************************************************************** + AddBoolean +*****************************************************************************} + + procedure tgenppcaddnode.second_addboolean; + var + cgop : TOpCg; + cgsize : TCgSize; + cmpop, + isjump : boolean; + otl,ofl : tasmlabel; + begin + { calculate the operator which is more difficult } + firstcomplex(self); + + cmpop:=false; + if (torddef(left.resulttype.def).typ=bool8bit) or + (torddef(right.resulttype.def).typ=bool8bit) then + cgsize:=OS_8 + else + if (torddef(left.resulttype.def).typ=bool16bit) or + (torddef(right.resulttype.def).typ=bool16bit) then + cgsize:=OS_16 + else + cgsize:=OS_32; + + if ((cs_full_boolean_eval in aktlocalswitches) and + not(nf_short_bool in flags)) or + (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then + begin + if left.nodetype in [ordconstn,realconstn] then + swapleftright; + + isjump:=(left.expectloc=LOC_JUMP); + if isjump then + begin + otl:=current_procinfo.CurrTrueLabel; + current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel); + ofl:=current_procinfo.CurrFalseLabel; + current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel); + end; + secondpass(left); + if left.location.loc in [LOC_FLAGS,LOC_JUMP] then + location_force_reg(current_asmdata.CurrAsmList,left.location,cgsize,false); + if isjump then + begin + current_procinfo.CurrTrueLabel:=otl; + current_procinfo.CurrFalseLabel:=ofl; + end + else if left.location.loc=LOC_JUMP then + internalerror(2003122901); + + isjump:=(right.expectloc=LOC_JUMP); + if isjump then + begin + otl:=current_procinfo.CurrTrueLabel; + current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel); + ofl:=current_procinfo.CurrFalseLabel; + current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel); + end; + secondpass(right); + if right.location.loc in [LOC_FLAGS,LOC_JUMP] then + location_force_reg(current_asmdata.CurrAsmList,right.location,cgsize,false); + if isjump then + begin + current_procinfo.CurrTrueLabel:=otl; + current_procinfo.CurrFalseLabel:=ofl; + end + else if right.location.loc=LOC_JUMP then + internalerror(200312292); + + cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln]; + + { set result location } + if not cmpop then + location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def)) + else + location_reset(location,LOC_FLAGS,OS_NO); + + load_left_right(cmpop,false); + + if (left.location.loc = LOC_CONSTANT) then + swapleftright; + + { compare the } + case nodetype of + ltn,lten,gtn,gten, + equaln,unequaln : + begin + if (right.location.loc <> LOC_CONSTANT) then + current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMPLW, + left.location.register,right.location.register)) + else + current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMPLWI, + left.location.register,longint(right.location.value))); + location.resflags := getresflags; + end; + else + begin + case nodetype of + xorn : + cgop:=OP_XOR; + orn : + cgop:=OP_OR; + andn : + cgop:=OP_AND; + else + internalerror(200203247); + end; + + if right.location.loc <> LOC_CONSTANT then + cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT, + left.location.register,right.location.register, + location.register) + else + cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT, + right.location.value,left.location.register, + location.register); + end; + end; + end + else + inherited second_addboolean; + end; + + +{***************************************************************************** + AddFloat +*****************************************************************************} + + procedure tgenppcaddnode.second_addfloat; + var + op : TAsmOp; + cmpop, + singleprec : boolean; + begin + pass_left_and_right; + + cmpop:=false; + singleprec:=tfloatdef(left.resulttype.def).typ=s32real; + case nodetype of + addn : + if singleprec then + op:=A_FADDS + else + op:=A_FADD; + muln : + if singleprec then + op:=A_FMULS + else + op:=A_FMUL; + subn : + if singleprec then + op:=A_FSUBS + else + op:=A_FSUB; + slashn : + if singleprec then + op:=A_FDIVS + else + op:=A_FDIV; + ltn,lten,gtn,gten, + equaln,unequaln : + begin + op:=A_FCMPO; + cmpop:=true; + end; + else + internalerror(200403182); + end; + + // get the operands in the correct order, there are no special cases + // here, everything is register-based + if nf_swaped in flags then + swapleftright; + + // put both operands in a register + location_force_fpureg(current_asmdata.CurrAsmList,right.location,true); + location_force_fpureg(current_asmdata.CurrAsmList,left.location,true); + + // initialize de result + if not cmpop then + begin + location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def)); + location.register := cg.getfpuregister(current_asmdata.CurrAsmList,location.size); + end + else + begin + location_reset(location,LOC_FLAGS,OS_NO); + location.resflags := getresflags; + end; + + // emit the actual operation + if not cmpop then + begin + current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op, + location.register,left.location.register, + right.location.register)) + end + else + begin + current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op, + newreg(R_SPECIALREGISTER,location.resflags.cr,R_SUBNONE),left.location.register,right.location.register)) + end; + end; + + +{***************************************************************************** + AddSmallSet +*****************************************************************************} + + procedure tgenppcaddnode.second_addsmallset; + var + cgop : TOpCg; + tmpreg : tregister; + opdone, + cmpop : boolean; + begin + pass_left_and_right; + + { when a setdef is passed, it has to be a smallset } + if ((left.resulttype.def.deftype=setdef) and + (tsetdef(left.resulttype.def).settype<>smallset)) or + ((right.resulttype.def.deftype=setdef) and + (tsetdef(right.resulttype.def).settype<>smallset)) then + internalerror(200203301); + + opdone := false; + cmpop:=nodetype in [equaln,unequaln,lten,gten]; + + { set result location } + if not cmpop then + location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def)) + else + location_reset(location,LOC_FLAGS,OS_NO); + + load_left_right(cmpop,false); + + if not(cmpop) then + location.register := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); + + case nodetype of + addn : + begin + if (nf_swaped in flags) and (left.nodetype=setelementn) then + swapleftright; + { are we adding set elements ? } + if right.nodetype=setelementn then + begin + { no range support for smallsets! } + if assigned(tsetelementnode(right).right) then + internalerror(43244); + if (right.location.loc = LOC_CONSTANT) then + cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT, + aint(aword(1) shl aword(right.location.value)), + left.location.register,location.register) + else + begin + tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); + cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,1,tmpreg); + cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_INT, + right.location.register,tmpreg); + if left.location.loc <> LOC_CONSTANT then + cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT,tmpreg, + left.location.register,location.register) + else + cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT, + left.location.value,tmpreg,location.register); + end; + opdone := true; + end + else + cgop := OP_OR; + end; + symdifn : + cgop:=OP_XOR; + muln : + cgop:=OP_AND; + subn : + begin + cgop:=OP_AND; + if (not(nf_swaped in flags)) then + if (right.location.loc=LOC_CONSTANT) then + right.location.value := not(right.location.value) + else + opdone := true + else if (left.location.loc=LOC_CONSTANT) then + left.location.value := not(left.location.value) + else + begin + swapleftright; + opdone := true; + end; + if opdone then + begin + if left.location.loc = LOC_CONSTANT then + begin + tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); + cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT, + left.location.value,tmpreg); + current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC, + location.register,tmpreg,right.location.register)); + end + else + current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC, + location.register,left.location.register, + right.location.register)); + end; + end; + equaln, + unequaln : + begin + emit_compare(true); + opdone := true; + end; + lten,gten: + begin + If (not(nf_swaped in flags) and + (nodetype = lten)) or + ((nf_swaped in flags) and + (nodetype = gten)) then + swapleftright; + // now we have to check whether left >= right + tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); + if left.location.loc = LOC_CONSTANT then + begin + cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_AND,OS_INT, + not(left.location.value),right.location.register,tmpreg); + current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0)); + // the two instructions above should be folded together by + // the peepholeoptimizer + end + else + begin + if right.location.loc = LOC_CONSTANT then + begin + cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT, + right.location.value,tmpreg); + current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg, + tmpreg,left.location.register)); + end + else + current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg, + right.location.register,left.location.register)); + end; + location.resflags.cr := RS_CR0; + location.resflags.flag := F_EQ; + opdone := true; + end; + else + internalerror(2002072701); + end; + + if not opdone then + begin + // these are all commutative operations + if (left.location.loc = LOC_CONSTANT) then + swapleftright; + if (right.location.loc = LOC_CONSTANT) then + cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT, + right.location.value,left.location.register, + location.register) + else + cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT, + right.location.register,left.location.register, + location.register); + end; + end; + +end.