Discussion:
[PATCH] assembler/disassembler support for ARM "udf" mnemonic
Roland McGrath
2013-08-30 22:16:20 UTC
Permalink
This makes the ARM assembler and disassembler grok the "udf" mnemonic for
the "permanently undefined" opcode ranges. AIUI these opcode ranges have
been specified with "permanently undefined" meaning from the beginning of
ARM (and Thumb, and Thumb-2). But only quite recent editions of the ARM
instruction set manual describe an assembly syntax for them.

I think I've covered all the cases correctly, but this should certainly get
some close scrutiny by an actual ARM expert.

No 'make check' failures for arm-linux-gnueabi or arm-nacl targets.

OK for trunk?


Thanks,
Roland



gas/
2013-08-30 Roland McGrath <***@google.com>

* config/tc-arm.c (T16_32_TAB): Add _udf.
(do_t_udf): New function.
(insns): Add "udf".

gas/testsuite/
2013-08-30 Roland McGrath <***@google.com>

* gas/arm/udf-bad.s: New file.
* gas/arm/udf-bad.d: New file.
* gas/arm/udf-bad.l: New file.
* gas/arm/udf.s: New file.
* gas/arm/udf.d: New file.
* gas/arm/udf.l: New file.

opcodes/
2013-08-30 Roland McGrath <***@google.com>

* arm-dis.c (arm_opcodes): Add udf.
(thumb_opcodes): Use "udf" mnemonic rather than UNDEFINED_INSTRUCTION.
(thumb32_opcodes): Add udf.w.
(print_insn_thumb32): Handle %H as the thumb32_opcodes comment says.

--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -9563,7 +9563,8 @@ encode_thumb32_addr_mode (int i, bfd_boolean
is_t, bfd_boolean is_d)
X(_wfe, bf20, f3af8002), \
X(_wfi, bf30, f3af8003), \
X(_sev, bf40, f3af8004), \
- X(_sevl, bf50, f3af8005)
+ X(_sevl, bf50, f3af8005), \
+ X(_udf, de00, f7f0a000)

