aboutsummaryrefslogtreecommitdiff
path: root/opcodes/arm-dis.c
diff options
context:
space:
mode:
Diffstat (limited to 'opcodes/arm-dis.c')
-rw-r--r--opcodes/arm-dis.c159
1 files changed, 143 insertions, 16 deletions
diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c
index 005c957..3dfbf5c 100644
--- a/opcodes/arm-dis.c
+++ b/opcodes/arm-dis.c
@@ -816,7 +816,8 @@ static const struct opcode32 neon_opcodes[] =
%e print arm SMI operand (bits 0..7,8..19).
%E print the LSB and WIDTH fields of a BFI or BFC instruction.
- %V print the 16-bit immediate field of a MOVT or MOVW instruction. */
+ %V print the 16-bit immediate field of a MOVT or MOVW instruction.
+ %R print the SPSR/CPSR or banked register of an MRS. */
static const struct opcode32 arm_opcodes[] =
{
@@ -829,6 +830,10 @@ static const struct opcode32 arm_opcodes[] =
{ARM_EXT_V3M, 0x00800090, 0x0fa000f0, "%22?sumull%20's%c\t%12-15Ru, %16-19Ru, %0-3R, %8-11R"},
{ARM_EXT_V3M, 0x00a00090, 0x0fa000f0, "%22?sumlal%20's%c\t%12-15Ru, %16-19Ru, %0-3R, %8-11R"},
+ /* Virtualization Extension instructions. */
+ {ARM_EXT_VIRT, 0x0160006e, 0x0fffffff, "eret%c"},
+ {ARM_EXT_VIRT, 0x01400070, 0x0ff000f0, "hvc%c\t%e"},
+
/* Integer Divide Extension instructions. */
{ARM_EXT_ADIV, 0x0710f010, 0x0ff0f0f0, "sdiv%c\t%16-19r, %0-3r, %8-11r"},
{ARM_EXT_ADIV, 0x0730f010, 0x0ff0f0f0, "udiv%c\t%16-19r, %0-3r, %8-11r"},
@@ -1091,8 +1096,9 @@ static const struct opcode32 arm_opcodes[] =
{ARM_EXT_V1, 0x00e00000, 0x0fe00010, "rsc%20's%c\t%12-15r, %16-19r, %o"},
{ARM_EXT_V1, 0x00e00010, 0x0fe00090, "rsc%20's%c\t%12-15R, %16-19R, %o"},
- {ARM_EXT_V3, 0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"},
- {ARM_EXT_V3, 0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15R, %22?SCPSR"},
+ {ARM_EXT_VIRT, 0x0120f200, 0x0fb0f200, "msr%c\t%C, %0-3r"},
+ {ARM_EXT_V3, 0x0120f000, 0x0db0f000, "msr%c\t%C, %o"},
+ {ARM_EXT_V3, 0x01000000, 0x0fb00cff, "mrs%c\t%12-15R, %R"},
{ARM_EXT_V1, 0x03000000, 0x0fe00000, "tst%p%c\t%16-19r, %o"},
{ARM_EXT_V1, 0x01000000, 0x0fe00010, "tst%p%c\t%16-19r, %o"},
@@ -1103,7 +1109,6 @@ static const struct opcode32 arm_opcodes[] =
{ARM_EXT_V1, 0x01200010, 0x0fe00090, "teq%p%c\t%16-19R, %o"},
{ARM_EXT_V1, 0x03400000, 0x0fe00000, "cmp%p%c\t%16-19r, %o"},
- {ARM_EXT_V3, 0x01400000, 0x0ff00010, "mrs%c\t%12-15R, %22?SCPSR"},
{ARM_EXT_V1, 0x01400000, 0x0fe00010, "cmp%p%c\t%16-19r, %o"},
{ARM_EXT_V1, 0x01400010, 0x0fe00090, "cmp%p%c\t%16-19R, %o"},
@@ -1313,6 +1318,7 @@ static const struct opcode16 thumb_opcodes[] =
%M print a modified 12-bit immediate (same location)
%J print a 16-bit immediate from hw1[3:0,10],hw2[14:12,7:0]
%K print a 16-bit immediate from hw2[3:0],hw1[3:0],hw2[11:4]
+ %H print a 16-bit immediate from hw2[3:0],hw1[11:0]
%S print a possibly-shifted Rm
%a print the address of a plain load/store
@@ -1360,6 +1366,10 @@ static const struct opcode32 thumb32_opcodes[] =
{ARM_EXT_DIV, 0xfb90f0f0, 0xfff0f0f0, "sdiv%c\t%8-11r, %16-19r, %0-3r"},
{ARM_EXT_DIV, 0xfbb0f0f0, 0xfff0f0f0, "udiv%c\t%8-11r, %16-19r, %0-3r"},
+ /* Virtualization Extension instructions. */
+ {ARM_EXT_VIRT, 0xf7e08000, 0xfff0f000, "hvc%c\t%V"},
+ /* We skip ERET as that is SUBS pc, lr, #0. */
+
/* MP Extension instructions. */
{ARM_EXT_MP, 0xf830f000, 0xff70f000, "pldw%c\t%a"},
@@ -1380,7 +1390,7 @@ static const struct opcode32 thumb32_opcodes[] =
{ARM_EXT_V6T2, 0xf3c08f00, 0xfff0ffff, "bxj%c\t%16-19r%x"},
{ARM_EXT_V6T2, 0xe810c000, 0xffd0ffff, "rfedb%c\t%16-19r%21'!"},
{ARM_EXT_V6T2, 0xe990c000, 0xffd0ffff, "rfeia%c\t%16-19r%21'!"},
- {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff000, "mrs%c\t%8-11r, %D"},
+ {ARM_EXT_V6T2, 0xf3e08000, 0xffe0f000, "mrs%c\t%8-11r, %D"},
{ARM_EXT_V6T2, 0xf3af8100, 0xffffffe0, "cps\t#%0-4d%X"},
{ARM_EXT_V6T2, 0xe8d0f000, 0xfff0fff0, "tbb%c\t[%16-19r, %0-3r]%x"},
{ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh%c\t[%16-19r, %0-3r, lsl #1]%x"},
@@ -2862,6 +2872,52 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
return FALSE;
}
+/* Return the name of a v7A special register. */
+
+static const char *
+banked_regname (unsigned reg)
+{
+ switch (reg)
+ {
+ case 15: return "CPSR";
+ case 32: return "R8_usr";
+ case 33: return "R9_usr";
+ case 34: return "R10_usr";
+ case 35: return "R11_usr";
+ case 36: return "R12_usr";
+ case 37: return "SP_usr";
+ case 38: return "LR_usr";
+ case 40: return "R8_fiq";
+ case 41: return "R9_fiq";
+ case 42: return "R10_fiq";
+ case 43: return "R11_fiq";
+ case 44: return "R12_fiq";
+ case 45: return "SP_fiq";
+ case 46: return "LR_fiq";
+ case 48: return "LR_irq";
+ case 49: return "SP_irq";
+ case 50: return "LR_svc";
+ case 51: return "SP_svc";
+ case 52: return "LR_abt";
+ case 53: return "SP_abt";
+ case 54: return "LR_und";
+ case 55: return "SP_und";
+ case 60: return "LR_mon";
+ case 61: return "SP_mon";
+ case 62: return "ELR_hyp";
+ case 63: return "SP_hyp";
+ case 79: return "SPSR";
+ case 110: return "SPSR_fiq";
+ case 112: return "SPSR_irq";
+ case 114: return "SPSR_svc";
+ case 116: return "SPSR_abt";
+ case 118: return "SPSR_und";
+ case 124: return "SPSR_mon";
+ case 126: return "SPSR_hyp";
+ default: return NULL;
+ }
+}
+
/* Print one ARM instruction from PC on INFO->STREAM. */
static void
@@ -3156,15 +3212,32 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
break;
case 'C':
- func (stream, "_");
- if (given & 0x80000)
- func (stream, "f");
- if (given & 0x40000)
- func (stream, "s");
- if (given & 0x20000)
- func (stream, "x");
- if (given & 0x10000)
- func (stream, "c");
+ if ((given & 0x02000200) == 0x200)
+ {
+ const char * name;
+ unsigned sysm = (given & 0x004f0000) >> 16;
+
+ sysm |= (given & 0x300) >> 4;
+ name = banked_regname (sysm);
+
+ if (name != NULL)
+ func (stream, "%s", name);
+ else
+ func (stream, "(UNDEF: %lu)", sysm);
+ }
+ else
+ {
+ func (stream, "%cPSR_",
+ (given & 0x00400000) ? 'S' : 'C');
+ if (given & 0x80000)
+ func (stream, "f");
+ if (given & 0x40000)
+ func (stream, "s");
+ if (given & 0x20000)
+ func (stream, "x");
+ if (given & 0x10000)
+ func (stream, "c");
+ }
break;
case 'U':
@@ -3302,6 +3375,22 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
}
break;
+ case 'R':
+ /* Get the PSR/banked register name. */
+ {
+ const char * name;
+ unsigned sysm = (given & 0x004f0000) >> 16;
+
+ sysm |= (given & 0x300) >> 4;
+ name = banked_regname (sysm);
+
+ if (name != NULL)
+ func (stream, "%s", name);
+ else
+ func (stream, "(UNDEF: %lu)", sysm);
+ }
+ break;
+
case 'V':
/* 16-bit unsigned immediate from a MOVT or MOVW
instruction, encoded in bits 0:11 and 15:19. */
@@ -3746,6 +3835,17 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
}
break;
+ case 'V':
+ {
+ unsigned int imm = 0;
+
+ imm |= (given & 0x00000fffu);
+ imm |= (given & 0x000f0000u) >> 4;
+ func (stream, "#%u", imm);
+ value_in_comment = imm;
+ }
+ break;
+
case 'S':
{
unsigned int reg = (given & 0x0000000fu);
@@ -4070,6 +4170,20 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
if (given & 0x100)
func (stream, "c");
}
+ else if ((given & 0x20) == 0x20)
+ {
+ char const* name;
+ unsigned sysm = (given & 0xf00) >> 8;
+
+ sysm |= (given & 0x30);
+ sysm |= (given & 0x00100000) >> 14;
+ name = banked_regname (sysm);
+
+ if (name != NULL)
+ func (stream, "%s", name);
+ else
+ func (stream, "(UNDEF: %lu)", sysm);
+ }
else
{
func (stream, psr_name (given & 0xff));
@@ -4077,8 +4191,21 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
break;
case 'D':
- if ((given & 0xff) == 0)
- func (stream, "%cPSR", (given & 0x100000) ? 'S' : 'C');
+ if (((given & 0xff) == 0)
+ || ((given & 0x20) == 0x20))
+ {
+ char const* name;
+ unsigned sm = (given & 0xf0000) >> 16;
+
+ sm |= (given & 0x30);
+ sm |= (given & 0x00100000) >> 14;
+ name = banked_regname (sm);
+
+ if (name != NULL)
+ func (stream, "%s", name);
+ else
+ func (stream, "(UNDEF: %lu)", sm);
+ }
else
func (stream, psr_name (given & 0xff));
break;