浏览代码

+ Missing part of internal ARM assembler, Mantis #26588. I'm not setting it as default for arm-wince yet, because testing reveals several points in generic code that need adjustments.

git-svn-id: trunk@29588 -
sergei 10 年之前
父节点
当前提交
9cc0bdd6b9
共有 5 个文件被更改,包括 456 次插入236 次删除
  1. 279 16
      compiler/arm/aasmcpu.pas
  2. 73 67
      compiler/arm/armins.dat
  3. 1 1
      compiler/arm/armnop.inc
  4. 97 146
      compiler/arm/armtab.inc
  5. 6 6
      compiler/ogcoff.pas

+ 279 - 16
compiler/arm/aasmcpu.pas

@@ -1596,6 +1596,12 @@ implementation
                      s:=s+' am2 ';
                  end
                else
+                 if (ot and OT_SHIFTEROP)=OT_SHIFTEROP then
+                  begin
+                    s:=s+'shifterop';
+                    addsize:=false;
+                  end
+                else
                  s:=s+'???';
                { size }
                if addsize then
@@ -1867,6 +1873,8 @@ implementation
                 begin
                   ot:=OT_SHIFTEROP;
                 end;
+              top_conditioncode:
+                ot:=OT_CONDITION;
               else
                 internalerror(2004022623);
             end;
@@ -1900,7 +1908,6 @@ implementation
         {siz : array[0..3] of longint;}
       begin
         Matches:=100;
-        writeln(getstring,'---');
 
         { Check the opcode and operands }
         if (p^.opcode<>opcode) or (p^.ops<>ops) then
@@ -1942,7 +1949,7 @@ implementation
         { update condition flags
           or floating point single }
       if (oppostfix=PF_S) and
