Ver código fonte

Refactor and secure some immediate operand encodings.
Add some system mode entries, udiv/sdiv in arm mode, and fix bugs in ldrh/strh.

git-svn-id: branches/laksen/armiw@29353 -

Jeppe Johansen 10 anos atrás
pai
commit
9a482d5281

+ 45 - 47
compiler/arm/aasmcpu.pas

@@ -113,6 +113,7 @@ uses
       OT_AMMASK    = $001f0000;
       { IT instruction }
       OT_CONDITION = $00200000;
+      OT_MODEFLAGS = $00400000;
 
       OT_MEMORYAM2 = OT_MEMORY or OT_AM2;
       OT_MEMORYAM3 = OT_MEMORY or OT_AM3;
@@ -2188,6 +2189,10 @@ implementation
                 begin
                   ot:=OT_REGS;
                 end;
+              top_modeflags:
+                begin
+                  ot:=OT_MODEFLAGS;
+                end;
               else
                 begin writeln(typ);
                 internalerror(200402261); end;
@@ -2863,6 +2868,10 @@ implementation
 
               case oper[1]^.reg of
                 NR_APSR,NR_CPSR:;
+                NR_SPSR:
+                  begin
+                    bytes:=bytes or (1 shl 22);
+                  end;
               else
                 Message(asmw_e_invalid_opcode_and_operands);
               end;
@@ -2877,13 +2886,22 @@ implementation
 
               if oper[0]^.typ=top_specialreg then
                 begin
-                  if oper[0]^.specialreg<>NR_CPSR then
-                    Message1(asmw_e_invalid_opcode_and_operands, 'Can only use CPSR in this form');
-
-                  if srF in oper[0]^.specialflags then
-                    bytes:=bytes or (2 shl 18);
+                  if (oper[0]^.specialreg<>NR_CPSR) and
+                     (oper[0]^.specialreg<>NR_SPSR) then
+                    Message1(asmw_e_invalid_opcode_and_operands, '"Invalid special reg"');
+
+                  if srC in oper[0]^.specialflags then
+                    bytes:=bytes or (1 shl 16);
+                  if srX in oper[0]^.specialflags then
+                    bytes:=bytes or (1 shl 17);
                   if srS in oper[0]^.specialflags then
                     bytes:=bytes or (1 shl 18);
+                  if srF in oper[0]^.specialflags then
+                    bytes:=bytes or (1 shl 19);
+
+                  { Set R bit }
+                  if oper[0]^.specialreg=NR_SPSR then
+                    bytes:=bytes or (1 shl 22);
                 end
               else
                 case oper[0]^.reg of
@@ -3002,16 +3020,11 @@ implementation
                     offset:=currsym.offset-insoffset-8;
                   offset:=offset+oper[1]^.ref^.offset;
                   if offset>=0 then
-                    begin
-                      { set U flag }
-                      bytes:=bytes or (1 shl 23);
-                      bytes:=bytes or offset
-                    end
+                    { set U flag }
+                    bytes:=bytes or (1 shl 23)
                   else
-                    begin
-                      offset:=-offset;
-                      bytes:=bytes or offset
-                    end;
+                    offset:=-offset;
+                  bytes:=bytes or (offset and $FFF);
                 end
               else
                 begin
@@ -3090,18 +3103,12 @@ implementation
                     offset:=currsym.offset-insoffset-8;
                   offset:=offset+refoper^.ref^.offset;
                   if offset>=0 then
-                    begin
-                      { set U flag }
-                      bytes:=bytes or (1 shl 23);
-                      bytes:=bytes or (offset and $F);
-                      bytes:=bytes or ((offset and $F0) shl 4);
-                    end
+                    { set U flag }
+                    bytes:=bytes or (1 shl 23)
                   else
-                    begin
-                      offset:=-offset;
-                      bytes:=bytes or (offset and $F);
-                      bytes:=bytes or ((offset and $F0) shl 4);
-                    end;
+                    offset:=-offset;
+                  bytes:=bytes or (offset and $F);
+                  bytes:=bytes or ((offset and $F0) shl 4);
                 end
               else
                 begin
