[binutils, ARM, 16/16] Add support to VLDR and VSTR of system registers

GNU as' Arm backend assumes each mnemonic has a single entry in the instruction table but VLDR (system register) and VSTR (system register) are different instructions than VLDR and VSTR. It is thus necessary to add some form of demultiplexing in the parser. It starts by creating a new operand type OP_VLDR which indicate that the operand is either the existing OP_RVSD operand or a system register. The function parse_operands () then tries these two cases in order, calling the new parse_sys_vldr_vstr for the second case.

Since the encoding function is specified in the instruction table entry, it also need to have some sort of demultiplexing. This is done in do_vldr_vstr which either calls the existing do_neon_ldr_str () or calls the new do_t_vldr_vstr_sysreg ().

A new internal relocation is needed as well since the offset has a shorter range than in other Thumb coprocessor instructions. Disassembly also requires special care since VSTR (system register) reuse the STC encoding with the coprocessor number 15. Armv8.1-M Mainline ARM manual states that coprocessor 8, 14 and 15 are reserved for floating-point and MVE instructions a feature bit check is added if the coprocessor number is one of this value and we are trying to match a coprocessor instruction (eg. STC) to forbid the match.

ChangeLog entries are as follows:

*** bfd/ChangeLog ***

2019-04-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>

	* reloc.c (BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM): New internal
	relocation.
	* bfd-in2.h: Regenerate.
	* libbfd.h: Likewise.

*** gas/ChangeLog ***

2019-04-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>

	* config/tc-arm.c (parse_sys_vldr_vstr): New function.
	(OP_VLDR): New enum operand_parse_code enumerator.
	(parse_operands): Add logic for OP_VLDR.
	(do_t_vldr_vstr_sysreg): New function.
	(do_vldr_vstr): Likewise.
	(insns): Guard VLDR and VSTR by arm_ext_v4t for Thumb mode.
	(md_apply_fix): Add bound check for VLDR and VSTR co-processor offset.
	Add masking logic for BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM relocation.
	* testsuite/gas/arm/archv8m_1m-cmse-main-bad.s: Add examples of bad
	uses of VLDR and VSTR.
	* testsuite/gas/arm/archv8m_1m-cmse-main-bad.l: Add error messages for
	above bad uses.
	* testsuite/gas/arm/archv8m_1m-cmse-main.s: Add examples of VLDR and
	VSTR valid uses.
	* testsuite/gas/arm/archv8m_1m-cmse-main.d: Add disassembly for the
	above examples.

*** opcodes/ChangeLog ***

2019-04-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>

	* arm-dis.c (coprocessor_opcodes): Document new %J and %K format
	specifier.  Add entries for VLDR and VSTR of system registers.
	(print_insn_coprocessor): Forbid coprocessor numbers 8, 14 and 15 in
	coprocessor instructions on Armv8.1-M Mainline targets.  Add handling
	of %J and %K format specifier.
This commit is contained in:
Andre Vieira 2019-04-15 12:23:24 +01:00
parent efd6b3591b
commit 32c36c3ce9
12 changed files with 295 additions and 5 deletions

View File

@ -1,3 +1,10 @@
2019-04-15 Thomas Preud'homme <thomas.preudhomme@arm.com>
* reloc.c (BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM): New internal
relocation.
* bfd-in2.h: Regenerate.
* libbfd.h: Likewise.
2019-04-15 Sudakshina Das <sudi.das@arm.com>
* reloc.c (BFD_RELOC_ARM_THUMB_LOOP12): New.

View File

@ -3722,6 +3722,7 @@ pc-relative or some form of GOT-indirect relocation. */
BFD_RELOC_ARM_CP_OFF_IMM_S2,
BFD_RELOC_ARM_T32_CP_OFF_IMM,
BFD_RELOC_ARM_T32_CP_OFF_IMM_S2,
BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM,
BFD_RELOC_ARM_ADR_IMM,
BFD_RELOC_ARM_LDR_IMM,
BFD_RELOC_ARM_LITERAL,

View File