-        not(p^.code[0] in [#$04]) then
+        not(p^.code[0] in [#$04..#$0B]) then
         begin
           Matches:=0;
           exit;
@@ -2113,61 +2120,317 @@ implementation
 
 
     procedure taicpu.gencode(objdata:TObjData);
+      const
+        CondVal : array[TAsmCond] of byte=(
+         $E, $0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $A,
+         $B, $C, $D, $E, 0);
       var
         bytes : dword;
         i_field : byte;
+        currsym : TObjSymbol;
+        offset : longint;
 
       procedure setshifterop(op : byte);
+        var
+          r : byte;
+          imm : dword;
         begin
           case oper[op]^.typ of
             top_const:
               begin
                 i_field:=1;
-                bytes:=bytes or dword(oper[op]^.val and $fff);
+                if oper[op]^.val and $ff=oper[op]^.val then
+                  bytes:=bytes or dword(oper[op]^.val)
+                else
+                  begin
+                    { calc rotate and adjust imm }
+                    r:=0;
+                    imm:=dword(oper[op]^.val);
+                    repeat
+                      imm:=RolDWord(imm, 2);
+                      inc(r)
+                    until imm and $ff=imm;
+                    bytes:=bytes or (r shl 8) or imm;
+                  end;
               end;
             top_reg:
               begin
                 i_field:=0;
-                bytes:=bytes or (getsupreg(oper[op]^.reg) shl 16);
+                bytes:=bytes or getsupreg(oper[op]^.reg);
 
                 { does a real shifter op follow? }
-                if (op+1<=op) and (oper[op+1]^.typ=top_shifterop) then
-                  begin
-                  end;
+                if (op+1<opercnt) and (oper[op+1]^.typ=top_shifterop) then
+                  with oper[op+1]^.shifterop^ do
+                    begin
+                      bytes:=bytes or (shiftimm shl 7);
+                      if shiftmode<>SM_RRX then
+                        bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
+                      else
+                        bytes:=bytes or (3 shl 5);
+                      if getregtype(rs) <> R_INVALIDREGISTER then
+                        begin
+                          bytes:=bytes or (1 shl 4);
+                          bytes:=bytes or (getsupreg(rs) shl 8);
+                        end
+                    end;
               end;
           else
             internalerror(2005091103);
           end;
         end;
 
+      function MakeRegList(reglist: tcpuregisterset): word;
+        var
+          i, w: word;
+        begin
+          result:=0;
+          w:=1;
+          for i:=RS_R0 to RS_R15 do
+            begin
+              if i in reglist then
+                result:=result or w;
+              w:=w shl 1
+            end;
+        end;
+
       begin
         bytes:=$0;
         i_field:=0;
         { evaluate and set condition code }
+        bytes:=bytes or (CondVal[condition] shl 28);
 
         { condition code allowed? }
 
         { setup rest of the instruction }
         case insentry^.code[0] of
-          #$08:
+          #$01: // B/BL
             begin
               { set instruction code }
-              bytes:=bytes or (ord(insentry^.code[1]) shl 26);
-              bytes:=bytes or (ord(insentry^.code[2]) shl 21);
-
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              { set offset }
+              currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
+              if (currsym.bind<>AB_LOCAL) and (currsym.objsection<>objdata.CurrObjSec) then
+                objdata.writereloc(oper[0]^.ref^.offset,0,currsym,RELOC_RELATIVE_24)
+              else
+                bytes:=bytes or (((currsym.offset-insoffset-8) shr 2) and $ffffff);
+            end;
+          #$04..#$07: // SUB
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              { set destination }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+              { set Rn }
+              bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+              { create shifter op }
+              setshifterop(2);
+              { set I field }
+              bytes:=bytes or (i_field shl 25);
+              { set S if necessary }
+              if oppostfix=PF_S then
+                bytes:=bytes or (1 shl 20);
+            end;
+          #$08,#$0A,#$0B: // MOV
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
               { set destination }
               bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
-
               { create shifter op }
               setshifterop(1);
-
-              { set i field }
+              { set I field }
               bytes:=bytes or (i_field shl 25);
-
-              { set s if necessary }
+              { set S if necessary }
               if oppostfix=PF_S then
                 bytes:=bytes or (1 shl 20);
             end;
+          #$0C,#$0E,#$0F: // CMP
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              { set destination }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+              { create shifter op }
+              setshifterop(1);
+              { set I field }
+              bytes:=bytes or (i_field shl 25);
+              { always set S bit }
+              bytes:=bytes or (1 shl 20);
+            end;
+          #$14: // MUL/MLA r1,r2,r3
+            begin
+              { set instruction code }
+              bytes:=bytes or ord(insentry^.code[1]) shl 24;
+              bytes:=bytes or ord(insentry^.code[2]) shl 16;
+              bytes:=bytes or ord(insentry^.code[3]);
+              { set regs }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 16;
+              bytes:=bytes or getsupreg(oper[1]^.reg);
+              bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
+            end;
+          #$15: // MUL/MLA r1,r2,r3,r4
+            begin
+              { set instruction code }
+              bytes:=bytes or ord(insentry^.code[1]) shl 24;
+              bytes:=bytes or ord(insentry^.code[2]) shl 16;
+              bytes:=bytes or ord(insentry^.code[3]);
+              { set regs }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 16;
+              bytes:=bytes or getsupreg(oper[1]^.reg);
+              bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
+              bytes:=bytes or getsupreg(oper[3]^.reg) shl 12;
+            end;
+          #$16: // MULL r1,r2,r3,r4
+            begin
+              { set instruction code }
+              bytes:=bytes or ord(insentry^.code[1]) shl 24;
+              bytes:=bytes or ord(insentry^.code[2]) shl 16;
+              bytes:=bytes or ord(insentry^.code[3]);
+              { set regs }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+              bytes:=bytes or getsupreg(oper[1]^.reg) shl 16;
+              bytes:=bytes or getsupreg(oper[2]^.reg);
+              bytes:=bytes or getsupreg(oper[3]^.reg) shl 8;
+            end;
+          #$17: // LDR/STR
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              { set Rn and Rd }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+              bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+              if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
+                begin
+                  { set offset }
+                  offset:=0;
+                  currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+                  if assigned(currsym) then
+                    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
+                  else
+                    begin
+                      offset:=-offset;
+                      bytes:=bytes or offset
+                    end;
+                end
+              else
+                begin
+                  { set U flag }
+                  if oper[1]^.ref^.signindex>0 then
+                    bytes:=bytes or (1 shl 23);
+                  { set I flag }
+                  bytes:=bytes or (1 shl 25);
+                  bytes:=bytes or getsupreg(oper[1]^.ref^.index);
+                  { set shift }
+                  with oper[1]^.ref^ do
+                    if shiftmode<>SM_None then
+                      begin
+                        bytes:=bytes or (shiftimm shl 7);
+                        if shiftmode<>SM_RRX then
+                          bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
+                        else
+                          bytes:=bytes or (3 shl 5);
+                      end
+                end;
+              { set W bit }
+              if oper[1]^.ref^.addressmode=AM_PREINDEXED then
+                bytes:=bytes or (1 shl 21);
+              { set P bit if necessary }
+              if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
+                bytes:=bytes or (1 shl 24);
+            end;
+          #$22: // LDRH/STRH
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 16);
+              bytes:=bytes or ord(insentry^.code[2]);
+              { src/dest register (Rd) }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+              { base register (Rn) }
+              bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+              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
+                  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;
+                end
+              else
+                begin
+                  { set U flag }
+                  bytes:=bytes or (1 shl 23);
+                  bytes:=bytes or getsupreg(oper[1]^.ref^.index);
+                end;
+              { set W bit }
+              if oper[1]^.ref^.addressmode=AM_PREINDEXED then
+                bytes:=bytes or (1 shl 21);
+              { set P bit if necessary }
+              if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
+                bytes:=bytes or (1 shl 24);
+            end;
+          #$26: // LDM/STM
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 20);
+              if oper[0]^.typ=top_ref then
+                begin
+                  { set W bit }
+                  if oper[0]^.ref^.addressmode=AM_PREINDEXED then
+                    bytes:=bytes or (1 shl 21);
+                  { set Rn }
+                  bytes:=bytes or (getsupreg(oper[0]^.ref^.index) shl 16);
+                end
+              else { typ=top_reg }
+                begin
+                  { set Rn }
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+                end;
+              { reglist }
+              bytes:=bytes or MakeRegList(oper[1]^.regset^);
+              { set P bit }
+              if (opcode=A_LDM) and (oppostfix in [PF_ED,PF_EA,PF_IB,PF_DB])
+              or (opcode=A_STM) and (oppostfix in [PF_FA,PF_FD,PF_IB,PF_DB]) then
+                bytes:=bytes or (1 shl 24);
+              { set U bit }
+              if (opcode=A_LDM) and (oppostfix in [PF_ED,PF_FD,PF_IB,PF_IA])
+              or (opcode=A_STM) and (oppostfix in [PF_FA,PF_EA,PF_IB,PF_IA]) then
+                bytes:=bytes or (1 shl 23);
+            end;
+          #$27: // SWP/SWPB
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 20);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 4);
+              { set regs }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+              bytes:=bytes or getsupreg(oper[1]^.reg);
+              bytes:=bytes or (getsupreg(oper[2]^.ref^.base) shl 16);
+            end;
+          #$03:  // BX
+            begin
+              writeln(objdata.CurrObjSec.fullname);
+              Comment(v_warning,'BX instruction');
+              // TBD
+            end;
           #$ff:
             internalerror(2005091101);
           else

