浏览代码

+ Support for ARM CPS/CPSIE/CPSID instructions and mode flag bitfield
operand (patch by Jeppe Johansen, mantis #18334)

git-svn-id: trunk@16750 -

Jonas Maebe 14 年之前
父节点
当前提交
bbf0e35a51

+ 1 - 0
.gitattributes

@@ -10946,6 +10946,7 @@ tests/webtbs/tw1820.pp svneol=native#text/plain
 tests/webtbs/tw18222.pp svneol=native#text/pascal
 tests/webtbs/tw1825.pp svneol=native#text/plain
 tests/webtbs/tw18266.pp svneol=native#text/plain
+tests/webtbs/tw18334.pp svneol=native#text/plain
 tests/webtbs/tw18443.pp svneol=native#text/pascal
 tests/webtbs/tw1850.pp svneol=native#text/plain
 tests/webtbs/tw1851.pp svneol=native#text/plain

+ 3 - 1
compiler/aasmtai.pas

@@ -179,6 +179,7 @@ interface
        ,top_regset
        ,top_shifterop
        ,top_conditioncode
+       ,top_modeflags
 {$endif arm}
 {$ifdef m68k}
        { m68k only }
@@ -214,7 +215,8 @@ interface
       {$ifdef arm}
           top_regset : (regset:^tcpuregisterset; regtyp: tregistertype; subreg: tsubregister);
           top_shifterop : (shifterop : pshifterop);
-          top_conditioncode: (cc: TAsmCond);
+          top_conditioncode : (cc : TAsmCond);
+          top_modeflags : (modeflags : tcpumodeflags);
       {$endif arm}
       {$ifdef m68k}
           top_regset : (regset:^tcpuregisterset);

+ 31 - 0
compiler/arm/aasmcpu.pas

@@ -163,6 +163,7 @@ uses
          procedure loadshifterop(opidx:longint;const so:tshifterop);
          procedure loadregset(opidx:longint; regsetregtype: tregistertype; regsetsubregtype: tsubregister; const s:tcpuregisterset);
          procedure loadconditioncode(opidx:longint;const cond:tasmcond);
+         procedure loadmodeflags(opidx:longint;const flags:tcpumodeflags);
          constructor op_none(op : tasmop);
 
          constructor op_reg(op : tasmop;_op1 : tregister);
@@ -187,6 +188,10 @@ uses
          { ITxxx }
          constructor op_cond(op: tasmop; cond: tasmcond);
 
+         { CPSxx }
+         constructor op_modeflags(op: tasmop; flags: tcpumodeflags);
+         constructor op_modeflags_const(op: tasmop; flags: tcpumodeflags; a: aint);
+
          { *M*LL }
          constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
 
@@ -328,6 +333,17 @@ implementation
          end;
       end;
 
+    procedure taicpu.loadmodeflags(opidx: longint; const flags: tcpumodeflags);
+      begin
+        allocate_oper(opidx+1);
+        with oper[opidx]^ do
+         begin
+           if typ<>top_modeflags then
+             clearop(opidx);
+           modeflags:=flags;
+           typ:=top_modeflags;
+         end;
+      end;
 
 {*****************************************************************************
                                  taicpu Constructors
@@ -448,6 +464,21 @@ implementation
         condition := cond;
       end;
 
+    constructor taicpu.op_modeflags(op: tasmop; flags: tcpumodeflags);
+      begin
+        inherited create(op);
+        ops := 1;
+        loadmodeflags(0,flags);
+      end;
+
+    constructor taicpu.op_modeflags_const(op: tasmop; flags: tcpumodeflags; a: aint);
+      begin
+        inherited create(op);
+        ops := 2;
+        loadmodeflags(0,flags);
+        loadconst(1,a);
+      end;
+
 
      constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
        begin

+ 7 - 0
compiler/arm/agarmgas.pas

@@ -204,6 +204,13 @@ unit agarmgas;
             end;
           top_conditioncode:
             getopstr:=cond2str[o.cc];
+          top_modeflags:
+            begin
+              getopstr:='';
+              if mfA in o.modeflags then getopstr:=getopstr+'a';
+              if mfI in o.modeflags then getopstr:=getopstr+'i';
+              if mfF in o.modeflags then getopstr:=getopstr+'f';
+            end;
           top_ref:
             if o.ref^.refaddr=addr_full then
               begin

+ 3 - 0
compiler/arm/armatt.inc

@@ -23,6 +23,9 @@
 'clz',
 'cnf',
 'cos',
+'cps',
+'cpsid',
+'cpsie',
 'dvf',
 'eor',
 'exp',

+ 3 - 0
compiler/arm/armatts.inc

@@ -199,5 +199,8 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
 attsufNONE
 );

+ 4 - 0
compiler/arm/armins.dat

@@ -162,6 +162,10 @@ reg32,reg32              \x27\x01\x01                   ARM7
 
 [COScc]
 
+[CPS]
+[CPSID]
+[CPSIE]
+
 [DVFcc]
 
 [EORcc]

+ 3 - 0
compiler/arm/armop.inc

@@ -23,6 +23,9 @@ A_CMP,
 A_CLZ,
 A_CNF,
 A_COS,
+A_CPS,
+A_CPSID,
+A_CPSIE,
 A_DVF,
 A_EOR,
 A_EXP,

+ 3 - 0
compiler/arm/cpubase.pas

@@ -203,6 +203,9 @@ unit cpubase;
         shiftimm : byte;
       end;
 
+      tcpumodeflag = (mfA, mfI, mfF);
+      tcpumodeflags = set of tcpumodeflag;
+
 {*****************************************************************************
                                  Constants
 *****************************************************************************}

+ 40 - 3
compiler/arm/raarmgas.pas

@@ -672,6 +672,38 @@ Unit raarmgas;
               end;
           end;
 
+
+        function is_modeflag(hs : string): boolean;
+          var
+            i: longint;
+            flags: tcpumodeflags;
+          begin
+            is_modeflag := false;
+
+            flags:=[];
+            hs:=lower(hs);
+
+            if (actopcode in [A_CPSID,A_CPSIE]) and (length(hs) >= 1) then
+              begin
+                for i:=1 to length(hs) do
+                  begin
+                    case hs[i] of
+                      'a':
+                        Include(flags,mfA);
+                      'f':
+                        Include(flags,mfF);
+                      'i':
+                        Include(flags,mfI);
+                    else
+                      exit;
+                    end;
+                  end;
+                oper.opr.typ := OPR_MODEFLAGS;
+                oper.opr.flags := flags;
+                exit(true);
+              end;
+          end;
+
       var
         tempreg : tregister;
         ireg : tsuperregister;
@@ -716,11 +748,16 @@ Unit raarmgas;
           *)
           AS_ID: { A constant expression, or a Variable ref.  }
             Begin
