2005-08-05 Paul Brook <paul@codesourcery.com>
authorPaul Brook <paul@codesourcery.com>
Fri, 5 Aug 2005 12:28:23 +0000 (12:28 +0000)
committerPaul Brook <paul@codesourcery.com>
Fri, 5 Aug 2005 12:28:23 +0000 (12:28 +0000)
gas/
* config/tc-arm.c (current_it_mask, current_cc): New variables.
(do_t_add_sub): Use correct encodings inside IT block.
(do_t_arit3c): Ditto.
(do_t_it): Simplify logic.  Set current_it_mask and current_cc.
(md_assemble): Verify conditional suffixes agains IT blocks.
gas/testsuite/
* gas/arm/thumb32.s: Use correct conditional suffixes inside IT
blocks.
* gas/arm/thumb2_it.d, gas/arm/thumb2_it.s: New test.

gas/ChangeLog
gas/config/tc-arm.c
gas/testsuite/ChangeLog
gas/testsuite/gas/arm/thumb32.s

index 1329e338a9904fdf4e7451c3bfb538d724747e03..789e03576d5b1802820d8c9978a7642d552a675f 100644 (file)
@@ -1,3 +1,11 @@
+2005-08-05  Paul Brook  <paul@codesourcery.com>
+
+       * config/tc-arm.c (current_it_mask, current_cc): New variables.
+       (do_t_add_sub): Use correct encodings inside IT block.
+       (do_t_arit3c): Ditto.
+       (do_t_it): Simplify logic.  Set current_it_mask and current_cc.
+       (md_assemble): Verify conditional suffixes agains IT blocks.
+
 2005-08-05  Paul Brook  <paul@codesourcery.com>
 
        * config/tc-arm.c (encode_thumb32_immediate): Only accept shifted
index 5ef6a41abc13b0994d72df76710443066512c189..6a587f3c9ce4a2fcb7449596fd60cef233c44123 100644 (file)
@@ -535,6 +535,11 @@ typedef struct literal_pool
 
 /* Pointer to a linked list of literal pools.  */
 literal_pool * list_of_pools = NULL;
+
+/* State variables for IT block handling.  */
+static bfd_boolean current_it_mask = 0;
+static int current_cc;
+
 \f
 /* Pure syntax.         */
 