+ 73 - 67
compiler/arm/armins.dat

@@ -97,33 +97,34 @@ void                  void                            none
 reg32,reg32,reg32        \4\x0\xA0                     ARM7
 reg32,reg32,reg32,reg32  \5\x0\xA0                     ARM7
 reg32,reg32,reg32,imm    \6\x0\xA0                     ARM7
-reg32,reg32,imm          \7\x2\xA0                     ARM7
+reg32,reg32,immshifter   \7\x2\xA0                     ARM7
 
 [ADDcc]
-reg32,reg32,reg32        \4\x0\x80                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\x80                     ARM7
-reg32,reg32,reg32,imm    \6\x0\x80                     ARM7
-reg32,reg32,imm          \7\x2\x80                     ARM7
+reg32,reg32,reg32           \4\x0\x80                  ARM7
+reg32,reg32,reg32,reg32     \5\x0\x80                  ARM7
+reg32,reg32,reg32,shifterop \6\x0\x80                  ARM7
+reg32,reg32,immshifter      \7\x2\x80                  ARM7
 
 [ADFcc]
 
 [ADRcc]
 
 [ANDcc]
-reg32,reg32,reg32        \4\x0\x00                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\x00                     ARM7
-reg32,reg32,reg32,imm    \6\x0\x00                     ARM7
-reg32,reg32,imm          \7\x2\x00                     ARM7
+reg32,reg32,reg32           \4\x0\x00                  ARM7
+;reg32,reg32,reg32,reg32    \5\x0\x00                  ARM7
+;reg32,reg32,reg32,imm      \6\x0\x00                  ARM7
+reg32,reg32,reg32,shifterop \6\x0\x00                  ARM7
+reg32,reg32,immshifter      \7\x2\x00                  ARM7
 
 [Bcc]
 mem32                    \1\x0A                        ARM7
 imm24                    \1\x0A                        ARM7
 
 [BICcc]