@@ -3197,19 +3204,14 @@ implementation
                   if assigned(currsym) then
                     offset:=currsym.offset-insoffset-8;
                   offset:=offset+refoper^.ref^.offset;
+
                   if offset>=0 then
-                    begin
-                      { set U flag }
-                      bytes:=bytes or (1 shl 23);
-                      bytes:=bytes or (offset and $F);
-                      bytes:=bytes or ((offset and $F0) shl 4);
-                    end
+                    { set U flag }
+                    bytes:=bytes or (1 shl 23)
                   else
-                    begin
-                      offset:=-offset;
-                      bytes:=bytes or (offset and $F);
-                      bytes:=bytes or ((offset and $F0) shl 4);
-                    end;
+                    offset:=-offset;
+                  bytes:=bytes or (offset and $F);
+                  bytes:=bytes or ((offset and $F0) shl 4);
                 end
               else
                 begin
@@ -3231,18 +3233,14 @@ implementation
               if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
                 begin
                   bytes:=bytes or (1 shl 22); // with immediate offset
-                  if oper[1]^.ref^.offset < 0 then
-                    begin
-                      bytes:=bytes or ((-oper[1]^.ref^.offset) and $f0 shl 4);
-                      bytes:=bytes or ((-oper[1]^.ref^.offset) and $f);
-                    end
+                  offset:=oper[1]^.ref^.offset;
+                  if offset>=0 then
+                    { set U flag }
+                    bytes:=bytes or (1 shl 23)
                   else
-                    begin
-                      { set U bit }
-                      bytes:=bytes or (1 shl 23);
-                      bytes:=bytes or (oper[1]^.ref^.offset and $f0 shl 4);
-                      bytes:=bytes or (oper[1]^.ref^.offset and $f);
-                    end;
+                    offset:=-offset;
+                  bytes:=bytes or (offset and $F);
+                  bytes:=bytes or ((offset and $F0) shl 4);
                 end
               else
                 begin

+ 10 - 3
compiler/arm/armins.dat

@@ -375,9 +375,9 @@ reg32,immshifter        \xB\x1\xA0                       ARM32,ARMv4
 reg32,regf          \x10\x01\x0F                        ARM32,ARMv4
 
 [MSRcc]
-regf,reg32          \x12\x01\x28\xF0                    ARM32,ARMv4
-regf,immshifter     \x13\x03\x28\xF0                    ARM32,ARMv4
-regs,immshifter     \x13\x03\x28\xF0                    ARM32,ARMv4
+regf,reg32          \x12\x01\x20\xF0                    ARM32,ARMv4
+regf,immshifter     \x13\x03\x20\xF0                    ARM32,ARMv4
+regs,immshifter     \x13\x03\x20\xF0                    ARM32,ARMv4
 
 [MULcc]
 reglo,reglo            \x64\x43\x40              THUMB,ARMv4T
@@ -647,8 +647,12 @@ reg32,reg32,reg32,reg32     \x16\x01\x40\xA                     ARM32,ARMv5TE
 reg32,reg32,reg32,reg32     \x16\x01\x40\xE                     ARM32,ARMv5TE
 
 [SMLAWBcc]
+reg32,reg32,reg32,reg32    \x80\xFB\x30\x0\x00                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x1\x20\x8                      ARM32,ARMv5TE
 
 [SMLAWTcc]
+reg32,reg32,reg32,reg32    \x80\xFB\x30\x0\x10                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x1\x20\xC                      ARM32,ARMv5TE
 
 [VLDMcc]
 memam4,reglist		      \x44\xC\x10\xA		         ARM32,VFPv2
@@ -1331,9 +1335,11 @@ reglist		                  \x26\x80		               ARM32,ARMv4
 
 [SDIVcc]
 reg32,reg32,reg32             \x80\xFB\x90\xF0\xF0       THUMB32,ARMv7R,ARMv7M