@ -1634,6 +1634,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_ARM_CP_OFF_IMM_S2",
"BFD_RELOC_ARM_T32_CP_OFF_IMM",
"BFD_RELOC_ARM_T32_CP_OFF_IMM_S2",
"BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM",
"BFD_RELOC_ARM_ADR_IMM",
"BFD_RELOC_ARM_LDR_IMM",
"BFD_RELOC_ARM_LITERAL",

View File

@ -3292,6 +3292,8 @@ ENUMX
BFD_RELOC_ARM_T32_CP_OFF_IMM
ENUMX
BFD_RELOC_ARM_T32_CP_OFF_IMM_S2
ENUMX
BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM
ENUMX
BFD_RELOC_ARM_ADR_IMM
ENUMX

View File

@ -1,3 +1,22 @@
2019-04-15 Thomas Preud'homme <thomas.preudhomme@arm.com>
* config/tc-arm.c (parse_sys_vldr_vstr): New function.
(OP_VLDR): New enum operand_parse_code enumerator.
(parse_operands): Add logic for OP_VLDR.
(do_t_vldr_vstr_sysreg): New function.
(do_vldr_vstr): Likewise.
(insns): Guard VLDR and VSTR by arm_ext_v4t for Thumb mode.
(md_apply_fix): Add bound check for VLDR and VSTR co-processor offset.
Add masking logic for BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM relocation.
* testsuite/gas/arm/archv8m_1m-cmse-main-bad.s: Add examples of bad
uses of VLDR and VSTR.
* testsuite/gas/arm/archv8m_1m-cmse-main-bad.l: Add error messages for
above bad uses.
* testsuite/gas/arm/archv8m_1m-cmse-main.s: Add examples of VLDR and
VSTR valid uses.
* testsuite/gas/arm/archv8m_1m-cmse-main.d: Add disassembly for the
above examples.
2019-04-15 Thomas Preud'homme <thomas.preudhomme@arm.com>
* config/tc-arm.c (arm_typed_reg_parse): Fix typo in comment.

View File

