diff options
Diffstat (limited to 'opcodes/arm-dis.c')
-rw-r--r-- | opcodes/arm-dis.c | 159 |
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; |