+reg32,reg32,reg32             \x15\x07\x10\x01\xF        ARM32,ARMv7
 
 [UDIVcc]
 reg32,reg32,reg32             \x80\xFB\xB0\xF0\xF0       THUMB32,ARMv7R,ARMv7M
+reg32,reg32,reg32             \x15\x07\x30\x01\xF        ARM32,ARMv7
 
 [MOVTcc]
 reg32,imm                     \x81\xF2\xC0\x0\x0         THUMB32,ARMv6T2
@@ -1501,6 +1507,7 @@ immshifter        \x2E\xF5\x7F\xF0\x40             ARM32,ARMv7
 
 [SMC]
 immshifter        \x2E\x01\x60\x00\x70             ARM32,ARMv7
+imm32             \x2E\x01\x60\x00\x70             ARM32,ARMv7
 
 ; Thumb armv6-m (gcc)
 [NEG]

+ 1 - 1
compiler/arm/armnop.inc

@@ -1,2 +1,2 @@
 { don't edit, this file is generated from armins.dat }
-703;
+710;

+ 52 - 3
compiler/arm/armtab.inc

@@ -1187,21 +1187,21 @@
     opcode  : A_MSR;
     ops     : 2;
     optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
-    code    : #18#1#40#240;
+    code    : #18#1#32#240;
     flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_MSR;
     ops     : 2;
     optypes : (ot_regf,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
-    code    : #19#3#40#240;
+    code    : #19#3#32#240;
     flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_MSR;
     ops     : 2;
     optypes : (ot_regs,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
-    code    : #19#3#40#240;
+    code    : #19#3#32#240;
     flags   : if_arm32 or if_armv4
   ),
   (
@@ -2310,6 +2310,34 @@
     code    : #22#1#64#14;
     flags   : if_arm32 or if_armv5te
   ),
+  (
+    opcode  : A_SMLAWB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#48#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLAWB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#32#8;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLAWT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#48#0#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLAWT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#32#12;
+    flags   : if_arm32 or if_armv5te
+  ),
   (
     opcode  : A_VLDM;
     ops     : 2;
@@ -4354,6 +4382,13 @@
     code    : #128#251#144#240#240;
     flags   : if_thumb32 or if_armv7r or if_armv7m
   ),
+  (
+    opcode  : A_SDIV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#16#1#15;
+    flags   : if_arm32 or if_armv7
+  ),
   (
     opcode  : A_UDIV;
     ops     : 3;
@@ -4361,6 +4396,13 @@
     code    : #128#251#176#240#240;
     flags   : if_thumb32 or if_armv7r or if_armv7m
   ),
+  (
+    opcode  : A_UDIV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#48#1#15;
+    flags   : if_arm32 or if_armv7
+  ),
   (
     opcode  : A_MOVT;
     ops     : 2;
@@ -4872,6 +4914,13 @@
     code    : #46#1#96#0#112;
     flags   : if_arm32 or if_armv7
   ),
+  (
+    opcode  : A_SMC;
+    ops     : 1;
+    optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #46#1#96#0#112;
+    flags   : if_arm32 or if_armv7
+  ),
   (
     opcode  : A_SVC;
     ops     : 1;

+ 1 - 0
compiler/arm/raarmgas.pas

@@ -1190,6 +1190,7 @@ Unit raarmgas;
                   ((operandnum=3) and not(instr.opcode in [A_UMLAL,A_UMULL,A_SMLAL,A_SMULL,A_MLA,A_UMAAL,A_MLS,
                                                            A_SMLABB,A_SMLABT,A_SMLATB,A_SMLATT,A_SMMLA,A_SMMLS,A_SMLAD,A_SMLALD,A_SMLSD,
                                                            A_SMLALBB,A_SMLALBT,A_SMLALTB,A_SMLALTT,A_SMLSLD,
+                                                           A_SMLAWB,A_SMLAWT,
                                                            A_MRC,A_MCR,A_MCRR,A_MRRC,A_MRC2,A_MCR2,A_MCRR2,A_MRRC2,
                                                            A_STREXD,A_STRD,
                                                            A_USADA8,