-reg32,reg32,reg32        \4\x1\xC0                     ARM7
-reg32,reg32,reg32,reg32  \5\x1\xC0                     ARM7
-reg32,reg32,reg32,imm    \6\x1\xC0                     ARM7
-reg32,reg32,imm          \7\x3\xC0                     ARM7
+;reg32,reg32,reg32        \4\x1\xC0                     ARM7
+;reg32,reg32,reg32,reg32  \5\x1\xC0                     ARM7
+;reg32,reg32,reg32,imm    \6\x1\xC0                     ARM7
+reg32,reg32,immshifter    \7\x3\xC0                     ARM7
 
 [BLcc]
 mem32                    \1\x0B                        ARM7
@@ -149,13 +150,13 @@ reg8,reg8           \300\1\x10\101                ARM7
 reg32,reg32              \xC\x1\x60                     ARM7
 reg32,reg32,reg32        \xD\x1\x60                     ARM7
 reg32,reg32,imm          \xE\x1\x60                     ARM7
-reg32,imm                \xF\x3\x60                     ARM7
+reg32,immshifter         \xF\x1\x60                     ARM7
 
 [CMPcc]
 reg32,reg32              \xC\x1\x40                     ARM7
 reg32,reg32,reg32        \xD\x1\x40                     ARM7
-reg32,reg32,imm          \xE\x1\x40                     ARM7
-reg32,imm                \xF\x3\x40                     ARM7
+reg32,reg32,shifterop    \xE\x1\x40                     ARM7
+reg32,immshifter         \xF\x3\x40                     ARM7
 
 [CLZcc]
 reg32,reg32              \x27\x01\x01                   ARM7
@@ -171,10 +172,11 @@ reg32,reg32              \x27\x01\x01                   ARM7
 [DVFcc]
 
 [EORcc]
-reg32,reg32,reg32        \4\x0\x20                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\x20                     ARM7
-reg32,reg32,reg32,imm    \6\x0\x20                     ARM7
-reg32,reg32,imm          \7\x2\x20                     ARM7
+reg32,reg32,reg32           \4\x0\x20                     ARM7
+;reg32,reg32,reg32,reg32     \5\x0\x20                     ARM7
+;reg32,reg32,reg32,imm       \6\x0\x20                     ARM7
+reg32,reg32,reg32,shifterop \6\x0\x20                     ARM7
+reg32,reg32,immshifter      \7\x2\x20                     ARM7
 
 [EXPcc]
 
@@ -193,14 +195,15 @@ reg32,reg32         \321\300\1\x11\101            ARM7
 
 [LDMcc]
 memam4,reglist		   \x26\x81			ARM7
+reg32,reglist		   \x26\x81			ARM7
 
 [LDRBTcc]
 
 [LDRBcc]
-reg32,memam2              \x17\x07\x10                            ARM7
+reg32,memam2              \x17\x04\x50                            ARM7
 
 [LDRcc]
-reg32,memam2              \x17\x05\x10                   ARM7
+reg32,memam2              \x17\x04\x10                   ARM7
 ; reg32,imm32              \x17\x05\x10                   ARM7
 ; reg32,reg32              \x18\x04\x10                   ARM7
 ; reg32,reg32,imm32        \x19\x04\x10                   ARM7
@@ -208,22 +211,24 @@ reg32,memam2              \x17\x05\x10                   ARM7
 ; reg32,reg32,reg32,imm32  \x21\x06\x10                   ARM7
 
 [LDRHcc]
-reg32,imm32              \x22\x50\xB0               ARM7
-reg32,reg32              \x23\x50\xB0               ARM7
-reg32,reg32,imm32        \x24\x50\xB0                   ARM7
-reg32,reg32,reg32        \x25\x10\xB0                   ARM7
+reg32,memam2              \x22\x10\xB0               ARM7
+;reg32,imm32              \x22\x50\xB0               ARM7
+;reg32,reg32              \x23\x50\xB0               ARM7
+;reg32,reg32,imm32        \x24\x50\xB0                   ARM7
+;reg32,reg32,reg32        \x25\x10\xB0                   ARM7
 
 [LDRSBcc]
-reg32,imm32              \x22\x50\xD0               ARM7
+reg32,memam2             \x22\x10\xD0               ARM7
 reg32,reg32              \x23\x50\xD0               ARM7
 reg32,reg32,imm32        \x24\x50\xD0                   ARM7
 reg32,reg32,reg32        \x25\x10\xD0                   ARM7
 
 [LDRSHcc]
