=================================================================== Index: gas/config/tc-arm.c --- gas/config/tc-arm.c (revision 76) +++ gas/config/tc-arm.c (revision 77) @@ -3400,6 +3400,29 @@ } } +/* Parse a conditional code (from conds[] below). The value returned is in the + range 0 .. 14, or FAIL. */ +static int +parse_cond (char **str) +{ + char *p, *q; + const struct asm_cond *c; + + p = q = *str; + while (ISALPHA (*q)) + q++; + + c = hash_find_n (arm_cond_hsh, p, q - p); + if (!c) + { + inst.error = _("condition required"); + return FAIL; + } + + *str = q; + return c->value; +} + /* Matcher codes for parse_operands. */ enum operand_parse_code { @@ -3454,6 +3477,7 @@ OP_CPSF, /* CPS flags */ OP_ENDI, /* Endianness specifier */ OP_PSR, /* CPSR/SPSR mask for msr */ + OP_COND, /* conditional code */ OP_RRnpc_I0, /* ARM register or literal 0 */ OP_RR_EXr, /* ARM register or expression with opt. reloc suff. */ @@ -3689,6 +3713,7 @@ case OP_ENDI: val = parse_endian_specifier (&str); break; case OP_oROR: val = parse_ror (&str); break; case OP_PSR: val = parse_psr (&str); break; + case OP_COND: val = parse_cond (&str); break; /* Register lists */ case OP_REGLST: @@ -3750,6 +3775,7 @@ case OP_ENDI: case OP_oROR: case OP_PSR: + case OP_COND: case OP_REGLST: case OP_VRSLST: case OP_VRDLST: @@ -5540,6 +5566,39 @@ } static void +do_t_czb (void) +{ + constraint (inst.operands[0].reg > 7, BAD_HIREG); + inst.instruction |= inst.operands[0].reg; + inst.reloc.pc_rel = 1; + inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH7; +} + +static void +do_t_it (void) +{ + unsigned int cond = inst.operands[0].imm; + if (cond & 0x1) + { + 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; + else + mask = (~(mask & 0xE) & 0xE) | 0x1; + + inst.instruction |= (mask & 0xF); + } + + inst.instruction |= cond << 4; +} + +static void do_t_ldmstm (void) { /* This really doesn't seem worth it. */ @@ -6246,25 +6305,24 @@ #endif }; -/* Table of all conditional suffixes. 0xF... is for special-case, - unconditional instructions. */ +/* Table of all conditional suffixes. 0xF is not defined as a condition code. */ static const struct asm_cond conds[] = { - {"eq", 0x00000000}, - {"ne", 0x10000000}, - {"cs", 0x20000000}, {"hs", 0x20000000}, - {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000}, - {"mi", 0x40000000}, - {"pl", 0x50000000}, - {"vs", 0x60000000}, - {"vc", 0x70000000}, - {"hi", 0x80000000}, - {"ls", 0x90000000}, - {"ge", 0xa0000000}, - {"lt", 0xb0000000}, - {"gt", 0xc0000000}, - {"le", 0xd0000000}, - {"al", 0xe0000000} + {"eq", 0x0}, + {"ne", 0x1}, + {"cs", 0x2}, {"hs", 0x2}, + {"cc", 0x3}, {"ul", 0x3}, {"lo", 0x3}, + {"mi", 0x4}, + {"pl", 0x5}, + {"vs", 0x6}, + {"vc", 0x7}, + {"hi", 0x8}, + {"ls", 0x9}, + {"ge", 0xa}, + {"lt", 0xb}, + {"gt", 0xc}, + {"le", 0xd}, + {"al", 0xe} }; /* Table of ARM-format instructions. */ @@ -6356,6 +6414,11 @@ #define UF(mnem, op, nops, ops, ae) TUF(mnem, op, 0, nops, ops, ae, 0) #define do_0 0 +/* unconditional Thumb-only */ +#define UT(mnem, op, nops, ops, te) \ + { #mnem, OPS##nops ops, 0, 0x##op, 0, THUMB_VARIANT, 0, do_##te } + + static const struct asm_opcode insns[] = { #define ARM_VARIANT ARM_EXT_V1 /* Core ARM Instructions. */ @@ -6714,6 +6777,24 @@ CM(ldr,sbt, 03000d0, 2, (RR, ADDR), ldsttv4), CM(str,ht, 02000b0, 2, (RR, ADDR), ldsttv4), + UT(czbne, b900, 2, (RR, EXP), t_czb), + UT(czbeq, b100, 2, (RR, EXP), t_czb), + UT(it, bf08, 1, (COND), t_it), + UT(itt, bf0c, 1, (COND), t_it), + UT(ite, bf04, 1, (COND), t_it), + UT(ittt, bf0e, 1, (COND), t_it), + UT(itet, bf06, 1, (COND), t_it), + UT(itte, bf0a, 1, (COND), t_it), + UT(itee, bf02, 1, (COND), t_it), + UT(itttt, bf0f, 1, (COND), t_it), + UT(itett, bf07, 1, (COND), t_it), + UT(ittet, bf0b, 1, (COND), t_it), + UT(iteet, bf03, 1, (COND), t_it), + UT(ittte, bf0d, 1, (COND), t_it), + UT(itete, bf05, 1, (COND), t_it), + UT(ittee, bf09, 1, (COND), t_it), + UT(iteee, bf01, 1, (COND), t_it), + #undef ARM_VARIANT #define ARM_VARIANT FPU_FPA_EXT_V1 /* Core FPA instruction set (V1). */ CE(wfs, e200110, 1, (RR), rd), @@ -7542,6 +7623,7 @@ #undef CM #undef UE #undef UF +#undef UT #undef OPS0 #undef OPS1 #undef OPS2 @@ -8664,6 +8746,32 @@ } break; + case BFD_RELOC_THUMB_PCREL_BRANCH7: /* CZB */ + newval = md_chars_to_number (buf, THUMB_SIZE); + { + addressT diff = ((newval & 0x00f8) >> 2) | (newval & 0x0200) >> 3; + fprintf (stderr, "%lx %lx\n", value, diff); + value = value + diff; + /* CZB can only branch forward. */ + if (value & ~0x3f) + as_bad_where (fixP->fx_file, fixP->fx_line, + _("branch out of range")); + if (seg->use_rela_p && !fixP->fx_done) + { +#ifdef OBJ_ELF + fixP->fx_offset = value; +#endif + fixP->fx_addnumber = value; + newval = newval & 0xfd07; + } + else + newval = ((newval & 0xfd07) + | ((value & 0x1e) << 2) + | ((value & 0x20) << 3)); + } + md_number_to_chars (buf, newval, THUMB_SIZE); + break; + case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */ newval = md_chars_to_number (buf, THUMB_SIZE); { @@ -9105,9 +9213,12 @@ case BFD_RELOC_ARM_PCREL_BRANCH: case BFD_RELOC_ARM_PCREL_BLX: case BFD_RELOC_RVA: + case BFD_RELOC_THUMB_PCREL_BRANCH7: case BFD_RELOC_THUMB_PCREL_BRANCH9: case BFD_RELOC_THUMB_PCREL_BRANCH12: + case BFD_RELOC_THUMB_PCREL_BRANCH20: case BFD_RELOC_THUMB_PCREL_BRANCH23: + case BFD_RELOC_THUMB_PCREL_BRANCH25: case BFD_RELOC_THUMB_PCREL_BLX: case BFD_RELOC_VTABLE_ENTRY: case BFD_RELOC_VTABLE_INHERIT: =================================================================== Index: opcodes/arm-dis.c --- opcodes/arm-dis.c (revision 76) +++ opcodes/arm-dis.c (revision 77) @@ -98,12 +98,12 @@ %M print Thumb register mask %N print Thumb register mask (with LR) %O print Thumb register mask (with PC) - %T print Thumb condition code (always bits 8-11) %I print cirrus signed shift immediate: bits 0..3|4..6 %B print Thumb branch destination (signed displacement) %W print (bitfield * 4) as a decimal %H print (bitfield * 2) as a decimal %a print (bitfield * 4) as a pc-rel offset + decoded symbol + %c print bitfield as a condition code %e print arm SMI operand (bits 0..7,8..19). %s print Thumb right-shift immediate (6..10; 0 == 32). */ @@ -643,6 +643,17 @@ {ARM_EXT_V6K, 0xbf30, 0xffff, "wfi"}, {ARM_EXT_V6K, 0xbf40, 0xffff, "sev"}, + /* ARM V6T2 instructions. */ + {ARM_EXT_V6T2, 0xb900, 0xfd00, "czbne\t%0-2r, %b"}, + {ARM_EXT_V6T2, 0xb100, 0xfd00, "czbeq\t%0-2r, %b"}, + {ARM_EXT_V6T2, 0xbf08, 0xff0f, "it\t%4-7c"}, + {ARM_EXT_V6T2, 0xbf14, 0xff17, "it%3?te\t%4-7c"}, + {ARM_EXT_V6T2, 0xbf04, 0xff17, "it%3?et\t%4-7c"}, + {ARM_EXT_V6T2, 0xbf12, 0xff13, "it%3?te%2?te\t%4-7c"}, + {ARM_EXT_V6T2, 0xbf02, 0xff13, "it%3?et%2?et\t%4-7c"}, + {ARM_EXT_V6T2, 0xbf11, 0xff11, "it%3?te%2?te%1?te\t%4-7c"}, + {ARM_EXT_V6T2, 0xbf01, 0xff11, "it%3?et%2?et%1?et\t%4-7c"}, + /* ARM V6. */ {ARM_EXT_V6, 0xb660, 0xfff8, "cpsie\t%2'a%1'i%0'f"}, {ARM_EXT_V6, 0xb670, 0xfff8, "cpsid\t%2'a%1'i%0'f"}, @@ -733,7 +744,7 @@ /* format 17 */ {ARM_EXT_V4T, 0xDF00, 0xFF00, "swi\t%0-7d"}, /* format 16 */ - {ARM_EXT_V4T, 0xD000, 0xF000, "b%T.n\t%0-7B"}, + {ARM_EXT_V4T, 0xD000, 0xF000, "b%8-11c.n\t%0-7B"}, /* format 18 */ {ARM_EXT_V4T, 0xE000, 0xF800, "b.n\t%0-10B"}, @@ -1952,18 +1963,6 @@ } break; - case 'T': - { - long cc = (given >> 8) & 0xf; - /* Must print 0xE as 'al' to distinguish - unconditional B from conditional BAL. */ - if (cc == 0xE) - func (stream, "al"); - else - func (stream, "%s", arm_conditional [cc]); - } - break; - case 'N': if (given & (1 << 8)) domasklr = 1; @@ -2009,6 +2008,16 @@ } break; + case 'b': + /* Print ARM V6T2 CZB address: pc+4+6 bits. */ + { + bfd_vma address = (pc + 4 + + ((given & 0x00f8) >> 2) + + ((given & 0x0200) >> 3)); + info->print_address_func (address, info); + } + break; + case 's': /* Right shift immediate -- bits 6..10; 1-31 print as themselves, 0 prints as 32. */ @@ -2083,6 +2092,17 @@ (reg * 2 + pc + 4, info); break; + case 'c': + { + /* Must print 0xE as 'al' to distinguish + unconditional B from conditional BAL. */ + if (reg == 0xE) + func (stream, "al"); + else + func (stream, "%s", arm_conditional [reg]); + } + break; + default: abort (); }