瀏覽代碼

* fix handling of register sets on m68k: it is required that they are stored as two tcpuregistersets because address registers and data registers have different register types

git-svn-id: trunk@25726 -
florian 11 年之前
父節點
當前提交
babbc21afd
共有 5 個文件被更改,包括 102 次插入64 次删除
  1. 8 1
      compiler/aasmtai.pas
  2. 23 18
      compiler/m68k/aasmcpu.pas
  3. 2 2
      compiler/m68k/ag68kgas.pas
  4. 63 41
      compiler/m68k/ra68kmot.pas
  5. 6 2
      compiler/rautils.pas

+ 8 - 1
compiler/aasmtai.pas

@@ -273,7 +273,7 @@ interface
           top_shifterop : (shifterop : pshifterop);
       {$endif defined(arm) or defined(aarch64)}
       {$ifdef m68k}
-          top_regset : (regset:^tcpuregisterset);
+          top_regset : (dataregset,addrregset:^tcpuregisterset);
       {$endif m68k}
       {$ifdef jvm}
           top_single : (sval:single);
@@ -2626,6 +2626,13 @@ implementation
               top_regset:
                 dispose(regset);
 {$endif ARM}
+{$ifdef m68k}
+              top_regset:
+                begin
+                  dispose(dataregset);
+                  dispose(addrregset);
+                end;
+{$endif m68k}
 {$ifdef jvm}
               top_string:
                 freemem(pcval);

+ 23 - 18
compiler/m68k/aasmcpu.pas

@@ -40,6 +40,9 @@ type
 
   taicpu = class(tai_cpu_abstract_sym)
      opsize : topsize;
+
+     procedure loadregset(opidx:longint; const dataregs,addrregs:tcpuregisterset);
+
      constructor op_none(op : tasmop);
      constructor op_none(op : tasmop;_size : topsize);
 
@@ -65,11 +68,11 @@ type
      constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; _op3 : treference);
      constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : treference);
 
-     constructor op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2: tcpuregisterset);
-     constructor op_regset_reg(op: tasmop; _size : topsize;const  _op1: tcpuregisterset; _op2: tregister);
+     constructor op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2data,_op2addr: tcpuregisterset);
+     constructor op_regset_reg(op: tasmop; _size : topsize;const _op1data,_op1addr: tcpuregisterset; _op2: tregister);
 
-     constructor op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2: tcpuregisterset);
-     constructor op_regset_ref(op: tasmop; _size : topsize;const  _op1: tcpuregisterset; _op2: treference);
+     constructor op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2data,_op2addr: tcpuregisterset);
+     constructor op_regset_ref(op: tasmop; _size : topsize;const _op1data,_op1addr: tcpuregisterset; _op2: treference);
 
      { this is for Jmp instructions }
      constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
@@ -86,7 +89,6 @@ type
      function spilling_get_operation_type(opnr: longint): topertype;override;
 
   private
-     procedure loadregset(opidx:longint;const s:tcpuregisterset);
      procedure init(_size : topsize); { this need to be called by all constructor }
   end;
 
@@ -168,7 +170,7 @@ type
 
 
 
-    procedure taicpu.loadregset(opidx:longint;const s:tcpuregisterset);
+    procedure taicpu.loadregset(opidx:longint; const dataregs,addrregs:tcpuregisterset);
       var
         i : byte;
       begin
@@ -177,17 +179,19 @@ type
          begin
            if typ<>top_regset then
              clearop(opidx);
-           new(regset);
-           regset^:=s;
+           new(dataregset);
+           new(addrregset);
+           dataregset^:=dataregs;
+           addrregset^:=addrregs;
            typ:=top_regset;
            for i:=RS_D0 to RS_D7 do
              begin
-               if assigned(add_reg_instruction_hook) and (i in regset^) then
+               if assigned(add_reg_instruction_hook) and (i in dataregset^) then
                  add_reg_instruction_hook(self,newreg(R_INTREGISTER,i,R_SUBWHOLE));
              end;
            for i:=RS_A0 to RS_SP do
              begin
-               if assigned(add_reg_instruction_hook) and (i in regset^) then
+               if assigned(add_reg_instruction_hook) and (i in addrregset^) then
                  add_reg_instruction_hook(self,newreg(R_ADDRESSREGISTER,i,R_SUBWHOLE));
              end;
          end;
@@ -377,42 +381,43 @@ type
       end;
 
 
-   constructor taicpu.op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2: tcpuregisterset);
+   constructor taicpu.op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2data,_op2addr: tcpuregisterset);
      Begin
         inherited create(op);
         init(_size);
         ops:=2;
         loadref(0,_op1);