-reg32,imm32              \x22\x50\xF0               ARM7
-reg32,reg32              \x23\x50\xF0               ARM7
-reg32,reg32,imm32        \x24\x50\xF0                   ARM7
-reg32,reg32,reg32        \x25\x10\xF0                   ARM7
+reg32,memam2              \x22\x10\xF0               ARM7
+;reg32,imm32              \x22\x50\xF0               ARM7
+;reg32,reg32              \x23\x50\xF0               ARM7
+;reg32,reg32,imm32        \x24\x50\xF0                   ARM7
+;reg32,reg32,reg32        \x25\x10\xF0                   ARM7
 
 [LDRTcc]
 
@@ -243,11 +248,10 @@ reg32,imm8,fpureg        \xF0\x02\x01                   FPA
 reg32,reg32,reg32,reg32  \x15\x00\x20\x90               ARM7
 
 [MOVcc]
-; reg32,shifterop              \x8\x0\0xd                   ARM7
-; reg32,immshifter             \x8\x0\0xd                  ARM7
-; reg32,reg32,reg32        \x9\x1\xA0                     ARM7
-; reg32,reg32,imm          \xA\x1\xA0                     ARM7
-; reg32,imm                \xB\x3\xA0                     ARM7
+reg32,shifterop        \x8\x1\xA0                       ARM7
+; reg32,reg32,reg32    \x9\x1\xA0                       ARM7
+reg32,reg32,shifterop  \xA\x1\xA0                       ARM7
+reg32,immshifter       \xB\x1\xA0                       ARM7
 
 [MRC]
 ; reg32,reg32         \321\301\1\x13\110                  ARM7
@@ -272,18 +276,18 @@ fpureg,fpureg              \xF2                      FPA
 fpureg,immfpu              \xF2                      FPA
 
 [MVNcc]
-; reg32,reg32         \x8\x0\0xf                     ARM7
-; reg32,reg32,reg32   \x9\x1\xE0                     ARM7
-; reg32,reg32,imm     \xA\x1\xE0                     ARM7
-; reg32,imm           \xB\x3\xE0                     ARM7
+reg32,reg32            \x8\x1\xE0                       ARM7
+; reg32,reg32,reg32    \x9\x1\xE0                       ARM7
+reg32,reg32,shifterop  \xA\x1\xE0                       ARM7
+reg32,immshifter       \xB\x1\xE0                       ARM7
 
 [NOP]
 
 [ORRcc]
-reg32,reg32,reg32        \4\x1\x80                     ARM7
-reg32,reg32,reg32,reg32  \5\x1\x80                     ARM7
-reg32,reg32,reg32,imm    \6\x1\x80                     ARM7
-reg32,reg32,imm          \7\x3\x80                     ARM7
+reg32,reg32,reg32            \4\x1\x80               ARM7
+reg32,reg32,reg32,reg32      \5\x1\x80               ARM7
+reg32,reg32,reg32,shifterop  \6\x1\x80               ARM7
+reg32,reg32,immshifter       \7\x3\x80               ARM7
 
 [RDFcc]
 
@@ -296,16 +300,16 @@ reg32,reg32,imm          \7\x3\x80                     ARM7
 [RPWcc]
 
 [RSBcc]
-reg32,reg32,reg32        \4\x0\x60                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\x60                     ARM7
-reg32,reg32,reg32,imm    \6\x0\x60                     ARM7
-reg32,reg32,imm          \7\x2\x60                     ARM7
+;reg32,reg32,reg32            \4\x0\x60                    ARM7
+;reg32,reg32,reg32,reg32      \5\x0\x60                    ARM7
+reg32,reg32,reg32,shifterop  \6\x0\x60                     ARM7
+reg32,reg32,immshifter       \7\x0\x60                     ARM7
 
 [RSCcc]
 reg32,reg32,reg32        \4\x0\xE0                     ARM7
 reg32,reg32,reg32,reg32  \5\x0\xE0                     ARM7
 reg32,reg32,reg32,imm    \6\x0\xE0                     ARM7
-reg32,reg32,imm          \7\x2\xE0                     ARM7
+reg32,reg32,immshifter   \7\x2\xE0                     ARM7
 
 [RSFcc]
 
@@ -317,7 +321,7 @@ reg32,reg32,imm          \7\x2\xE0                     ARM7
 reg32,reg32,reg32        \4\x0\xC0                     ARM7
 reg32,reg32,reg32,reg32  \5\x0\xC0                     ARM7
 reg32,reg32,reg32,imm    \6\x0\xC0                     ARM7
