Преглед изворни кода

+ preparations for returning int64 in ax:bx:cx:dx on i8086

git-svn-id: trunk@24498 -
nickysn пре 12 година
родитељ
комит
6b2f59c3e0
4 измењених фајлова са 66 додато и 4 уклоњено
  1. 24 0
      compiler/i8086/cpubase.inc
  2. 18 2
      compiler/i8086/cpupara.pas
  3. 14 2
      compiler/paramgr.pas
  4. 10 0
      compiler/x86/cpubase.pas

+ 24 - 0
compiler/i8086/cpubase.inc

@@ -106,6 +106,18 @@
       { High part of 32bit return value }
       NR_FUNCTION_RETURN32_HIGH_REG = NR_DX;
       RS_FUNCTION_RETURN32_HIGH_REG = RS_DX;
+      { Bits 0..15 of 64bit return value }
+      NR_FUNCTION_RETURN64_LOW_REG = NR_DX;
+      RS_FUNCTION_RETURN64_LOW_REG = RS_DX;
+      { Bits 16..31 of 64bit return value }
+      NR_FUNCTION_RETURN64_HIGH_REG = NR_CX;
+      RS_FUNCTION_RETURN64_HIGH_REG = RS_CX;
+      { Bits 32..47 of 64bit return value }
+      NR_FUNCTION_RETURN64_HIGHER_REG = NR_BX;
+      RS_FUNCTION_RETURN64_HIGHER_REG = RS_BX;
+      { Bits 48..63 of 64bit return value }
+      NR_FUNCTION_RETURN64_HIGHEST_REG = NR_AX;
+      RS_FUNCTION_RETURN64_HIGHEST_REG = RS_AX;
       { The value returned from a function is available in this register }
       NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
       RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
@@ -115,6 +127,18 @@
       { The high part of 32bit value returned from a function }
       NR_FUNCTION_RESULT32_HIGH_REG = NR_FUNCTION_RETURN32_HIGH_REG;
       RS_FUNCTION_RESULT32_HIGH_REG = RS_FUNCTION_RETURN32_HIGH_REG;
+      { Bits 0..15 of 64bit return value returned from a function }
+      NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
+      RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
+      { Bits 16..31 of 64bit return value returned from a function }
+      NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
+      RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
+      { Bits 32..47 of 64bit return value returned from a function }
+      NR_FUNCTION_RESULT64_HIGHER_REG = NR_FUNCTION_RETURN64_HIGHER_REG;
+      RS_FUNCTION_RESULT64_HIGHER_REG = RS_FUNCTION_RETURN64_HIGHER_REG;
+      { Bits 48..63 of 64bit return value returned from a function }
+      NR_FUNCTION_RESULT64_HIGHEST_REG = NR_FUNCTION_RETURN64_HIGHEST_REG;
+      RS_FUNCTION_RESULT64_HIGHEST_REG = RS_FUNCTION_RETURN64_HIGHEST_REG;
 
       { WARNING: don't change to R_ST0!! See comments above implementation of }
       { a_loadfpu* methods in rgcpu (JM)                                      }

+ 18 - 2
compiler/i8086/cpupara.pas

@@ -330,8 +330,24 @@ unit cpupara;
             paraloc:=result.add_location;
             paraloc^.loc:=LOC_REGISTER;
             if retcgsize in [OS_64,OS_S64] then
-              internalerror(2013031201);
-            if retcgsize in [OS_32,OS_S32] then
+             begin
+               { low 32bits }
+               if side=callerside then
+                 paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
+               else
+                 paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
+               paraloc^.size:=OS_32;
+
+               { high 32bits }
+               paraloc:=result.add_location;
+               paraloc^.loc:=LOC_REGISTER;
+               if side=callerside then
+                 paraloc^.register:=NR_FUNCTION_RESULT64_HIGHER_REG
+               else
+                 paraloc^.register:=NR_FUNCTION_RETURN64_HIGHER_REG;
+               paraloc^.size:=OS_32;
+             end
+            else if retcgsize in [OS_32,OS_S32] then
              begin
                { low 16bits }
                if side=callerside then

+ 14 - 2
compiler/paramgr.pas

@@ -278,7 +278,13 @@ implementation
           LOC_CREGISTER:
             begin
               if getsupreg(paraloc^.register)<first_int_imreg then
-                cg.getcpuregister(list,paraloc^.register);
+                begin
+                  cg.getcpuregister(list,paraloc^.register);
+{$ifdef cpu16bitalu}
+                  if paraloc^.Size in [OS_32, OS_S32] then
+                    cg.getcpuregister(list,GetNextReg(paraloc^.register));
+{$endif cpu16bitalu}
+                end;
             end;
 {$ifndef x86}
 { don't allocate ST(x), they're not handled by the register allocator }
@@ -327,7 +333,13 @@ implementation
               LOC_CREGISTER:
                 begin
                   if getsupreg(paraloc^.register)<first_int_imreg then
-                    cg.ungetcpuregister(list,paraloc^.register);
+                    begin
+                      cg.ungetcpuregister(list,paraloc^.register);
+{$ifdef cpu16bitalu}
+                      if paraloc^.Size in [OS_32, OS_S32] then
+                        cg.ungetcpuregister(list,GetNextReg(paraloc^.register));
+{$endif cpu16bitalu}
+                    end;
                 end;
               LOC_FPUREGISTER,
               LOC_CFPUREGISTER:

+ 10 - 0
compiler/x86/cpubase.pas

@@ -556,6 +556,16 @@ implementation
 {$ifdef i8086}
     function GetNextReg(const r: TRegister): TRegister;
       begin
+        { HACK for returning 64-bit values in registers ax:bx:cx:dx }
+        case r of
+          NR_FUNCTION_RESULT64_LOW_REG: exit(NR_FUNCTION_RESULT64_HIGH_REG);
+          NR_FUNCTION_RESULT64_HIGHER_REG: exit(NR_FUNCTION_RESULT64_HIGHEST_REG);
+        end;
+        case r of
+          NR_FUNCTION_RETURN64_LOW_REG: exit(NR_FUNCTION_RETURN64_HIGH_REG);
+          NR_FUNCTION_RETURN64_HIGHER_REG: exit(NR_FUNCTION_RETURN64_HIGHEST_REG);
+        end;
+
         if getsupreg(r)<first_int_imreg then
           internalerror(2013051401);
         result:=TRegister(longint(r)+1);