/* To catch errors in encoding functions, the codes are all offset by
0xF800, putting them in one of the 32-bit prefix ranges, ergo undefined
@@ -12219,6 +12220,30 @@ do_t_tb (void)
}

static void
+do_t_udf (void)
+{
+ if (!inst.operands[0].present)
+ inst.operands[0].imm = 0;
+
+ if ((unsigned int) inst.operands[0].imm > 255 || inst.size_req == 4)
+ {
+ constraint (inst.size_req == 2,
+ _("immediate value out of range"));
+ inst.instruction = THUMB_OP32 (inst.instruction);
+ inst.instruction |= (inst.operands[0].imm & 0xf000u) << 4;
+ inst.instruction |= (inst.operands[0].imm & 0x0fffu) << 0;
+ }
+ else
+ {
+ inst.instruction = THUMB_OP16 (inst.instruction);
+ inst.instruction |= inst.operands[0].imm;
+ }
+
+ set_it_insn_type (NEUTRAL_IT_INSN);
+}
+
+
+static void
do_t_usat (void)
{
do_t_ssat_usat (0);
@@ -18029,6 +18054,7 @@ static const struct asm_opcode insns[] =
tCE("adr", 28f0000, _adr, 2, (RR, EXP), adr, t_adr),
C3(adrl, 28f0000, 2, (RR, EXP), adrl),
tCE("nop", 1a00000, _nop, 1, (oI255c), nop, t_nop),
+ tCE("udf", 7f000f0, _udf, 1, (oIffffb), bkpt, t_udf),

/* Thumb-compatibility pseudo ops. */
tCE("lsl", 1a00000, _lsl, 3, (RR, oRR, SH), shift, t_shift),
--- /dev/null
+++ b/gas/testsuite/gas/arm/udf-bad.d
@@ -0,0 +1,2 @@
+#name: Invalid UDF operands
+#error-output: udf-bad.l
--- /dev/null
+++ b/gas/testsuite/gas/arm/udf-bad.l
@@ -0,0 +1,5 @@
+[^:]*: Assembler messages:
+^[^:]*:4: Error: immediate value out of range -- `udf #0x10000'
+^[^:]*:7: Error: immediate value out of range -- `udf #0x10000'
+^[^:]*:8: Error: immediate value out of range -- `udf.w #0x10000'
+^[^:]*:9: Error: immediate value out of range -- `udf.n #0x100'
--- /dev/null
+++ b/gas/testsuite/gas/arm/udf-bad.s
@@ -0,0 +1,9 @@
+ .syntax unified
+
+arm: .arm
+ udf #0x10000
+
+thumb: .thumb
+ udf #0x10000
+ udf.w #0x10000
+ udf.n #0x100
--- /dev/null
+++ b/gas/testsuite/gas/arm/udf.d
@@ -0,0 +1,30 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: UDF
+#error-output: udf.l
+
+.*: +file format .*arm.*
+
+Disassembly of section \.text:
+
+0+0 <arm>:
+\s*0:\s+e7f000f0\s+udf #0
+\s*4:\s+e7fabcfd\s+udf #43981 ; 0xabcd
+
+0+0 <thumb>:
+\s*8:\s+deab\s+udf #171 ; 0xab
+\s*a:\s+decd\s+udf #205 ; 0xcd
+\s*c:\s+de00\s+udf #0
+\s*e:\s+46c0\s+nop.*
+\s*10:\s+f7f0 a000\s+udf\.w #0
+\s*14:\s+f7f1 a234\s+udf\.w #4660 ; 0x1234
+\s*18:\s+f7fc acdd\s+udf\.w #52445 ; 0xccdd
+\s*1c:\s+bf08\s+it eq
+\s*1e:\s+de12\s+udfeq #18
+\s*20:\s+de23\s+udf #35 ; 0x23
+\s*22:\s+de34\s+udf #52 ; 0x34
+\s*24:\s+de56\s+udf #86 ; 0x56
+\s*26:\s+bf18\s+it ne
+\s*28:\s+f7f1 a234\s+udfne\.w #4660 ; 0x1234
+\s*2c:\s+f7f2 a345\s+udf\.w #9029 ; 0x2345
+\s*30:\s+f7f3 a456\s+udf\.w #13398 ; 0x3456
+\s*34:\s+f7f5 a678\s+udf\.w #22136 ; 0x5678
--- /dev/null
+++ b/gas/testsuite/gas/arm/udf.l
@@ -0,0 +1,3 @@
+^[^:]*: Assembler messages:
+^[^:]*:16: Warning: IT blocks containing 16-bit Thumb instructions of
the following class are deprecated in ARMv8: Short branches,
Undefined, SVC, LDM/STM
+^[^:]*:21: Warning: IT blocks containing 32-bit Thumb instructions
are deprecated in ARMv8
--- /dev/null
+++ b/gas/testsuite/gas/arm/udf.s
@@ -0,0 +1,24 @@
+ .syntax unified
+
+arm: .arm
+ udf
+ udf #0xabcd
+
+thumb: .thumb
+ udf #0xab
+ udf.n #0xcd
+ udf
+ nop
+ udf.w
+ udf #0x1234
+ udf.w #0xccdd
+ it eq
+ udf #0x12
+ udf #0x23
+ udf #0x34
+ udf #0x56
+ it ne
+ udf #0x1234
+ udf #0x2345
+ udf #0x3456
+ udf #0x5678
--- a/opcodes/arm-dis.c
+++ b/opcodes/arm-dis.c
@@ -879,6 +879,8 @@ static const struct opcode32 arm_opcodes[] =
{
/* ARM instructions. */
{ARM_EXT_V1, 0xe1a00000, 0xffffffff, "nop\t\t\t; (mov r0, r0)"},
+ {ARM_EXT_V1, 0xe7f000f0, 0xfff000f0, "udf\t#%e"},
+
{ARM_EXT_V4T | ARM_EXT_V5, 0x012FFF10, 0x0ffffff0, "bx%c\t%0-3r"},
{ARM_EXT_V2, 0x00000090, 0x0fe000f0, "mul%20's%c\t%16-19R, %0-3R, %8-11R"},
{ARM_EXT_V2, 0x00200090, 0x0fe000f0, "mla%20's%c\t%16-19R, %0-3R,
%8-11R, %12-15R"},
@@ -1414,6 +1416,7 @@ static const struct opcode16 thumb_opcodes[] =
/* format 17 */
{ARM_EXT_V4T, 0xDF00, 0xFF00, "svc%c\t%0-7d"},
/* format 16 */
+ {ARM_EXT_V4T, 0xDE00, 0xFF00, "udf%c\t#%0-7d"},
{ARM_EXT_V4T, 0xDE00, 0xFE00, UNDEFINED_INSTRUCTION},
{ARM_EXT_V4T, 0xD000, 0xF000, "b%8-11c.n\t%0-7B%X"},
/* format 18 */
@@ -1534,6 +1537,7 @@ static const struct opcode32 thumb32_opcodes[] =
{ARM_EXT_V6T2, 0xf3af8003, 0xffffffff, "wfi%c.w"},
{ARM_EXT_V6T2, 0xf3af8004, 0xffffffff, "sev%c.w"},
{ARM_EXT_V6T2, 0xf3af8000, 0xffffff00, "nop%c.w\t{%0-7d}"},
+ {ARM_EXT_V6T2, 0xf7f0a000, 0xfff0f000, "udf%c.w\t%H"},

{ARM_EXT_V6T2, 0xf3bf8f2f, 0xffffffff, "clrex%c"},
{ARM_EXT_V6T2, 0xf3af8400, 0xffffff1f, "cpsie.w\t%7'a%6'i%5'f%X"},
@@ -4057,6 +4061,17 @@ print_insn_thumb32 (bfd_vma pc, struct
disassemble_info *info, long given)
}
break;

+ case 'H':
+ {
+ unsigned int imm = 0;
+
+ imm |= (given & 0x000f0000u) >> 4;
+ imm |= (given & 0x00000fffu) >> 0;
+ func (stream, "#%u", imm);
+ value_in_comment = imm;
+ }
+ break;
+
case 'V':
{
unsigned int imm = 0;
Joseph S. Myers
2013-08-31 00:09:02 UTC
Permalink
Post by Roland McGrath
* config/tc-arm.c (T16_32_TAB): Add _udf.
(binutils uses "PR <component>/<number>" notation to refer to bugs, so

PR gas/15914

in these ChangeLog entries.)
--
Joseph S. Myers
***@codesourcery.com
nick clifton
2013-09-04 08:00:56 UTC
Permalink
Hi Roland,
Post by Roland McGrath
gas/
* config/tc-arm.c (T16_32_TAB): Add _udf.
(do_t_udf): New function.
(insns): Add "udf".
gas/testsuite/
* gas/arm/udf-bad.s: New file.
* gas/arm/udf-bad.d: New file.
* gas/arm/udf-bad.l: New file.
* gas/arm/udf.s: New file.
* gas/arm/udf.d: New file.
* gas/arm/udf.l: New file.
opcodes/
* arm-dis.c (arm_opcodes): Add udf.
(thumb_opcodes): Use "udf" mnemonic rather than UNDEFINED_INSTRUCTION.
(thumb32_opcodes): Add udf.w.
(print_insn_thumb32): Handle %H as the thumb32_opcodes comment says.
Approved and applied.

Note - I attached the PR number (15914) to the changelog entries so that
they would show up in the bugzilla database.

Cheers
Nick

Loading...