+              if is_modeflag(actasmpattern) then
+                begin
+                  consume(AS_ID);
+                end
+              else
               { Condition code? }
               if is_conditioncode(actasmpattern) then
-              begin
-                consume(AS_ID);
-              end
+                begin
+                  consume(AS_ID);
+                end
               else
               { Local Label ? }
               if is_locallabel(actasmpattern) then

+ 4 - 1
compiler/rautils.pas

@@ -65,7 +65,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_REFERENCE,OPR_REGISTER,OPR_REGLIST,OPR_COND,OPR_REGSET,OPR_SHIFTEROP,OPR_MODEFLAGS);
 
   TOprRec = record
     case typ:TOprType of
@@ -88,6 +88,7 @@ type
       OPR_REGSET    : (regset : tcpuregisterset; regtype: tregistertype; subreg: tsubregister);
       OPR_SHIFTEROP : (shifterop : tshifterop);
       OPR_COND      : (cc : tasmcond);
+      OPR_MODEFLAGS : (flags : tcpumodeflags);
 {$endif arm}
   end;
 
@@ -1067,6 +1068,8 @@ end;
                 ai.loadshifterop(i-1,shifterop);
               OPR_COND:
                 ai.loadconditioncode(i-1,cc);
+              OPR_MODEFLAGS:
+                ai.loadmodeflags(i-1,flags);
 {$endif ARM}
               { ignore wrong operand }
               OPR_NONE:

+ 14 - 0
tests/webtbs/tw18334.pp

@@ -0,0 +1,14 @@
+{ %cpu=arm }
+{ %norun }
+
+procedure test; assembler;
+  asm
+    cps #0
+    cpsie aif, #0
+    cpsid aif, #0
+    cpsie aif
+    cpsid aif
+  end;
+
+begin
+end.