@ -6128,6 +6128,39 @@ check_suffix:
return FAIL;
}
static int
parse_sys_vldr_vstr (char **str)
{
unsigned i;
int val = FAIL;
struct {
const char *name;
int regl;
int regh;
} sysregs[] = {
{"FPSCR", 0x1, 0x0},
{"FPSCR_nzcvqc", 0x2, 0x0},
{"VPR", 0x4, 0x1},
{"P0", 0x5, 0x1},
{"FPCXTNS", 0x6, 0x1},
{"FPCXTS", 0x7, 0x1}
};
char *op_end = strchr (*str, ',');
size_t op_strlen = op_end - *str;
for (i = 0; i < sizeof (sysregs) / sizeof (sysregs[0]); i++)
{
if (!strncmp (*str, sysregs[i].name, op_strlen))
{
val = sysregs[i].regl | (sysregs[i].regh << 3);
*str = op_end;
break;
}
}
return val;
}
/* Parse the flags argument to CPSI[ED]. Returns FAIL on error, or a
value suitable for splatting into the AIF field of the instruction. */
@ -6652,6 +6685,7 @@ enum operand_parse_code
OP_RNDQ_Ibig, /* Neon D or Q reg, or big immediate for logic and VMVN. */
OP_RNDQ_I63b, /* Neon D or Q reg, or immediate for shift. */
OP_RIWR_I32z, /* iWMMXt wR register, or immediate 0 .. 32 for iWMMXt2. */
OP_VLDR, /* VLDR operand. */
OP_I0, /* immediate zero */
OP_I7, /* immediate value 0 .. 7 */
@ -7225,6 +7259,13 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
val = parse_psr (&str, op_parse_code == OP_wPSR);
break;
case OP_VLDR:
po_reg_or_goto (REG_TYPE_VFSD, try_sysreg);
break;
try_sysreg:
val = parse_sys_vldr_vstr (&str);
break;
case OP_APSR_RR:
po_reg_or_goto (REG_TYPE_RN, try_apsr);
break;
@ -7401,6 +7442,10 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
inst.error = BAD_PC;
break;
case OP_VLDR:
if (inst.operands[i].isreg)
break;
/* fall through. */
case OP_CPSF:
case OP_ENDI:
case OP_oROR:
@ -17397,6 +17442,55 @@ do_neon_ldr_str (void)
}
}
static void
do_t_vldr_vstr_sysreg (void)
{
int fp_vldr_bitno = 20, sysreg_vldr_bitno = 20;
bfd_boolean is_vldr = ((inst.instruction & (1 << fp_vldr_bitno)) != 0);
/* Use of PC is UNPREDICTABLE. */
if (inst.operands[1].reg == REG_PC)
inst.error = _("Use of PC here is UNPREDICTABLE");
if (inst.operands[1].immisreg)
inst.error = _("instruction does not accept register index");
if (!inst.operands[1].isreg)
inst.error = _("instruction does not accept PC-relative addressing");
if (abs (inst.operands[1].imm) >= (1 << 7))
inst.error = _("immediate value out of range");
inst.instruction = 0xec000f80;
if (is_vldr)
inst.instruction |= 1 << sysreg_vldr_bitno;
encode_arm_cp_address (1, TRUE, FALSE, BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM);
inst.instruction |= (inst.operands[0].imm & 0x7) << 13;
inst.instruction |= (inst.operands[0].imm & 0x8) << 19;
}
static void
do_vldr_vstr (void)
{
bfd_boolean sysreg_op = !inst.operands[0].isreg;
/* VLDR/VSTR (System Register). */
if (sysreg_op)
{
if (!mark_feature_used (&arm_ext_v8_1m_main))
as_bad (_("Instruction not permitted on this architecture"));
do_t_vldr_vstr_sysreg ();
}
/* VLDR/VSTR. */
else
{
if (!mark_feature_used (&fpu_vfp_ext_v1xd))
as_bad (_("Instruction not permitted on this architecture"));
do_neon_ldr_str ();
}
}
/* "interleave" version also handles non-interleaving register VLD1/VST1
instructions. */
@ -21284,8 +21378,6 @@ static const struct asm_opcode insns[] =
NCE(vstm, c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
NCE(vstmia, c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
NCE(vstmdb, d000b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
NCE(vldr, d100b00, 2, (RVSD, ADDRGLDC), neon_ldr_str),
NCE(vstr, d000b00, 2, (RVSD, ADDRGLDC), neon_ldr_str),
nCEF(vcvt, _vcvt, 3, (RNSDQ, RNSDQ, oI32z), neon_cvt),
nCEF(vcvtr, _vcvt, 2, (RNSDQ, RNSDQ), neon_cvtr),
@ -21297,6 +21389,15 @@ static const struct asm_opcode insns[] =
NCE(vmov, 0, 1, (VMOV), neon_mov),
NCE(vmovq, 0, 1, (VMOV), neon_mov),
#undef THUMB_VARIANT
/* Could be either VLDR/VSTR or VLDR/VSTR (system register) which are guarded
by different feature bits. Since we are setting the Thumb guard, we can
require Thumb-1 which makes it a nop guard and set the right feature bit in
do_vldr_vstr (). */
#define THUMB_VARIANT & arm_ext_v4t
NCE(vldr, d100b00, 2, (VLDR, ADDRGLDC), vldr_vstr),
NCE(vstr, d000b00, 2, (VLDR, ADDRGLDC), vldr_vstr),
#undef ARM_VARIANT
#define ARM_VARIANT & arm_ext_fp16
#undef THUMB_VARIANT
@ -24548,6 +24649,7 @@ md_apply_fix (fixS * fixP,
case BFD_RELOC_ARM_CP_OFF_IMM:
case BFD_RELOC_ARM_T32_CP_OFF_IMM:
case BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM:
if (fixP->fx_r_type == BFD_RELOC_ARM_CP_OFF_IMM)
newval = md_chars_to_number (buf, INSN_SIZE);
else
@ -24561,6 +24663,12 @@ md_apply_fix (fixS * fixP,
as_bad_where (fixP->fx_file, fixP->fx_line,
_("co-processor offset out of range"));
}
else if ((newval & 0xfe001f80) == 0xec000f80)
{
if (value < -511 || value > 512 || (value & 3))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("co-processor offset out of range"));
}
else if (value < -1023 || value > 1023 || (value & 3))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("co-processor offset out of range"));
@ -24574,10 +24682,18 @@ md_apply_fix (fixS * fixP,
else
newval = get_thumb32_insn (buf);
if (value == 0)
newval &= 0xffffff00;
{
if (fixP->fx_r_type == BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM)
newval &= 0xffffff80;
else
newval &= 0xffffff00;
}
else
{
newval &= 0xff7fff00;
if (fixP->fx_r_type == BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM)
newval &= 0xff7fff80;
else
newval &= 0xff7fff00;
if ((newval & 0x0f200f00) == 0x0d000900)
{
/* This is a fp16 vstr/vldr.

View File

@ -6,3 +6,11 @@
[^:]*:11: Error: VPR expected last -- `vscclrm {s0}'
[^:]*:12: Error: VFP single precision register or VPR expected -- `vscclrm {s1,d1,VPR}'
[^:]*:13: Error: VFP single precision register expected -- `vscclrm {s1-d1,VPR}'
[^:]*:15: Error: syntax error -- `vldr APSR,\[r2\]'
[^:]*:20: Error: syntax error -- `vstr APSR,\[r2\]'
[^:]*:16: Error: co-processor offset out of range
[^:]*:17: Error: co-processor offset out of range
[^:]*:18: Error: co-processor offset out of range
[^:]*:21: Error: co-processor offset out of range
[^:]*:22: Error: co-processor offset out of range
[^:]*:23: Error: co-processor offset out of range

View File

@ -11,3 +11,13 @@ vscclrm {} @ Rejects empty list
vscclrm {s0} @ Rejects list without VPR
vscclrm {s1, d1, VPR} @ Reject mix of single and double-precision VFP registers
vscclrm {s1-d1, VPR} @ Likewise when using a range
vldr APSR, [r2] @ Rejects incorrect system register
vldr FPSCR, [r2, #2] @ Rejects invalid immediate for offset variant
vldr FPSCR, [r2, #2]! @ Likewise for pre-index variant
vldr FPSCR, [r2], #2 @ Likewise for post-index variant
vstr APSR, [r2] @ Rejects incorrect system register
vstr FPSCR, [r2, #2] @ Rejects invalid immediate for offset variant
vstr FPSCR, [r2, #2]! @ Likewise for pre-index variant
vstr FPSCR, [r2], #2 @ Likewise for post-index variant

View File

@ -20,4 +20,38 @@ Disassembly of section .text:
0+.* <[^>]*> ec9f 0b20 vscclrm {d0-d15, VPR}
0+.* <[^>]*> bf18 it ne
0+.* <[^>]*> ecdf 1a01 vscclrmne {s3, VPR}
0+.* <[^>]*> ed92 2f80 vldr FPSCR, \[r2\]
0+.* <[^>]*> ed92 2f82 vldr FPSCR, \[r2, #8\]
0+.* <[^>]*> ed92 2f82 vldr FPSCR, \[r2, #8\]
0+.* <[^>]*> ed12 2f82 vldr FPSCR, \[r2, #-8\]
0+.* <[^>]*> edb2 2f82 vldr FPSCR, \[r2, #8\]!
0+.* <[^>]*> edb2 2f82 vldr FPSCR, \[r2, #8\]!
0+.* <[^>]*> ed32 2f82 vldr FPSCR, \[r2, #-8\]!
0+.* <[^>]*> ecb2 2f82 vldr FPSCR, \[r2\], #8
0+.* <[^>]*> ecb2 2f82 vldr FPSCR, \[r2\], #8
0+.* <[^>]*> ec32 2f82 vldr FPSCR, \[r2\], #-8
0+.* <[^>]*> ed93 4f80 vldr FPSCR_nzcvqc, \[r3\]
0+.* <[^>]*> edd3 8f80 vldr VPR, \[r3\]
0+.* <[^>]*> edd3 af80 vldr P0, \[r3\]
0+.* <[^>]*> edd3 cf80 vldr FPCXTNS, \[r3\]
0+.* <[^>]*> edd3 ef80 vldr FPCXTS, \[r3\]
0+.* <[^>]*> bfa8 it ge
0+.* <[^>]*> edd3 ef80 vldrge FPCXTS, \[r3\]
0+.* <[^>]*> ed82 2f80 vstr FPSCR, \[r2\]
0+.* <[^>]*> ed82 2f82 vstr FPSCR, \[r2, #8\]
0+.* <[^>]*> ed82 2f82 vstr FPSCR, \[r2, #8\]
0+.* <[^>]*> ed02 2f82 vstr FPSCR, \[r2, #-8\]
0+.* <[^>]*> eda2 2f82 vstr FPSCR, \[r2, #8\]!
0+.* <[^>]*> eda2 2f82 vstr FPSCR, \[r2, #8\]!
0+.* <[^>]*> ed22 2f82 vstr FPSCR, \[r2, #-8\]!
0+.* <[^>]*> eca2 2f82 vstr FPSCR, \[r2\], #8
0+.* <[^>]*> eca2 2f82 vstr FPSCR, \[r2\], #8
0+.* <[^>]*> ec22 2f82 vstr FPSCR, \[r2\], #-8
0+.* <[^>]*> ed83 4f80 vstr FPSCR_nzcvqc, \[r3\]
0+.* <[^>]*> edc3 8f80 vstr VPR, \[r3\]
0+.* <[^>]*> edc3 af80 vstr P0, \[r3\]
0+.* <[^>]*> edc3 cf80 vstr FPCXTNS, \[r3\]
0+.* <[^>]*> edc3 ef80 vstr FPCXTS, \[r3\]
0+.* <[^>]*> bfa8 it ge
0+.* <[^>]*> edc3 ef80 vstrge FPCXTS, \[r3\]
#...

View File

@ -18,3 +18,37 @@ vscclrm {s0-s31, VPR} @ Accept all single-precision VFP registers and VPR
@ together
vscclrm {d0-d15, VPR} @ Likewise for double-precision VFP registers
vscclrmne {s3, VPR} @ Accepts conditional execution
vldr FPSCR, [r2] @ Accepts offset variant without immediate
vldr FPSCR, [r2, #8] @ Likewise but with immediate without sign
vldr FPSCR, [r2, #+8] @ Likewise but with positive sign
vldr FPSCR, [r2, #-8] @ Likewise but with negative sign
vldr FPSCR, [r2, #8]! @ Accepts pre-index variant with immediate without sign
vldr FPSCR, [r2, #+8]! @ Likewise but with positive sign
vldr FPSCR, [r2, #-8]! @ Likewise but with negative sign
vldr FPSCR, [r2], #8 @ Accepts post-index variant with immediate without sign
vldr FPSCR, [r2], #+8 @ Likewise but with positive sign
vldr FPSCR, [r2], #-8 @ Likewise but with negative sign
vldr FPSCR_nzcvqc, [r3] @ Accepts FPSCR_nzcvqc system register
vldr VPR, [r3] @ Accepts VPR system register
vldr P0, [r3] @ Accepts P0 system register
vldr FPCXTNS, [r3] @ Accepts FPCXTNS system register
vldr FPCXTS, [r3] @ Accepts FPCXTS system register
vldrge FPCXTS, [r3] @ Accepts conditional execution
vstr FPSCR, [r2] @ Accepts offset variant without immediate
vstr FPSCR, [r2, #8] @ Likewise but with immediate without sign
vstr FPSCR, [r2, #+8] @ Likewise but with positive sign
vstr FPSCR, [r2, #-8] @ Likewise but with negative sign
vstr FPSCR, [r2, #8]! @ Accepts pre-index variant with immediate without sign
vstr FPSCR, [r2, #+8]! @ Likewise but with positive sign
vstr FPSCR, [r2, #-8]! @ Likewise but with negative sign
vstr FPSCR, [r2], #8 @ Accepts post-index variant with immediate without sign
vstr FPSCR, [r2], #+8 @ Likewise but with positive sign
vstr FPSCR, [r2], #-8 @ Likewise but with negative sign
vstr FPSCR_nzcvqc, [r3] @ Accepts FPSCR_nzcvqc system register
vstr VPR, [r3] @ Accepts VPR system register
vstr P0, [r3] @ Accepts P0 system register
vstr FPCXTNS, [r3] @ Accepts FPCXTNS system register
vstr FPCXTS, [r3] @ Accepts FPCXTS system register
vstrge FPCXTS, [r3] @ Accepts conditional execution

View File

@ -1,3 +1,11 @@
2019-04-15 Thomas Preud'homme <thomas.preudhomme@arm.com>
* arm-dis.c (coprocessor_opcodes): Document new %J and %K format
specifier. Add entries for VLDR and VSTR of system registers.
(print_insn_coprocessor): Forbid coprocessor numbers 8, 14 and 15 in
coprocessor instructions on Armv8.1-M Mainline targets. Add handling
of %J and %K format specifier.
2019-04-15 Thomas Preud'homme <thomas.preudhomme@arm.com>
* arm-dis.c (coprocessor_opcodes): Document new %C format control code.

View File

@ -111,6 +111,8 @@ struct opcode16
%B print vstm/vldm register list
%C print vscclrm register list
%I print cirrus signed shift immediate: bits 0..3|4..6
%J print register for VLDR instruction
%K print address for VLDR instruction
%F print the COUNT field of a LFM/SFM instruction.
%P print floating point precision in arithmetic insn
%Q print floating point precision in ldf/stf insn
@ -471,6 +473,10 @@ static const struct sopcode32 coprocessor_opcodes[] =
0x0d000a00, 0x0f300f00, "vstr%c\t%y1, %A"},
{ANY, ARM_FEATURE_COPROC (FPU_VFP_EXT_V1xD),
0x0d100a00, 0x0f300f00, "vldr%c\t%y1, %A"},
{ANY, ARM_FEATURE_COPROC (ARM_EXT2_V8_1M_MAIN),
0xec100f80, 0xfe101f80, "vldr%c\t%J, %K"},
{ANY, ARM_FEATURE_COPROC (ARM_EXT2_V8_1M_MAIN),
0xec000f80, 0xfe101f80, "vstr%c\t%J, %K"},
{ANY, ARM_FEATURE_COPROC (FPU_VFP_EXT_V1xD),
0x0d200b01, 0x0fb00f01, "fstmdbx%c\t%16-19r!, %z3\t;@ Deprecated"},
@ -3462,6 +3468,8 @@ print_insn_coprocessor (bfd_vma pc,
int cp_num;
struct arm_private_data *private_data = info->private_data;
arm_feature_set allowed_arches = ARM_ARCH_NONE;
arm_feature_set arm_ext_v8_1m_main =
ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_1M_MAIN);
allowed_arches = private_data->features;
@ -3557,23 +3565,34 @@ print_insn_coprocessor (bfd_vma pc,
/* Floating-point instructions. */
if (cp_num == 9 || cp_num == 10 || cp_num == 11)
continue;
/* Armv8.1-M Mainline FP & MVE instructions. */
if (ARM_CPU_HAS_FEATURE (arm_ext_v8_1m_main, allowed_arches)
&& !ARM_CPU_IS_ANY (allowed_arches)
&& (cp_num == 8 || cp_num == 14 || cp_num == 15))
continue;
}
for (c = insn->assembler; *c; c++)
{
if (*c == '%')
{
switch (*++c)
const char mod = *++c;
switch (mod)
{
case '%':
func (stream, "%%");
break;
case 'A':
case 'K':
{
int rn = (given >> 16) & 0xf;
bfd_vma offset = given & 0xff;
if (mod == 'K')
offset = given & 0x7f;
func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
if (PRE_BIT_SET || WRITEBACK_BIT_SET)
@ -3705,6 +3724,37 @@ print_insn_coprocessor (bfd_vma pc,
break;
case 'J':
{
int regno = ((given >> 19) & 0x8) | ((given >> 13) & 0x7);
switch (regno)
{
case 0x1:
func (stream, "FPSCR");
break;
case 0x2:
func (stream, "FPSCR_nzcvqc");
break;
case 0xc:
func (stream, "VPR");
break;
case 0xd:
func (stream, "P0");
break;
case 0xe:
func (stream, "FPCXTNS");
break;
case 0xf:
func (stream, "FPCXTS");
break;
default:
func (stream, "<invalid reg %d>", regno);
break;
}
}
break;
case 'F':
switch (given & 0x00408000)
{