From fb55235acca3e07a3735a6220b90a362d9128bf5 Mon Sep 17 00:00:00 2001 From: daniel Date: Sat, 8 Mar 2003 13:59:16 +0000 Subject: [PATCH] * Work to handle new register notation in ag386nsm + Added newra version of Ti386moddivnode --- compiler/i386/ag386nsm.pas | 13 +++- compiler/i386/n386add.pas | 11 +++- compiler/i386/n386mat.pas | 131 ++++++++++++++++++++++++++++++++++++- compiler/i386/rgcpu.pas | 12 +++- compiler/rgobj.pas | 8 ++- 5 files changed, 165 insertions(+), 10 deletions(-) diff --git a/compiler/i386/ag386nsm.pas b/compiler/i386/ag386nsm.pas index 17f6c2b302..b140b02824 100644 --- a/compiler/i386/ag386nsm.pas +++ b/compiler/i386/ag386nsm.pas @@ -384,6 +384,7 @@ interface found, do_line, quoted : boolean; + regstr:string[5]; begin if not assigned(p) then exit; @@ -454,8 +455,12 @@ interface ait_regalloc : begin + if tai_regalloc(hp).reg.enum=R_INTREGISTER then + regstr:=intel_regname(tai_regalloc(hp).reg.number) + else + regstr:=std_reg2str[tai_regalloc(hp).reg.enum]; if (cs_asm_regalloc in aktglobalswitches) then - AsmWriteLn(target_asm.comment+'Register '+std_reg2str[tai_regalloc(hp).reg.enum]+ + AsmWriteLn(target_asm.comment+'Register '+regstr+ allocstr[tai_regalloc(hp).allocation]); end; @@ -916,7 +921,11 @@ initialization end. { $Log$ - Revision 1.31 2003-03-08 08:59:07 daniel + Revision 1.32 2003-03-08 13:59:17 daniel + * Work to handle new register notation in ag386nsm + + Added newra version of Ti386moddivnode + + Revision 1.31 2003/03/08 08:59:07 daniel + $define newra will enable new register allocator + getregisterint will return imaginary registers with $newra + -sr switch added, will skip register allocation so you can see diff --git a/compiler/i386/n386add.pas b/compiler/i386/n386add.pas index 849edd9516..c4798e7d4d 100644 --- a/compiler/i386/n386add.pas +++ b/compiler/i386/n386add.pas @@ -1344,10 +1344,11 @@ interface r.enum:=R_INTREGISTER; r.number:=NR_EDX; rg.ungetregisterint(exprasmlist,r); - {Free EAX} - rg.ungetregisterint(exprasmlist,r_eax); + {Allocate a new register and store the result in EAX in it.} location.register:=rg.getregisterint(exprasmlist,OS_INT); emit_reg_reg(A_MOV,S_L,r_eax,location.register); + {Free EAX} + rg.ungetregisterint(exprasmlist,r_eax); location_freetemp(exprasmlist,left.location); location_freetemp(exprasmlist,right.location); end; @@ -1635,7 +1636,11 @@ begin end. { $Log$ - Revision 1.56 2003-03-08 10:53:48 daniel + Revision 1.57 2003-03-08 13:59:17 daniel + * Work to handle new register notation in ag386nsm + + Added newra version of Ti386moddivnode + + Revision 1.56 2003/03/08 10:53:48 daniel * Created newra version of secondmul in n386add.pas Revision 1.55 2003/02/19 22:00:15 daniel diff --git a/compiler/i386/n386mat.pas b/compiler/i386/n386mat.pas index 921b64d3fc..e18c08b38d 100644 --- a/compiler/i386/n386mat.pas +++ b/compiler/i386/n386mat.pas @@ -64,6 +64,130 @@ implementation TI386MODDIVNODE *****************************************************************************} +{$ifdef newra} + procedure ti386moddivnode.pass_2; + + var r,r2,hreg1,hreg2:Tregister; + power:longint; + hl:Tasmlabel; + pushedregs:Tmaybesave; + + begin + secondpass(left); + if codegenerror then + exit; + maybe_save(exprasmlist,right.registers32,left.location,pushedregs); + secondpass(right); + maybe_restore(exprasmlist,left.location,pushedregs); + if codegenerror then + exit; + location_copy(location,left.location); + + if is_64bitint(resulttype.def) then + begin + { should be handled in pass_1 (JM) } + internalerror(200109052); + end + else + begin + { put numerator in register } + location_reset(location,LOC_REGISTER,OS_INT); + location_force_reg(exprasmlist,left.location,OS_INT,false); + hreg1:=left.location.register; + + if (nodetype=divn) and (right.nodetype=ordconstn) and + ispowerof2(tordconstnode(right).value,power) then + begin + { for signed numbers, the numerator must be adjusted before the + shift instruction, but not wih unsigned numbers! Otherwise, + "Cardinal($ffffffff) div 16" overflows! (JM) } + if is_signed(left.resulttype.def) Then + begin + if (aktOptProcessor <> class386) and + not(CS_LittleSize in aktglobalswitches) then + { use a sequence without jumps, saw this in + comp.compilers (JM) } + begin + { no jumps, but more operations } + hreg2:=rg.getregisterint(exprasmlist,OS_INT); + emit_reg_reg(A_MOV,S_L,hreg1,hreg2); + { if the left value is signed, hreg2 := $ffffffff, + otherwise 0 } + emit_const_reg(A_SAR,S_L,31,hreg2); + { if signed, hreg2 := right value-1, otherwise 0 } + emit_const_reg(A_AND,S_L,tordconstnode(right).value-1,hreg2); + { add to the left value } + emit_reg_reg(A_ADD,S_L,hreg2,hreg1); + { release EDX if we used it } + { also releas EDI } + rg.ungetregisterint(exprasmlist,hreg2); + { do the shift } + emit_const_reg(A_SAR,S_L,power,hreg1); + end + else + begin + { a jump, but less operations } + emit_reg_reg(A_TEST,S_L,hreg1,hreg1); + objectlibrary.getlabel(hl); + emitjmp(C_NS,hl); + if power=1 then + emit_reg(A_INC,S_L,hreg1) + else + emit_const_reg(A_ADD,S_L,tordconstnode(right).value-1,hreg1); + cg.a_label(exprasmlist,hl); + emit_const_reg(A_SAR,S_L,power,hreg1); + end + end + else + emit_const_reg(A_SHR,S_L,power,hreg1); + location.register:=hreg1; + end + else + begin + {Bring denominator to a register.} + hreg2:=rg.getregisterint(exprasmlist,OS_INT); + if right.location.loc<>LOC_CREGISTER then + location_release(exprasmlist,right.location); + cg.a_load_loc_reg(exprasmlist,right.location,hreg2); + rg.getexplicitregisterint(exprasmlist,NR_EAX); + rg.getexplicitregisterint(exprasmlist,NR_EDX); + r.enum:=R_INTREGISTER; + r.number:=NR_EAX; + r2.enum:=R_INTREGISTER; + r2.number:=NR_EDX; + emit_reg_reg(A_MOV,S_L,hreg1,r); + rg.ungetregisterint(exprasmlist,hreg1); + {Sign extension depends on the left type.} + if torddef(left.resulttype.def).typ=u32bit then + emit_reg_reg(A_XOR,S_L,r2,r2) + else + emit_none(A_CDQ,S_NO); + + {Division depends on the right type.} + if torddef(right.resulttype.def).typ=u32bit then + emit_reg(A_DIV,S_L,hreg2) + else + emit_reg(A_IDIV,S_L,hreg2); + + rg.ungetregisterint(exprasmlist,hreg2); + if nodetype=divn then + begin + rg.ungetregisterint(exprasmlist,r2); + location.register:=rg.getregisterint(exprasmlist,OS_INT); + emit_reg_reg(A_MOV,S_L,r,location.register); + rg.ungetregisterint(exprasmlist,r); + end + else + begin + rg.ungetregisterint(exprasmlist,r); + location.register:=rg.getregisterint(exprasmlist,OS_INT); + emit_reg_reg(A_MOV,S_L,r2,location.register); + rg.ungetregisterint(exprasmlist,r2); + end; + end; + end; + end; +{$else} procedure ti386moddivnode.pass_2; var hreg1 : tregister; @@ -281,6 +405,7 @@ implementation location.register:=hreg1; end; end; +{$endif} {***************************************************************************** @@ -883,7 +1008,11 @@ begin end. { $Log$ - Revision 1.45 2003-02-19 22:00:15 daniel + Revision 1.46 2003-03-08 13:59:17 daniel + * Work to handle new register notation in ag386nsm + + Added newra version of Ti386moddivnode + + Revision 1.45 2003/02/19 22:00:15 daniel * Code generator converted to new register notation - Horribily outdated todo.txt removed diff --git a/compiler/i386/rgcpu.pas b/compiler/i386/rgcpu.pas index d6ce09e5d4..acc91188ab 100644 --- a/compiler/i386/rgcpu.pas +++ b/compiler/i386/rgcpu.pas @@ -288,8 +288,10 @@ unit rgcpu; procedure trgcpu.ungetreference(list: taasmoutput; const ref : treference); begin - ungetregisterint(list,ref.base); - ungetregisterint(list,ref.index); + if ref.base.number<>NR_NO then + ungetregisterint(list,ref.base); + if ref.index.number<>NR_NO then + ungetregisterint(list,ref.index); end; @@ -515,7 +517,11 @@ end. { $Log$ - Revision 1.14 2003-03-08 08:59:07 daniel + Revision 1.15 2003-03-08 13:59:17 daniel + * Work to handle new register notation in ag386nsm + + Added newra version of Ti386moddivnode + + Revision 1.14 2003/03/08 08:59:07 daniel + $define newra will enable new register allocator + getregisterint will return imaginary registers with $newra + -sr switch added, will skip register allocation so you can see diff --git a/compiler/rgobj.pas b/compiler/rgobj.pas index e81c63f34e..6fb70bda31 100644 --- a/compiler/rgobj.pas +++ b/compiler/rgobj.pas @@ -453,8 +453,10 @@ unit rgobj; internalerror(2003010803); supreg:=r.number shr 8; { takes much time } +{$ifndef newra} if not(supreg in usableregs) then exit; +{$endif} {$ifdef TEMPREGDEBUG} if (supreg in unusedregs) then {$ifdef EXTTEMPREGDEBUG} @@ -1226,7 +1228,11 @@ end. { $Log$ - Revision 1.27 2003-03-08 10:53:48 daniel + Revision 1.28 2003-03-08 13:59:16 daniel + * Work to handle new register notation in ag386nsm + + Added newra version of Ti386moddivnode + + Revision 1.27 2003/03/08 10:53:48 daniel * Created newra version of secondmul in n386add.pas Revision 1.26 2003/03/08 08:59:07 daniel