-reg32,reg32,imm          \7\x2\xC0                     ARM7
+reg32,reg32,immshifter   \7\x2\xC0                     ARM7
 
 [SFMcc]
 reg32,imm8,fpureg        \xF0\x02\x00                   FPA
@@ -338,6 +342,7 @@ reg32,reg32,reg32,reg32  \x16\x00\xC0\x90		 ARM7
 
 [STMcc]
 memam4,reglist		   \x26\x80			ARM7
+reg32,reglist		   \x26\x80			ARM7
 
 [STRcc]
 reg32,memam2              \x17\x04\x00                   ARM7
@@ -348,35 +353,36 @@ reg32,memam2              \x17\x04\x00                   ARM7
 ; reg32,reg32,reg32,imm32  \x21\x06\x00                   ARM7
 
 [STRBcc]
-reg32,memam2              \x17\x06\x00                           ARM7
+reg32,memam2              \x17\x04\x40                           ARM7
 
 [STRBTcc]
 
 ; A dummy since it is parsed as STR{cond}H
 [STRHcc]
-reg32,imm32              \x22\x40\xB0              ARM7
-reg32,reg32              \x23\x40\xB0               ARM7
-reg32,reg32,imm32        \x24\x40\xB0                   ARM7
-reg32,reg32,reg32        \x25\x00\xB0                   ARM7
+reg32,memam2              \x22\x00\xB0              ARM7
+;reg32,imm32              \x22\x40\xB0              ARM7
+;reg32,reg32              \x23\x40\xB0               ARM7
+;reg32,reg32,imm32        \x24\x40\xB0                   ARM7
+;reg32,reg32,reg32        \x25\x00\xB0                   ARM7
 
 [STRTcc]
 
 [SUBcc]
-reg32,reg32,shifterop     \4\x0\x40                     ARM7
-reg32,reg32,immshifter    \4\x0\x40                     ARM7
-reg32,reg32,reg32        \4\x0\x40                     ARM7
-; reg32,reg32,reg32,reg32  \5\x0\x40                     ARM7
-; reg32,reg32,reg32,imm    \6\x0\x40                     ARM7
-; reg32,reg32,imm          \7\x2\x40                     ARM7
+reg32,reg32,shifterop       \4\x0\x40                     ARM7
+reg32,reg32,immshifter      \4\x0\x40                     ARM7
+reg32,reg32,reg32           \4\x0\x40                     ARM7
+; reg32,reg32,reg32,reg32     \5\x0\x40                     ARM7
+reg32,reg32,reg32,shifterop \6\x0\x40                     ARM7
+; reg32,reg32,imm           \7\x2\x40                     ARM7
 
 [SWIcc]
 imm                 \2\x0F                        ARM7
 
 [SWPcc]
-reg32,reg32,reg32   \x27\x01\x90                   ARM7
+reg32,reg32,memam2   \x27\x10\x09                   ARM7
 
 [SWPBcc]
-reg32,reg32,reg32   \x27\x01\x90                   ARM7
+reg32,reg32,reg32    \x27\x14\x09                   ARM7
 
 [TANcc]
 
@@ -387,10 +393,10 @@ reg32,reg32,imm     \xE\x1\x20                     ARM7
 reg32,imm           \xF\x3\x20                     ARM7
 
 [TSTcc]
-reg32,reg32         \xC\x1\x00                     ARM7
-reg32,reg32,reg32   \xD\x1\x00                     ARM7
-reg32,reg32,imm     \xE\x1\x00                     ARM7
-reg32,imm           \xF\x3\x00                     ARM7
+reg32,reg32           \xC\x1\x00                     ARM7
+reg32,reg32,reg32     \xD\x1\x00                     ARM7
+reg32,reg32,shifterop \xE\x1\x00                     ARM7
+reg32,immshifter      \xF\x3\x00                     ARM7
 
 [UMLALcc]
 reg32,reg32,reg32,reg32  \x16\x00\xA0\x90		 ARM7

+ 1 - 1
compiler/arm/armnop.inc

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

+ 97 - 146
compiler/arm/armtab.inc

@@ -31,7 +31,7 @@
   (
     opcode  : A_ADC;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
     code    : #7#2#160;
     flags   : if_arm7
   ),
@@ -52,14 +52,14 @@
   (
     opcode  : A_ADD;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop);
     code    : #6#0#128;
     flags   : if_arm7
   ),
   (
     opcode  : A_ADD;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
     code    : #7#2#128;
     flags   : if_arm7
   ),
