2
0
Эх сурвалжийг харах

* Work to handle new register notation in ag386nsm
+ Added newra version of Ti386moddivnode

daniel 22 жил өмнө
parent
commit
fb55235acc

+ 11 - 2
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

+ 8 - 3
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

+ 130 - 1
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
 

+ 9 - 3
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

+ 7 - 1
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