-        loadregset(1,_op2);
+        loadregset(1,_op2data,_op2addr);
      end;
 
-   constructor taicpu.op_regset_ref(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: treference);
+
+   constructor taicpu.op_regset_ref(op: tasmop; _size : topsize;const _op1data,_op1addr: tcpuregisterset; _op2: treference);
      Begin
         inherited create(op);
         init(_size);
         ops:=2;
-        loadregset(0,_op1);
+        loadregset(0,_op1data,_op1addr);
         loadref(1,_op2);
      End;
 
 
 
-   constructor taicpu.op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2: tcpuregisterset);
+   constructor taicpu.op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2data,_op2addr: tcpuregisterset);
      Begin
         inherited create(op);
         init(_size);
         ops:=2;
         loadreg(0,_op1);
-        loadregset(1,_op2);
+        loadregset(1,_op2data,_op2addr);
      end;
 
 
-   constructor taicpu.op_regset_reg(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: tregister);
+   constructor taicpu.op_regset_reg(op: tasmop; _size : topsize;const _op1data,_op1addr: tcpuregisterset; _op2: tregister);
      Begin
         inherited create(op);
         init(_size);
         ops:=2;
-        loadregset(0,_op1);
+        loadregset(0,_op1data,_op1addr);
         loadreg(1,_op2);
      End;
 

+ 2 - 2
compiler/m68k/ag68kgas.pas

@@ -229,12 +229,12 @@ interface
               hs:='';
               for i:=RS_D0 to RS_D7 do
                 begin
-                  if i in o.regset^ then
+                  if i in o.dataregset^ then
                    hs:=hs+gas_regname(newreg(R_INTREGISTER,i,R_SUBWHOLE))+'/';
                 end;
               for i:=RS_A0 to RS_SP do
                 begin
-                  if i in o.regset^ then
+                  if i in o.addrregset^ then
                    hs:=hs+gas_regname(newreg(R_INTREGISTER,i,R_SUBWHOLE))+'/';
                 end;
               delete(hs,length(hs),1);

+ 63 - 41
compiler/m68k/ra68kmot.pas

@@ -1283,10 +1283,11 @@ const
     r:Tregister;
     hl: tasmlabel;
     reg_one, reg_two: tregister;
-    regset: tcpuregisterset;
+    addrregset,dataregset: tcpuregisterset;
     p: pointer;
   begin
