This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Thumb32 assembler (38/69)
- From: Zack Weinberg <zack at codesourcery dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Tue, 26 Apr 2005 02:55:10 -0700
- Subject: Thumb32 assembler (38/69)
Cleanup: return values from some of the parse_* functions instead of
using out-parameters. Also, some rearrangement to remove duplicate
code in parse_operands.
zw
* config/tc-arm.c (parse_cps_flags, parse_endian_specifier, parse_ror):
On success, return the value instead of poking it into an out-parameter.
(parse_operands): Migrate value checks to a second switch statement
for compactness and clarity. Update to match above interface changes.
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c (revision 40)
+++ gas/config/tc-arm.c (revision 41)
@@ -2454,12 +2454,11 @@
return SUCCESS;
}
-/* Parse the flags argument to CPSI[ED]. Returns SUCCESS or FAIL as
- appropriate; on success, *valp gets a value suitable for splatting
- into the AIF field of the instruction. */
+/* Parse the flags argument to CPSI[ED]. Returns FAIL on error, or a
+ value suitable for splatting into the AIF field of the instruction. */
static int
-parse_cps_flags (int *valp, char **str)
+parse_cps_flags (char **str)
{
int val = 0;
int saw_a_flag = 0;
@@ -2488,8 +2487,7 @@
}
*str = s - 1;
- *valp = val;
- return SUCCESS;
+ return val;
}
static int
@@ -2515,11 +2513,10 @@
}
/* Parse an endian specifier ("BE" or "LE", case insensitive);
- write 0 into *val for big-endian, 1 for little-endian; return
- SUCCESS for successful parse, or FAIL and set inst.error. */
+ returns 0 for big-endian, 1 for little-endian, FAIL for an error. */
static int
-parse_endian_specifier (int *val, char **str)
+parse_endian_specifier (char **str)
{
int little_endian;
char *s = *str;
@@ -2540,17 +2537,16 @@
return FAIL;
}
- *val = little_endian;
*str = s + 2;
- return SUCCESS;
+ return little_endian;
}
/* Parse a rotation specifier: ROR #0, #8, #16, #24. *val receives a
value suitable for poking into the rotate field of an sxt or sxta
- instruction. */
+ instruction, or FAIL on error. */
static int
-parse_ror (int *val, char **str)
+parse_ror (char **str)
{
int rot;
char *s = *str;
@@ -2568,17 +2564,15 @@
switch (rot)
{
- case 0: *val = 0x0; break;
- case 8: *val = 0x1; break;
- case 16: *val = 0x2; break;
- case 24: *val = 0x3; break;
+ case 0: *str = s; return 0x0;
+ case 8: *str = s; return 0x1;
+ case 16: *str = s; return 0x2;
+ case 24: *str = s; return 0x3;
default:
inst.error = _("rotation can only be 0, 8, 16, or 24");
return FAIL;
}
- *str = s;
- return SUCCESS;
}
/* Directives: register aliases. */
@@ -4405,6 +4399,9 @@
switch (*p)
{
/* Registers */
+ case OP_(RRnpc):
+ case OP_(oRL):
+ case OP_(RL):
case OP_(RR): po_reg_or_fail (REG_TYPE_RN); break;
case OP_(RCP): po_reg_or_fail (REG_TYPE_CP); break;
case OP_(RCN): po_reg_or_fail (REG_TYPE_CN); break;
@@ -4423,28 +4420,15 @@
case OP_(RIWG): po_reg_or_fail (REG_TYPE_MMXWCG); break;
case OP_(RXA): po_reg_or_fail (REG_TYPE_XSCALE); break;
- /* Register variants */
- case OP_(RRnpc):
- po_reg_or_fail (REG_TYPE_RN);
- if (inst.operands[i].reg == REG_PC)
- inst.error = BAD_PC;
- /* We do not signal an immediate failure for the PC; this
- allows a syntax error to take precedence. The error will
- be caught by output_inst. */
- break;
-
case OP_(bRRnpc):
po_char_or_fail ('[');
po_reg_or_fail (REG_TYPE_RN);
po_char_or_fail (']');
- if (inst.operands[i].reg == REG_PC)
- inst.error = BAD_PC;
break;
+ case OP_(RLw):
case OP_(RRw):
po_reg_or_fail (REG_TYPE_RN);
- if (inst.operands[i].reg == REG_PC)
- inst.error = BAD_PC;
if (*str == '!')
{
inst.operands[i].writeback = 1;
@@ -4452,38 +4436,16 @@
}
break;
- case OP_(oRL):
- case OP_(RL):
- po_reg_or_fail (REG_TYPE_RN);
- if (inst.operands[i].reg > 7)
- inst.error = BAD_HIREG;
- break;
-
case OP_(RLlb):
po_char_or_fail ('[');
po_reg_or_fail (REG_TYPE_RN);
- if (inst.operands[i].reg > 7)
- inst.error = BAD_HIREG;
break;
case OP_(RLtb):
po_reg_or_fail (REG_TYPE_RN);
po_char_or_fail (']');
- if (inst.operands[i].reg > 7)
- inst.error = BAD_HIREG;
break;
- case OP_(RLw):
- po_reg_or_fail (REG_TYPE_RN);
- if (inst.operands[i].reg > 7)
- inst.error = BAD_HIREG;
- if (*str == '!')
- {
- inst.operands[i].writeback = 1;
- str++;
- }
- break;
-
/* Immediates */
I0:
case OP_(I0): po_imm_or_fail ( 0, 0, FALSE); break;
@@ -4566,21 +4528,12 @@
/* Register or expression */
case OP_(RR_EX): po_reg_or_goto (REG_TYPE_RN, EXP); break;
case OP_(RR_EXr): po_reg_or_goto (REG_TYPE_RN, EXPr); break;
- case OP_(RR_iEX): po_reg_or_goto (REG_TYPE_RN, iEXP); break;
-
case OP_(oRL_iEX):
case OP_(RL_iEX):
- po_reg_or_goto (REG_TYPE_RN, iEXP);
- if (inst.operands[i].reg > 7)
- inst.error = BAD_HIREG;
- break;
+ case OP_(RR_iEX): po_reg_or_goto (REG_TYPE_RN, iEXP); break;
/* Register or immediate */
- case OP_(RRnpc_I0):
- po_reg_or_goto (REG_TYPE_RN, I0);
- if (inst.operands[i].reg == REG_PC)
- inst.error = BAD_PC;
- break;
+ case OP_(RRnpc_I0): po_reg_or_goto (REG_TYPE_RN, I0); break;
case OP_(RF_IF):
if (!is_immediate_prefix (*str))
@@ -4599,31 +4552,14 @@
break;
/* Misc */
- case OP_(CPSF):
- if (parse_cps_flags (&inst.operands[i].imm, &str))
- return FAIL;
- break;
+ case OP_(CPSF): val = parse_cps_flags (&str); break;
+ case OP_(ENDI): val = parse_endian_specifier (&str); break;
+ case OP_(oROR): val = parse_ror (&str); break;
+ case OP_(PSR): val = parse_psr (&str); break;
- case OP_(ENDI):
- if (parse_endian_specifier (&inst.operands[i].imm, &str))
- return FAIL;
- break;
-
- case OP_(oROR):
- if (parse_ror (&inst.operands[i].imm, &str))
- return FAIL;
- break;
-
- case OP_(PSR):
- if ((val = parse_psr (&str)) == FAIL)
- return FAIL;
- inst.operands[i].imm = val;
- break;
-
+ /* Register lists */
case OP_(REGLST):
- if ((val = reg_list (&str)) == FAIL)
- return FAIL;
- inst.operands[i].imm = val;
+ val = reg_list (&str);
if (*str == '^')
{
inst.operands[1].writeback = 1;
@@ -4633,20 +4569,56 @@
case OP_(VRSLST):
val = vfp_parse_reg_list (&str, &inst.operands[i].reg, 0);
- goto vfp_reglist;
+ break;
case OP_(VRDLST):
val = vfp_parse_reg_list (&str, &inst.operands[i].reg, 1);
+ break;
- vfp_reglist:
+ default:
+ as_fatal ("unhandled operand code %03o", *p);
+ }
+
+ /* Various value-based sanity checks and shared operations. We
+ do not signal immediate failures for the register constraints;
+ this allows a syntax error to take precedence. */
+ switch (*p)
+ {
+ case OP_(RRnpc):
+ case OP_(bRRnpc):
+ case OP_(RRw):
+ case OP_(RRnpc_I0):
+ if (inst.operands[i].isreg && inst.operands[i].reg == REG_PC)
+ inst.error = BAD_PC;
+ break;
+
+ case OP_(oRL):
+ case OP_(RL):
+ case OP_(RLlb):
+ case OP_(RLtb):
+ case OP_(RLw):
+ case OP_(oRL_iEX):
+ case OP_(RL_iEX):
+ if (inst.operands[i].isreg && inst.operands[i].reg > 7)
+ inst.error = BAD_HIREG;
+ break;
+
+ case OP_(CPSF):
+ case OP_(ENDI):
+ case OP_(oROR):
+ case OP_(PSR):
+ case OP_(REGLST):
+ case OP_(VRSLST):
+ case OP_(VRDLST):
if (val == FAIL)
return FAIL;
inst.operands[i].imm = val;
break;
default:
- as_fatal ("unhandled operand code %03o", *p);
+ break;
}
+
/* If we get here, this operand was successfully parsed. */
inst.operands[i].present = 1;