This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Thumb32 assembler (46/69)
- From: Zack Weinberg <zack at codesourcery dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Tue, 26 Apr 2005 02:55:40 -0700
- Subject: Thumb32 assembler (46/69)
Refactor coprocessor address parsing for use via parse_operands; this
allows conversion of most of the remaining coprocessor encode
functions, and friendlier diagnostics for some ill-formed VFP
instructions.
zw
* config/tc-arm.c (struct arm_it): Add postind field to operands;
reorder operands bitfields to put all address bits together.
(CP_T_PRE, CP_T_UD, CP_T_WB): Delete.
(cp_address_required_here): Split into parse_cp_address and
encode_cp_address_arm. Restructure for use via parse_operands.
(OP_I4): Rename OP_bI4.
(OP_CADDR, OP_RIWR_RIWC): New operand parse codes.
(parse_operands): Support new codes. Do not require prefix for bI4.
(do_lstc, do_vfp_sp_ldst, do_vfp_dp_ldst, dp_fpa_ldst, do_fpa_ldmstm)
(do_iwmmxt_wldst, do_iwmmxt_wldstw, do_mav_ldst): Use parse_operands.
(do_mav_ldst_1, do_mav_ldst_2, do_mav_ldst_3, do_mav_ldst_4):
Update to match.
(md_apply_fix3): Share most code between BFD_RELOC_ARM_CP_OFF_IMM and
BFD_RELOC_ARM_CP_OFF_IMM_S2. For these, clear WRITE_BACK if value is
zero.
* testsuite/gas/arm/vfp-bad.l: Adjust expected diagnostics.
===================================================================
Index: gas/testsuite/gas/arm/vfp-bad.l
--- gas/testsuite/gas/arm/vfp-bad.l (revision 48)
+++ gas/testsuite/gas/arm/vfp-bad.l (revision 49)
@@ -1,9 +1,9 @@
[^:]*: Assembler messages:
-[^:]*:4: Error: garbage following instruction -- `fstd d0,\[r0\],#8'
-[^:]*:5: Error: garbage following instruction -- `fstd d0,\[r0,#-8\]!'
-[^:]*:6: Error: garbage following instruction -- `fsts s0,\[r0\],#8'
-[^:]*:7: Error: garbage following instruction -- `fsts s0,\[r0,#-8\]!'
-[^:]*:8: Error: garbage following instruction -- `fldd d0,\[r0\],#8'
-[^:]*:9: Error: garbage following instruction -- `fldd d0,\[r0,#-8\]!'
-[^:]*:10: Error: garbage following instruction -- `flds s0,\[r0\],#8'
-[^:]*:11: Error: garbage following instruction -- `flds s0,\[r0,#-8\]!'
+[^:]*:4: Error: instruction does not support writeback -- `fstd d0,\[r0\],#8'
+[^:]*:5: Error: instruction does not support writeback -- `fstd d0,\[r0,#-8\]!'
+[^:]*:6: Error: instruction does not support writeback -- `fsts s0,\[r0\],#8'
+[^:]*:7: Error: instruction does not support writeback -- `fsts s0,\[r0,#-8\]!'
+[^:]*:8: Error: instruction does not support writeback -- `fldd d0,\[r0\],#8'
+[^:]*:9: Error: instruction does not support writeback -- `fldd d0,\[r0,#-8\]!'
+[^:]*:10: Error: instruction does not support writeback -- `flds s0,\[r0\],#8'
+[^:]*:11: Error: instruction does not support writeback -- `flds s0,\[r0,#-8\]!'
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c (revision 48)
+++ gas/config/tc-arm.c (revision 49)
@@ -198,9 +198,11 @@
int present : 1; /* operand present */
int isreg : 1; /* operand was a register */
int immisreg : 1; /* .imm field is a second register */
- int writeback : 1; /* operand has trailing ! */
int hasreloc : 1; /* operand has relocation suffix */
- int postind : 1; /* operand is post-indexed */
+ int writeback : 1; /* operand has trailing ! */
+ int preind : 1; /* preindexed address */
+ int postind : 1; /* postindexed address */
+ int negative : 1; /* index register was negated */
} operands[6];
};
@@ -287,9 +289,6 @@
#define CP_T_X 0x00008000
#define CP_T_Y 0x00400000
-#define CP_T_Pre 0x01000000
-#define CP_T_UD 0x00800000
-#define CP_T_WB 0x00200000
#define CONDS_BIT 0x00100000
#define LOAD_BIT 0x00100000
@@ -2096,141 +2095,155 @@
return FAIL;
}
+/* Parse a coprocessor address expression:
+
+ [Rl]{!} shorthand for [Rl,#0]{!}
+ [Rl,offset]{!} +-8 bits, *4 (usually) - preindex, opt. writeback
+ [Rl],offset +-8 bits, *4 (usually) - postindex
+ [Rl],\{number\} 8 bits - no relocation - "unindexed" (magic)
+ label translated to [PC, offset]
+
+ Data is written to inst.operands[i] and/or inst.reloc.exp.
+ Returns SUCCESS or FAIL. Does not check for no-writeback / no-unindex. */
+
static int
-cp_address_required_here (char ** str, int wb_ok, int reloc)
+parse_cp_address (char **str, int i)
{
- char * p = * str;
- int pre_inc = 0;
- int write_back = 0;
+ char *p = *str;
- if (*p == '[')
- {
- int reg;
+ if (skip_past_char (&p, '[') == FAIL)
+ { /* bare address - translate to PC-relative offset */
+ if (my_get_expression (&inst.reloc.exp, &p, GE_NO_PREFIX))
+ return FAIL;
- p++;
+ inst.reloc.pc_rel = 1;
+ inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
+ inst.operands[i].reg = REG_PC;
+ inst.operands[i].preind = 1;
+ *str = p;
+ return SUCCESS;
+ }
- if ((reg = reg_required_here (&p, 16, REG_TYPE_RN)) == FAIL)
- return FAIL;
+ if ((inst.operands[i].reg = reg_required_here (&p, -1, REG_TYPE_RN)) == FAIL)
+ return FAIL;
- if (*p == ']')
+ if (skip_past_char (&p, ']') == SUCCESS)
+ {
+ if (*p == '\0' || *p == '!') /* [Rn]{!} - shorthand for [Rn,#0]{!} */
{
- p++;
+ inst.operands[i].preind = 1;
+ inst.operands[i].writeback = (*p == '!');
+ inst.reloc.exp.X_op = O_constant;
+ inst.reloc.exp.X_add_number = 0;
+ *str = p + (*p == '!');
+ return SUCCESS;
+ }
- if (*p == '\0')
- {
- /* As an extension to the official ARM syntax we allow:
- [Rn]
- as a short hand for:
- [Rn,#0] */
- inst.instruction |= PRE_INDEX | INDEX_UP;
- *str = p;
- return SUCCESS;
- }
+ if (skip_past_comma (&p) == FAIL)
+ {
+ inst.error = _("comma expected after closing square bracket");
+ return FAIL;
+ }
- if (skip_past_comma (& p) == FAIL)
- {
- inst.error = _("comma expected after closing square bracket");
- return FAIL;
- }
+ if (skip_past_char (&p, '{') == SUCCESS)
+ {
+ /* [Rn], {expr} - unindexed, with option */
+ if (immediate_required_here (&p, &inst.operands[i].imm,
+ 0, 255, TRUE) == FAIL)
+ return FAIL;
- if (*p == '#')
+ if (skip_past_char (&p, '}') == FAIL)
{
- if (wb_ok)
- {
- /* [Rn], #expr */
- write_back = WRITE_BACK;
-
- if (reg == REG_PC)
- {
- inst.error = _("pc may not be used in post-increment");
- return FAIL;
- }
-
- if (my_get_expression (& inst.reloc.exp, &p, GE_IMM_PREFIX))
- return FAIL;
- inst.reloc.type = reloc;
- }
- else
- pre_inc = PRE_INDEX | INDEX_UP;
- }
- else if (*p == '{')
- {
- int option;
-
- /* [Rn], {<expr>} */
- p++;
- if (immediate_required_here (&p, &option, 0, 255, TRUE) == FAIL)
- return FAIL;
-
- if (*p != '}')
- {
- inst.error = _("'}' expected at end of 'option' field");
- return FAIL;
- }
- else
- {
- p++;
- inst.instruction |= option;
- inst.instruction |= INDEX_UP;
- }
- }
- else
- {
- inst.error = _("# or { expected after comma");
+ inst.error = _("'}' expected at end of 'option' field");
return FAIL;
}
}
else
{
- /* '['Rn, #expr']'[!] */
-
- if (skip_past_comma (& p) == FAIL)
- {
- inst.error = _("pre-indexed expression expected");
- return FAIL;
- }
-
- if (my_get_expression (& inst.reloc.exp, &p, GE_IMM_PREFIX))
+ if (my_get_expression (&inst.reloc.exp, &p, GE_IMM_PREFIX))
return FAIL;
- inst.reloc.type = reloc;
- pre_inc = PRE_INDEX;
- if (*p++ != ']')
- {
- inst.error = _("missing ]");
- return FAIL;
- }
-
- if (wb_ok && *p == '!')
- {
- if (reg == REG_PC)
- {
- inst.error = _("pc may not be used with write-back");
- return FAIL;
- }
-
- p++;
- write_back = WRITE_BACK;
- }
+ inst.operands[i].postind = 1;
+ inst.operands[i].writeback = 1;
}
}
else
{
- if (my_get_expression (&inst.reloc.exp, &p, GE_NO_PREFIX))
+ /* '['Rn, #expr']'[!] */
+ if (skip_past_comma (&p) == FAIL)
+ {
+ inst.error = _("pre-indexed expression expected");
+ return FAIL;
+ }
+
+ if (my_get_expression (&inst.reloc.exp, &p, GE_IMM_PREFIX))
return FAIL;
- inst.reloc.type = reloc;
- inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
- inst.reloc.pc_rel = 1;
- inst.instruction |= (REG_PC << 16);
- pre_inc = PRE_INDEX;
- }
+ if (skip_past_char (&p, ']') == FAIL)
+ {
+ inst.error = _("missing ]");
+ return FAIL;
+ }
- inst.instruction |= write_back | pre_inc;
+ if (skip_past_char (&p, '!') == SUCCESS)
+ inst.operands[i].writeback = 1;
+
+ inst.operands[i].preind = 1;
+ }
*str = p;
return SUCCESS;
}
+/* inst.operands[i] was set up by parse_cp_address. Encode it into an
+ ARM-format instruction. If wb_ok is false, reject use of writeback;
+ if unind_ok is false, reject use of unindexed addressing. If
+ reloc_override is not 0, use it instead of BFD_ARM_CP_OFF_IMM. */
+
+static int
+encode_cp_address_arm (int i, int wb_ok, int unind_ok, int reloc_override)
+{
+ inst.instruction |= inst.operands[i].reg << 16;
+
+ assert (!(inst.operands[i].preind && inst.operands[i].postind));
+
+ if (!inst.operands[i].preind && !inst.operands[i].postind) /* unindexed */
+ {
+ assert (!inst.operands[i].writeback);
+ if (!unind_ok)
+ {
+ inst.error = _("instruction does not support unindexed addressing");
+ return FAIL;
+ }
+ inst.instruction |= inst.operands[i].imm;
+ inst.instruction |= INDEX_UP;
+ return SUCCESS;
+ }
+
+ if (inst.operands[i].preind)
+ inst.instruction |= PRE_INDEX;
+
+ if (inst.operands[i].writeback)
+ {
+ if (inst.operands[i].reg == REG_PC)
+ {
+ inst.error = _("pc may not be used with write-back");
+ return FAIL;
+ }
+ if (!wb_ok)
+ {
+ inst.error = _("instruction does not support writeback");
+ return FAIL;
+ }
+ inst.instruction |= WRITE_BACK;
+ }
+
+ if (reloc_override)
+ inst.reloc.type = reloc_override;
+ else
+ inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
+ return SUCCESS;
+}
+
/* Parse a Thumb address expression:
[Rl]
@@ -4120,7 +4133,6 @@
#define OP_EXPr 026 /* same, with optional relocation suffix */
#define OP_I0 027 /* immediate value 0 */
-#define OP_I4 030 /* 1 .. 4 */
#define OP_I7 031 /* 0 .. 7 */
#define OP_I15 032 /* 0 .. 15 */
#define OP_I16 033 /* 1 .. 16 */
@@ -4133,6 +4145,7 @@
#define OP_bI7 041 /* immediate, prefix optional, 0 .. 7 */
#define OP_bI15 042 /* 0 .. 15 */
#define OP_bI31 043 /* 0 .. 31 */
+#define OP_bI4 030 /* 1 .. 4 */
#define OP_I31w 050 /* 0 .. 31, optional trailing ! */
#define OP_RRw 051 /* ARM register, not the PC, optional trailing ! */
@@ -4148,6 +4161,7 @@
#define OP_VRDLST 065 /* VFP double-precision register list */
#define OP_TADDR 070 /* Thumb memory address expression */
+#define OP_CADDR 071 /* Co-processor memory address expression */
/* This-or-that operands. All have bit 7 set. */
#define OP_RR_EX 100 /* ARM register or expression */
@@ -4156,6 +4170,7 @@
#define OP_RR_EXr 103 /* ARM register or expression with opt. reloc suff. */
#define OP_RR_iEX 104 /* ARM register or expression with imm prefix */
#define OP_RF_IF 105 /* FPA register or immediate */
+#define OP_RIWR_RIWC 106 /* iWMMXt R or C reg */
/* Optional operands. All have the high bit set. */
#define OP_obI7 200 /* optional, prefix optional, immediate 0 .. 7 */
@@ -4283,7 +4298,6 @@
/* Immediates */
I0:
case OP_(I0): po_imm_or_fail ( 0, 0, FALSE); break;
- case OP_(I4): po_imm_or_fail ( 1, 4, FALSE); break;
case OP_(I7): po_imm_or_fail ( 0, 7, FALSE); break;
case OP_(I15): po_imm_or_fail ( 0, 15, FALSE); break;
case OP_(I16): po_imm_or_fail ( 1, 16, FALSE); break;
@@ -4293,6 +4307,7 @@
case OP_(I255): po_imm_or_fail ( 0, 255, FALSE); break;
case OP_(Iffff): po_imm_or_fail ( 0, 0xffff, FALSE); break;
+ case OP_(bI4): po_imm_or_fail ( 1, 4, TRUE); break;
case OP_(obI7):
case OP_(bI7): po_imm_or_fail ( 0, 7, TRUE); break;
case OP_(bI15): po_imm_or_fail ( 0, 15, TRUE); break;
@@ -4386,6 +4401,20 @@
}
break;
+ /* Two kinds of register */
+ case OP_(RIWR_RIWC):
+ {
+ struct reg_entry *rege = arm_reg_parse_multi (&str);
+ if (rege->type != REG_TYPE_MMXWR && rege->type != REG_TYPE_MMXWC)
+ {
+ inst.error = _("iWMMXt data or control register expected");
+ return FAIL;
+ }
+ inst.operands[i].reg = rege->number;
+ inst.operands[i].isreg = (rege->type == REG_TYPE_MMXWR);
+ }
+ break;
+
/* Misc */
case OP_(CPSF): val = parse_cps_flags (&str); break;
case OP_(ENDI): val = parse_endian_specifier (&str); break;
@@ -4416,6 +4445,11 @@
return FAIL;
break;
+ case OP_(CADDR):
+ if (parse_cp_address (&str, i))
+ return FAIL;
+ break;
+
default:
as_fatal ("unhandled operand code %03o", *p);
}
@@ -5446,21 +5480,17 @@
end_of_line (str);
}
+/* Co-processor register load/store.
+ Format: <LDC|STC>{cond}[L] CP#,CRd,<address> */
static void
do_lstc (char * str)
{
- /* Co-processor register load/store.
- Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
-
- reg_or_fail (&str, 8, REG_TYPE_CP);
- comma_or_fail (&str);
-
- reg_or_fail (&str, 12, REG_TYPE_CN);
- comma_or_fail (&str);
-
- if (cp_address_required_here (&str, TRUE, BFD_RELOC_ARM_CP_OFF_IMM) == FAIL)
+ if (parse_operands (str, OPERANDS3(RCP,RCN,CADDR)))
return;
- end_of_line (str);
+
+ inst.instruction |= inst.operands[0].reg << 8;
+ inst.instruction |= inst.operands[1].reg << 12;
+ encode_cp_address_arm (2, TRUE, TRUE, 0);
}
static void
@@ -6764,25 +6794,21 @@
static void
do_vfp_sp_ldst (char * str)
{
- reg_or_fail (&str, VFP_REG_Sd, REG_TYPE_VFS);
- comma_or_fail (&str);
-
- if (cp_address_required_here (&str, FALSE, BFD_RELOC_ARM_CP_OFF_IMM) == FAIL)
+ if (parse_operands (str, OPERANDS2(RVS,CADDR)))
return;
- end_of_line (str);
+ vfp_sp_encode_reg (inst.operands[0].reg, VFP_REG_Sd);
+ encode_cp_address_arm (1, FALSE, TRUE, 0);
}
static void
do_vfp_dp_ldst (char * str)
{
- reg_or_fail (&str, VFP_REG_Dd, REG_TYPE_VFD);
- comma_or_fail (&str);
-
- if (cp_address_required_here (&str, FALSE, BFD_RELOC_ARM_CP_OFF_IMM) == FAIL)
+ if (parse_operands (str, OPERANDS2(RVD,CADDR)))
return;
- end_of_line (str);
+ inst.instruction |= inst.operands[0].reg << VFP_REG_Dd;
+ encode_cp_address_arm (1, FALSE, TRUE, 0);
}
@@ -6934,108 +6960,54 @@
static void
do_fpa_ldst (char * str)
{
- reg_or_fail (&str, 12, REG_TYPE_FN);
- comma_or_fail (&str);
-
- if (cp_address_required_here (&str, TRUE, BFD_RELOC_ARM_CP_OFF_IMM) == FAIL)
+ if (parse_operands (str, OPERANDS2(RF,CADDR)))
return;
-
- end_of_line (str);
+ inst.instruction |= (inst.operands[0].reg << 12);
+ encode_cp_address_arm (1, TRUE, TRUE, 0);
}
static void
do_fpa_ldmstm (char * str)
{
- int num_regs;
-
- reg_or_fail (&str, 12, REG_TYPE_FN);
- comma_or_fail (&str);
-
- /* Get Number of registers to transfer. */
- if (immediate_required_here (&str, &num_regs, 1, 4, TRUE) == FAIL)
+ if (parse_operands (str, OPERANDS3(RF,bI4,CADDR)))
return;
- comma_or_fail (&str);
- switch (num_regs)
+ inst.instruction |= (inst.operands[0].reg << 12);
+ switch (inst.operands[1].imm)
{
- case 1:
- inst.instruction |= CP_T_X;
- break;
- case 2:
- inst.instruction |= CP_T_Y;
- break;
- case 3:
- inst.instruction |= CP_T_Y | CP_T_X;
- break;
- case 4:
- break;
- default:
- abort ();
+ case 1: inst.instruction |= CP_T_X; break;
+ case 2: inst.instruction |= CP_T_Y; break;
+ case 3: inst.instruction |= CP_T_Y | CP_T_X; break;
+ case 4: break;
+ default: abort ();
}
- if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
+ if (inst.instruction & (PRE_INDEX | INDEX_UP))
{
- int reg;
- int write_back;
- int offset;
-
/* The instruction specified "ea" or "fd", so we can only accept
[Rn]{!}. The instruction does not really support stacking or
unstacking, so we have to emulate these by setting appropriate
bits and offsets. */
-
- char_or_fail (&str, '[');
- note_reg_or_fail (reg, &str, 16, REG_TYPE_RN);
- char_or_fail (&str, ']');
-
- if (*str == '!')
+ if (inst.reloc.exp.X_op != O_constant
+ || inst.reloc.exp.X_add_number != 0)
{
- write_back = 1;
- str++;
- if (reg == REG_PC)
- {
- inst.error =
- _("r15 not allowed as base register with write-back");
- return;
- }
+ inst.error = _("this instruction does not support indexing");
+ return;
}
+ if (inst.operands[2].writeback)
+ inst.instruction |= WRITE_BACK;
+ if (inst.instruction & (PRE_INDEX | WRITE_BACK))
+ inst.reloc.exp.X_add_number = 12 * inst.operands[1].imm;
else
- write_back = 0;
+ inst.instruction |= PRE_INDEX; /* prevent use of unindexed mode */
- if (inst.instruction & CP_T_Pre)
- {
- /* Pre-decrement. */
- offset = 3 * num_regs;
- if (write_back)
- inst.instruction |= CP_T_WB;
- }
- else
- {
- /* Post-increment. */
- if (write_back)
- {
- inst.instruction |= CP_T_WB;
- offset = 3 * num_regs;
- }
- else
- {
- /* No write-back, so convert this into a standard pre-increment
- instruction -- aesthetically more pleasing. */
- inst.instruction |= CP_T_Pre | CP_T_UD;
- offset = 0;
- }
- }
+ if (!(inst.instruction & INDEX_UP))
+ inst.reloc.exp.X_add_number = -inst.reloc.exp.X_add_number;
- inst.instruction |= offset;
+ inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
}
else
- {
- if (cp_address_required_here (&str, TRUE, BFD_RELOC_ARM_CP_OFF_IMM)
- == FAIL)
- return;
- }
-
- end_of_line (str);
+ encode_cp_address_arm (2, TRUE, TRUE, 0);
}
@@ -7188,33 +7160,21 @@
static void
do_iwmmxt_wldst (char * str)
{
- reg_or_fail (&str, 12, REG_TYPE_MMXWR);
- comma_or_fail (&str);
-
- if (cp_address_required_here (&str, TRUE, BFD_RELOC_ARM_CP_OFF_IMM_S2) == FAIL)
+ if (parse_operands (str, OPERANDS2(RIWR,CADDR)))
return;
- end_of_line (str);
+ inst.instruction |= (inst.operands[0].reg << 12);
+ encode_cp_address_arm (1, TRUE, FALSE, BFD_RELOC_ARM_CP_OFF_IMM_S2);
}
static void
do_iwmmxt_wldstw (char * str)
{
- struct reg_entry *reg;
-
- if ((reg = arm_reg_parse_multi (&str)) == NULL
- || (reg->type != REG_TYPE_MMXWR && reg->type != REG_TYPE_MMXWC))
- {
- inst.error = _("iWMMXt data or control register expected");
- return;
- }
- comma_or_fail (&str);
-
- if (cp_address_required_here (&str, TRUE, BFD_RELOC_ARM_CP_OFF_IMM) == FAIL)
+ if (parse_operands (str, OPERANDS2(RIWR_RIWC,CADDR)))
return;
- end_of_line (str);
- if (reg->type == REG_TYPE_MMXWC)
+ /* RIWR_RIWC clears .isreg for a control register. */
+ if (!inst.operands[0].isreg)
{
if ((inst.instruction & COND_MASK) != COND_ALWAYS)
{
@@ -7225,7 +7185,8 @@
inst.instruction |= 0xf0000000;
}
- inst.instruction |= reg->number << 12;
+ inst.instruction |= inst.operands[0].reg << 12;
+ encode_cp_address_arm (1, TRUE, TRUE, 0);
}
static void
@@ -7606,37 +7567,37 @@
<insn><cond> CRd,[Rn],<offset>. */
static void
-do_mav_ldst (char * str, enum arm_reg_type reg0)
+do_mav_ldst (char *str, const char *operands)
{
- reg_or_fail (&str, 12, reg0);
- comma_or_fail (&str);
+ if (parse_operands (str, operands))
+ return;
- cp_address_required_here (&str, TRUE, BFD_RELOC_ARM_CP_OFF_IMM);
- end_of_line (str);
+ inst.instruction |= inst.operands[0].reg << 12;
+ encode_cp_address_arm (1, TRUE, TRUE, 0);
}
static void
do_mav_ldst_1 (char * str)
{
- do_mav_ldst (str, REG_TYPE_MVF);
+ do_mav_ldst (str, OPERANDS2(RMF,CADDR));
}
static void
do_mav_ldst_2 (char * str)
{
- do_mav_ldst (str, REG_TYPE_MVD);
+ do_mav_ldst (str, OPERANDS2(RMD,CADDR));
}
static void
do_mav_ldst_3 (char * str)
{
- do_mav_ldst (str, REG_TYPE_MVFX);
+ do_mav_ldst (str, OPERANDS2(RMFX,CADDR));
}
static void
do_mav_ldst_4 (char * str)
{
- do_mav_ldst (str, REG_TYPE_MVDX);
+ do_mav_ldst (str, OPERANDS2(RMDX,CADDR));
}
/* XScale instructions. Also sorted arithmetic before move. */
@@ -10522,28 +10483,25 @@
#endif
case BFD_RELOC_ARM_CP_OFF_IMM:
- sign = value >= 0;
if (value < -1023 || value > 1023 || (value & 3))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("co-processor offset out of range"));
+ cp_off_common:
+ sign = value >= 0;
if (value < 0)
value = -value;
newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
newval |= (value >> 2) | (sign ? INDEX_UP : 0);
+ if (value == 0)
+ newval &= ~WRITE_BACK;
md_number_to_chars (buf, newval, INSN_SIZE);
break;
case BFD_RELOC_ARM_CP_OFF_IMM_S2:
- sign = value >= 0;
if (value < -255 || value > 255)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("co-processor offset out of range"));
- if (value < 0)
- value = -value;
- newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
- newval |= value | (sign ? INDEX_UP : 0);
- md_number_to_chars (buf, newval , INSN_SIZE);
- break;
+ goto cp_off_common;
case BFD_RELOC_ARM_THUMB_OFFSET:
newval = md_chars_to_number (buf, THUMB_SIZE);