-   regset := [];
+   dataregset := [];
+   addrregset := [];
    tempstr := '';
    case actasmtoken of
    { // Memory reference //  }
@@ -1477,21 +1478,28 @@ const
                    if (actasmtoken = AS_SLASH) then
                    begin
                      r:=actasmregister;
-                     if getregtype(r)<>R_INTREGISTER then
+                     if getregtype(r)=R_ADDRESSREGISTER then
+                       include(addrregset,getsupreg(r))
+                     else if getregtype(r)=R_INTREGISTER then
+                       include(dataregset,getsupreg(r))
+                     else
                        internalerror(200302191);
-                     include(regset,getsupreg(r));
                      Consume(AS_SLASH);
                      if actasmtoken = AS_REGISTER then
                      begin
                        While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
                        begin
                          case actasmtoken of
-                          AS_REGISTER: begin
-                                         if getregtype(r)<>R_INTREGISTER then
-                                           internalerror(200302191);
-                                         include(regset,getsupreg(r));
-                                         Consume(AS_REGISTER);
-                                       end;
+                          AS_REGISTER:
+                            begin
+                              if getregtype(r)=R_ADDRESSREGISTER then
+                                include(addrregset,getsupreg(r))
+                              else if getregtype(r)=R_INTREGISTER then
+                                include(dataregset,getsupreg(r))
+                              else
+                                Message(asmr_e_invalid_reg_list_in_movem);
+                              Consume(AS_REGISTER);
+                            end;
                           AS_SLASH: Consume(AS_SLASH);
                           AS_SEPARATOR,AS_COMMA: break;
                          else
@@ -1502,14 +1510,15 @@ const
                          end; { end case }
                        end; { end while }
                        oper.opr.typ:= OPR_regset;
-                       oper.opr.regset := regset;
+                       oper.opr.regsetdata := dataregset;
+                       oper.opr.regsetaddr := addrregset;
                      end
                      else
                       { error recovery ... }
                       begin
-                            Message(asmr_e_invalid_reg_list_in_movem);
-                            while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
-                               Consume(actasmtoken);
+                        Message(asmr_e_invalid_reg_list_in_movem);
+                        while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+                           Consume(actasmtoken);
                       end;
                    end
                    else
@@ -1519,34 +1528,47 @@ const
                      Consume(AS_MINUS);
                      reg_one:=actasmregister;
                      if actasmtoken <> AS_REGISTER then
-                     begin
-                       Message(asmr_e_invalid_reg_list_in_movem);
-                       while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
-                         Consume(actasmtoken);
-                     end
+                       begin
+                         Message(asmr_e_invalid_reg_list_in_movem);
+                         while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+                           Consume(actasmtoken);
+                       end
                      else
-                     begin
-                      { determine the register range ... }
-                      reg_two:=actasmregister;
-                      if getregtype(reg_two)<>R_INTREGISTER then
-                        internalerror(200302191);
-                      if getsupreg(reg_one) > getsupreg(reg_two) then
-                       for i:=getsupreg(reg_two) to getsupreg(reg_one) do
-                         include(regset,i)
-                      else
-                       for i:=getsupreg(reg_one) to getsupreg(reg_two) do
-                         include(regset,i);
-                      Consume(AS_REGISTER);
-                      if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
-                      begin
-                       Message(asmr_e_invalid_reg_list_in_movem);
-                       while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
-                         Consume(actasmtoken);
-                      end;
-                      { set up instruction }
-                      oper.opr.typ:= OPR_regset;
-                      oper.opr.regset := regset;
-                     end;
+                       begin
+                         { determine the register range ... }
+                         reg_two:=actasmregister;
+                         if getregtype(r)=R_ADDRESSREGISTER then
+                           begin
+                             if getsupreg(reg_one) > getsupreg(reg_two) then
+                               for i:=getsupreg(reg_two) to getsupreg(reg_one) do
+                                 include(addrregset,i)
+                             else
+                              for i:=getsupreg(reg_one) to getsupreg(reg_two) do
+                                include(addrregset,i);
+                           end
+                         else if getregtype(r)=R_INTREGISTER then
+                           begin
+                             if getsupreg(reg_one) > getsupreg(reg_two) then
+                               for i:=getsupreg(reg_two) to getsupreg(reg_one) do
+                                 include(dataregset,i)
+                             else
+                              for i:=getsupreg(reg_one) to getsupreg(reg_two) do
+                                include(dataregset,i);
+                           end
+                         else
+                           Message(asmr_e_invalid_reg_list_in_movem);
+                         Consume(AS_REGISTER);
+                         if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+                           begin
+                             Message(asmr_e_invalid_reg_list_in_movem);
+                             while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+                               Consume(actasmtoken);
+                           end;
+                         { set up instruction }
+                         oper.opr.typ:= OPR_regset;
+                         oper.opr.regsetdata := dataregset;
+                         oper.opr.regsetaddr := addrregset;
+                       end;
                    end
                    else
                    { DIVSL/DIVS/MULS/MULU with long for MC68020 only }

+ 6 - 2
compiler/rautils.pas

@@ -72,7 +72,7 @@ Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
 
 type
   TOprType=(OPR_NONE,OPR_CONSTANT,OPR_SYMBOL,OPR_LOCAL,
-            OPR_REFERENCE,OPR_REGISTER,OPR_REGLIST,OPR_COND,OPR_REGSET,OPR_SHIFTEROP,OPR_MODEFLAGS,OPR_SPECIALREG);
+            OPR_REFERENCE,OPR_REGISTER,OPR_COND,OPR_REGSET,OPR_SHIFTEROP,OPR_MODEFLAGS,OPR_SPECIALREG);
 
   TOprRec = record
     case typ:TOprType of
@@ -83,7 +83,7 @@ type
       OPR_LOCAL     : (localvarsize, localconstoffset: asizeint;localsym:tabstractnormalvarsym;localsymofs:aint;localindexreg:tregister;localscale:byte;localgetoffset,localforceref:boolean);
       OPR_REGISTER  : (reg:tregister);
 {$ifdef m68k}
-      OPR_REGLIST   : (regset : tcpuregisterset);
+      OPR_REGSET   : (regsetdata,regsetaddr : tcpuregisterset);
 {$endif m68k}
 {$ifdef powerpc}
       OPR_COND      : (cond : tasmcond);
@@ -1115,6 +1115,10 @@ end;
                              localscale,localgetoffset,localforceref);
               OPR_REFERENCE:
                 ai.loadref(i-1,ref);
+{$ifdef m68k}
+              OPR_REGSET:
+                ai.loadregset(i-1,regsetdata,regsetaddr);
+{$endif}
 {$ifdef ARM}
               OPR_REGSET:
                 ai.loadregset(i-1,regtype,subreg,regset,usermode);