From e27ec89e51e1db97b276d427f8fd3d8abe57631f Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Fri, 5 Aug 2005 12:28:23 +0000 Subject: [PATCH] 2005-08-05 Paul Brook 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 | 8 +++ gas/config/tc-arm.c | 100 +++++++++++++++++++++----- gas/testsuite/ChangeLog | 6 ++ gas/testsuite/gas/arm/thumb32.s | 122 ++++++++++++++++++-------------- 4 files changed, 166 insertions(+), 70 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 1329e338a9..789e03576d 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,11 @@ +2005-08-05 Paul Brook + + * 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 * config/tc-arm.c (encode_thumb32_immediate): Only accept shifted diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 5ef6a41abc..6a587f3c9c 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -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; + /* 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); diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index f565aed20c..0f41a71b5d 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2005-08-05 Paul Brook + + * 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 * gas/arm/thumb32.d: Update ldm/stm dests. diff --git a/gas/testsuite/gas/arm/thumb32.s b/gas/testsuite/gas/arm/thumb32.s index ff01068e39..be9f95f7d8 100644 --- a/gas/testsuite/gas/arm/thumb32.s +++ b/gas/testsuite/gas/arm/thumb32.s @@ -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 -- 2.34.1