@@ -73,21 +73,14 @@
   (
     opcode  : A_AND;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#0;
-    flags   : if_arm7
-  ),
-  (
-    opcode  : A_AND;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop);
     code    : #6#0#0;
     flags   : if_arm7
   ),
   (
     opcode  : A_AND;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
     code    : #7#2#0;
     flags   : if_arm7
   ),
@@ -108,28 +101,7 @@
   (
     opcode  : A_BIC;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#1#192;
-    flags   : if_arm7
-  ),
-  (
-    opcode  : A_BIC;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#1#192;
-    flags   : if_arm7
-  ),
-  (
-    opcode  : A_BIC;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
-    code    : #6#1#192;
-    flags   : if_arm7
-  ),
-  (
-    opcode  : A_BIC;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
     code    : #7#3#192;
     flags   : if_arm7
   ),
@@ -199,8 +171,8 @@
   (
     opcode  : A_CMN;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
-    code    : #15#3#96;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none);
+    code    : #15#1#96;
     flags   : if_arm7
   ),
   (
@@ -220,14 +192,14 @@
   (
     opcode  : A_CMP;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
     code    : #14#1#64;
     flags   : if_arm7
   ),
   (
     opcode  : A_CMP;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none);
     code    : #15#3#64;
     flags   : if_arm7
   ),
@@ -248,21 +220,14 @@
   (
     opcode  : A_EOR;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#32;
-    flags   : if_arm7
-  ),
-  (
-    opcode  : A_EOR;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop);
     code    : #6#0#32;
     flags   : if_arm7
   ),
   (
     opcode  : A_EOR;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
     code    : #7#2#32;
     flags   : if_arm7
   ),
@@ -281,52 +246,38 @@
     flags   : if_arm7
   ),
   (
-    opcode  : A_LDRB;
+    opcode  : A_LDM;
     ops     : 2;
-    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
-    code    : #23#7#16;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none);
+    code    : #38#129;
     flags   : if_arm7
   ),
   (
-    opcode  : A_LDR;
+    opcode  : A_LDRB;
     ops     : 2;
     optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
-    code    : #23#5#16;
+    code    : #23#4#80;
     flags   : if_arm7
   ),
   (
-    opcode  : A_LDRH;
+    opcode  : A_LDR;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
-    code    : #34#80#176;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+    code    : #23#4#16;
     flags   : if_arm7
   ),
   (
     opcode  : A_LDRH;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #35#80#176;
-    flags   : if_arm7
-  ),
-  (
-    opcode  : A_LDRH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
-    code    : #36#80#176;
-    flags   : if_arm7
-  ),
-  (
-    opcode  : A_LDRH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #37#16#176;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+    code    : #34#16#176;
     flags   : if_arm7
   ),
   (
     opcode  : A_LDRSB;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
-    code    : #34#80#208;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+    code    : #34#16#208;
     flags   : if_arm7
   ),
   (
@@ -353,29 +304,8 @@
   (
     opcode  : A_LDRSH;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
-    code    : #34#80#240;
-    flags   : if_arm7
-  ),
-  (
-    opcode  : A_LDRSH;
-    ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #35#80#240;
-    flags   : if_arm7
-  ),
-  (
-    opcode  : A_LDRSH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
-    code    : #36#80#240;
-    flags   : if_arm7
-  ),
-  (
-    opcode  : A_LDRSH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #37#16#240;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+    code    : #34#16#240;
     flags   : if_arm7
   ),
   (
@@ -392,6 +322,27 @@
     code    : #21#0#32#144;
     flags   : if_arm7
   ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #8#1#160;
+    flags   : if_arm7
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
+    code    : #10#1#160;
+    flags   : if_arm7
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none);
+    code    : #11#1#160;
+    flags   : if_arm7
+  ),
   (
     opcode  : A_MRS;
     ops     : 2;
@@ -441,6 +392,27 @@
     code    : #242;
     flags   : if_fpa
   ),
+  (
+    opcode  : A_MVN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #8#1#224;
+    flags   : if_arm7
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
+    code    : #10#1#224;
+    flags   : if_arm7
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none);
+    code    : #11#1#224;
+    flags   : if_arm7
+  ),
   (
     opcode  : A_ORR;
     ops     : 3;
@@ -458,43 +430,29 @@
   (
     opcode  : A_ORR;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop);
     code    : #6#1#128;
     flags   : if_arm7
   ),
   (
     opcode  : A_ORR;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
     code    : #7#3#128;
     flags   : if_arm7
   ),