@@ -5863,6 +5868,8 @@ do_t_add_sub (void)
     {
       if (!inst.operands[2].isreg)
        {
+         /* ??? Convert large immediates to addw/subw.  */
+         /* ??? 16-bit adds with small immediates.  */
          /* For an immediate, we always generate a 32-bit opcode;
             section relaxation will shrink it later if possible.  */
          inst.instruction = THUMB_OP32 (inst.instruction);
@@ -5877,11 +5884,20 @@ do_t_add_sub (void)
          /* See if we can do this with a 16-bit instruction.  */
          if (!inst.operands[2].shifted && inst.size_req != 4)
            {
-             if (Rd <= 7 && Rn <= 7 && Rn <= 7
-                 && (inst.instruction == T_MNEM_adds
-                     || inst.instruction == T_MNEM_subs))
+             bfd_boolean narrow;
+
+             if (inst.instruction == T_MNEM_adds
+                 || inst.instruction == T_MNEM_subs)
+               narrow = (current_it_mask == 0);
+             else
+               narrow = (current_it_mask != 0);
+             if (Rd > 7 || Rs > 7 || Rn > 7)
+               narrow = FALSE;
+
+             if (narrow)
                {
-                 inst.instruction = (inst.instruction == T_MNEM_adds
+                 inst.instruction = ((inst.instruction == T_MNEM_adds
+                                      || inst.instruction == T_MNEM_add)
                                      ? T_OPCODE_ADD_R3
                                      : T_OPCODE_SUB_R3);
                  inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
@@ -6018,10 +6034,22 @@ do_t_arit3 (void)
        }
       else
        {
+         bfd_boolean narrow;
+
          /* See if we can do this with a 16-bit instruction.  */
-         if (THUMB_SETS_FLAGS (inst.instruction)
-             && !inst.operands[2].shifted
-             && inst.size_req != 4
+         if (THUMB_SETS_FLAGS (inst.instruction))
+           narrow = current_it_mask == 0;
+         else
+           narrow = current_it_mask != 0;
+
+         if (Rd > 7 || Rn > 7 || Rs > 7)
+           narrow = FALSE;
+         if (inst.operands[2].shifted)
+           narrow = FALSE;
+         if (inst.size_req == 4)
+           narrow = FALSE;
+
+         if (narrow
              && Rd == Rs)
            {
              inst.instruction = THUMB_OP16 (inst.instruction);
@@ -6089,10 +6117,22 @@ do_t_arit3c (void)
        }
       else
        {
+         bfd_boolean narrow;
+
          /* See if we can do this with a 16-bit instruction.  */
-         if (THUMB_SETS_FLAGS (inst.instruction)
-             && !inst.operands[2].shifted
-             && inst.size_req != 4)
+         if (THUMB_SETS_FLAGS (inst.instruction))
+           narrow = current_it_mask == 0;
+         else
+           narrow = current_it_mask != 0;
+
+         if (Rd > 7 || Rn > 7 || Rs > 7)
+           narrow = FALSE;
+         if (inst.operands[2].shifted)
+           narrow = FALSE;
+         if (inst.size_req == 4)
+           narrow = FALSE;
+
+         if (narrow)
            {
              if (Rd == Rs)
                {
@@ -6363,21 +6403,26 @@ static void
 do_t_it (void)
 {
   unsigned int cond = inst.operands[0].imm;
+
+  current_it_mask = (inst.instruction & 0xf) | 0x10;
+  current_cc = cond;
+
+  /* If the condition is a negative condition, invert the mask.  */
   if ((cond & 0x1) == 0x0)
     {
       unsigned int mask = inst.instruction & 0x000f;
-      inst.instruction &= 0xfff0;
 
       if ((mask & 0x7) == 0)
        /* no conversion needed */;
       else if ((mask & 0x3) == 0)
-       mask = (~(mask & 0x8) & 0x8) | 0x4;
-      else if ((mask & 1) == 0)
-       mask = (~(mask & 0xC) & 0xC) | 0x2;
+       mask ^= 0x8;
+      else if ((mask & 0x1) == 0)
+       mask ^= 0xC;
       else
-       mask = (~(mask & 0xE) & 0xE) | 0x1;
+       mask ^= 0xE;
 
-      inst.instruction |= (mask & 0xF);
+      inst.instruction &= 0xfff0;
+      inst.instruction |= mask;
     }
 
   inst.instruction |= cond << 4;
@@ -7687,12 +7732,35 @@ md_assemble (char *str)
          return;
        }
 
+      /* Check conditional suffixes.  */
+      if (current_it_mask)
+       {
+         int cond;
+         cond = current_cc ^ ((current_it_mask >> 4) & 1) ^ 1;
+         if (cond != inst.cond)
+           {
+             as_bad (_("incorrect condition in IT block"));
+             return;
+           }
+         current_it_mask <<= 1;
+         current_it_mask &= 0x1f;
+       }
+      else if (inst.cond != COND_ALWAYS && opcode->tencode != do_t_branch)
+       {
+         as_bad (_("thumb conditional instrunction not in IT block"));
+         return;
+       }
+
       mapping_state (MAP_THUMB);
       inst.instruction = opcode->tvalue;
 
       if (!parse_operands (p, opcode->operands))
        opcode->tencode ();
 
+      /* Clear current_it_mask at the end of an IT block.  */
+      if (current_it_mask == 0x10)
+       current_it_mask = 0;
+
       if (!inst.error)
        {
          assert (inst.instruction < 0xe800 || inst.instruction > 0xffff);
index f565aed20caf214a5b4d61ec539758a06b45fee9..0f41a71b5da4413638807ee8f36c5a8391c4e00f 100644 (file)
@@ -1,3 +1,9 @@
+2005-08-05  Paul Brook  <paul@codesourcery.com>
+
+       * gas/arm/thumb32.s: Use correct conditional suffixes inside IT
+       blocks.
+       * gas/arm/thumb2_it.d, gas/arm/thumb2_it.s: New test.
+
 2005-08-05  Paul Brook  <paul@codesourcery.com>
 
        * gas/arm/thumb32.d: Update ldm/stm dests.
index ff01068e3992db68239985c626f42b78934780cc..be9f95f7d87eedb876d0978391144ba32942907b 100644 (file)
@@ -275,62 +275,76 @@ nop_hint:
        nop {129}
 
 it:
-       .macro  itx opc cond n
-       \opc    \cond
-       .rept   \n
-       nop
-       .endr
+       .macro nop1 cond ncond a
+       .ifc \a,t
+       nop\cond
+       .else
+       nop\ncond
+       .endif
+       .endm
+       .macro it0 cond m=
+       it\m \cond
+       nop\cond
+       .endm
+       .macro it1 cond ncond a m=
+       it0 \cond \a\m
+       nop1 \cond \ncond \a
+       .endm
+       .macro it2 cond ncond a b m=
+       it1 \cond \ncond \a \b\m
+       nop1 \cond \ncond \b
+       .endm
+       .macro it3 cond ncond a b c
+       it2 \cond \ncond \a \b \c
+       nop1 \cond \ncond \c
        .endm
 
-       itx     it eq 1
-       itx     it ne 1
-       itx     it cs 1
-       itx     it hs 1
-       itx     it cc 1
-       itx     it ul 1
-       itx     it lo 1
-       itx     it mi 1
-       itx     it pl 1
-       itx     it vs 1
-       itx     it vc 1
-       itx     it hi 1
-       itx     it ge 1
-       itx     it lt 1
-       itx     it gt 1
-       itx     it le 1
-       itx     it al 1
-
-       itx     itt eq 2
-       itx     ite eq 2
-       itx     ittt eq 3
-       itx     itet eq 3
-       itx     itte eq 3
-       itx     itee eq 3
-       itx     itttt eq 4
-       itx     itett eq 4
-       itx     ittet eq 4
-       itx     ittte eq 4
-       itx     ittee eq 4
-       itx     itete eq 4
-       itx     iteet eq 4
-       itx     iteee eq 4
-       
-       itx     itt ne 2
-       itx     ite ne 2
-       itx     ittt ne 3
-       itx     itet ne 3
-       itx     itte ne 3
-       itx     itee ne 3
-       itx     itttt ne 4
-       itx     itett ne 4
-       itx     ittet ne 4
-       itx     ittte ne 4
-       itx     ittee ne 4
-       itx     itete ne 4
-       itx     iteet ne 4
-       itx     iteee ne 4
-
-       .purgem itx
+       it0     eq
+       it0     ne
+       it0     cs
+       it0     hs
+       it0     cc
+       it0     ul
+       it0     lo
+       it0     mi
+       it0     pl
+       it0     vs
+       it0     vc
+       it0     hi
+       it0     ge
+       it0     lt
+       it0     gt
+       it0     le
+       it0     al
+       it1 eq ne t
+       it1 eq ne e
+       it2 eq ne t t
+       it2 eq ne e t
+       it2 eq ne t e
+       it2 eq ne e e
+       it3 eq ne t t t
+       it3 eq ne e t t
+       it3 eq ne t e t
+       it3 eq ne t t e
+       it3 eq ne t e e
+       it3 eq ne e t e
+       it3 eq ne e e t
+       it3 eq ne e e e
+
+       it1 ne eq t
+       it1 ne eq e
+       it2 ne eq t t
+       it2 ne eq e t
+       it2 ne eq t e
+       it2 ne eq e e
+       it3 ne eq t t t
+       it3 ne eq e t t
+       it3 ne eq t e t
+       it3 ne eq t t e
+       it3 ne eq t e e
+       it3 ne eq e t e
+       it3 ne eq e e t
+       it3 ne eq e e e
 
 ldst:
        .macro  ls op