-  (
-    opcode  : A_RSB;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#96;
-    flags   : if_arm7
-  ),
-  (
-    opcode  : A_RSB;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#96;
-    flags   : if_arm7
-  ),
   (
     opcode  : A_RSB;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop);
     code    : #6#0#96;
     flags   : if_arm7
   ),
   (
     opcode  : A_RSB;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #7#2#96;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
+    code    : #7#0#96;
     flags   : if_arm7
   ),
   (
@@ -521,7 +479,7 @@
   (
     opcode  : A_RSC;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
     code    : #7#2#224;
     flags   : if_arm7
   ),
@@ -549,7 +507,7 @@
   (
     opcode  : A_SBC;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
     code    : #7#2#192;
     flags   : if_arm7
   ),
@@ -582,45 +540,31 @@
     flags   : if_arm7
   ),
   (
-    opcode  : A_STR;
+    opcode  : A_STM;
     ops     : 2;
-    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
-    code    : #23#4#0;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none);
+    code    : #38#128;
     flags   : if_arm7
   ),
   (
-    opcode  : A_STRB;
+    opcode  : A_STR;
     ops     : 2;
     optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
-    code    : #23#6#0;
+    code    : #23#4#0;
     flags   : if_arm7
   ),
   (
-    opcode  : A_STRH;
+    opcode  : A_STRB;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
-    code    : #34#64#176;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+    code    : #23#4#64;
     flags   : if_arm7
   ),
   (
     opcode  : A_STRH;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #35#64#176;
-    flags   : if_arm7
-  ),
-  (
-    opcode  : A_STRH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
-    code    : #36#64#176;
-    flags   : if_arm7
-  ),
-  (
-    opcode  : A_STRH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #37#0#176;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+    code    : #34#0#176;
     flags   : if_arm7
   ),
   (
@@ -644,6 +588,13 @@
     code    : #4#0#64;
     flags   : if_arm7
   ),
+  (
+    opcode  : A_SUB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop);
+    code    : #6#0#64;
+    flags   : if_arm7
+  ),
   (
     opcode  : A_SWI;
     ops     : 1;
@@ -654,15 +605,15 @@
   (
     opcode  : A_SWP;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #39#1#144;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none);
+    code    : #39#16#9;
     flags   : if_arm7
   ),
   (
     opcode  : A_SWPB;
     ops     : 3;
     optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #39#1#144;
+    code    : #39#20#9;
     flags   : if_arm7
   ),
   (
@@ -710,14 +661,14 @@
   (
     opcode  : A_TST;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
     code    : #14#1#0;
     flags   : if_arm7
   ),
   (
     opcode  : A_TST;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none);
     code    : #15#3#0;
     flags   : if_arm7
   ),

+ 6 - 6
compiler/ogcoff.pas

@@ -1009,10 +1009,9 @@ const pemagic : array[0..3] of byte = (
           result:=aname
         else
           begin
-            { non-PECOFF targets lack rodata support.
-              TODO: WinCE likely supports it, but needs testing. }
+            { non-PECOFF targets lack rodata support }
             if (atype in [sec_rodata,sec_rodata_norel]) and
-               not (target_info.system in systems_windows) then
+               not (target_info.system in systems_all_windows) then
               atype:=sec_data;
             secname:=coffsecnames[atype];
             if create_smartlink_sections and
@@ -1038,8 +1037,7 @@ const pemagic : array[0..3] of byte = (
       begin
         if (aType in [sec_rodata,sec_rodata_norel]) then
           begin
-            { TODO: WinCE needs testing }
-            if (target_info.system in systems_windows) then
+            if (target_info.system in systems_all_windows) then
               aType:=sec_rodata_norel
             else
               aType:=sec_data;
@@ -1279,6 +1277,8 @@ const pemagic : array[0..3] of byte = (
                 rel.reloctype:=IMAGE_REL_ARM_ADDR32NB;
               RELOC_SECREL32 :
                 rel.reloctype:=IMAGE_REL_ARM_SECREL;
+              RELOC_RELATIVE_24 :
+                rel.reloctype:=IMAGE_REL_ARM_BRANCH24;
 {$endif arm}
 {$ifdef i386}
               RELOC_RELATIVE :
@@ -3045,7 +3045,7 @@ const pemagic : array[0..3] of byte = (
             asmbin : '';
             asmcmd : '';
             supported_targets : [system_arm_wince];
-            flags : [af_outputbinary];
+            flags : [af_outputbinary,af_smartlink_sections];
             labelprefix : '.L';
             comment : '';
             dollarsign: '$';