This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Thumb32 assembler (14/69)
- From: Zack Weinberg <zack at codesourcery dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Tue, 26 Apr 2005 02:54:00 -0700
- Subject: Thumb32 assembler (14/69)
Simplification of the handling of PSR codes. The hash table now
contains only the suffix; the initial [CS]PSR_? is parsed by hand.
This halves the size of the static table, since it no longer needs
separate entries for CPSR_foo and SPSR_foo.
zw
* config/tc-arm.c (struct asm_psr): Remove cpsr field.
(PSR_c, PSR_x, PSR_s, PSR_f): Incorporate PSR_SHIFT into values.
(PSR_SHIFT): Delete.
(psrs): Move next to register table. Remove all SPSR entries.
Remove entry for "CPSR" alone. Remove ->cpsr column. Remove
CPSR_ prefix from all entries.
(arm_psr_parse): Fold into psr_required_here. Do not include
prefix in text passed to hash lookup. Use hash_find_n.
Distinguish between CPSR_ and SPSR_ entries here, and handle
unsuffixed CPSR/SPSR without a hash lookup.
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c (revision 15)
+++ gas/config/tc-arm.c (revision 16)
@@ -320,162 +320,19 @@
struct asm_psr
{
const char *template;
- bfd_boolean cpsr;
unsigned long field;
};
/* The bit that distinguishes CPSR and SPSR. */
#define SPSR_BIT (1 << 22)
-/* How many bits to shift the PSR_xxx bits up by. */
-#define PSR_SHIFT 16
+/* The individual PSR flag bits. */
+#define PSR_c (1 << 16)
+#define PSR_x (1 << 17)
+#define PSR_s (1 << 18)
+#define PSR_f (1 << 19)
-#define PSR_c (1 << 0)
-#define PSR_x (1 << 1)
-#define PSR_s (1 << 2)
-#define PSR_f (1 << 3)
-static const struct asm_psr psrs[] =
-{
- {"CPSR", TRUE, PSR_c | PSR_f},
- {"CPSR_all", TRUE, PSR_c | PSR_f},
- {"SPSR", FALSE, PSR_c | PSR_f},
- {"SPSR_all", FALSE, PSR_c | PSR_f},
- {"CPSR_flg", TRUE, PSR_f},
- {"CPSR_f", TRUE, PSR_f},
- {"SPSR_flg", FALSE, PSR_f},
- {"SPSR_f", FALSE, PSR_f},
- {"CPSR_c", TRUE, PSR_c},
- {"CPSR_ctl", TRUE, PSR_c},
- {"SPSR_c", FALSE, PSR_c},
- {"SPSR_ctl", FALSE, PSR_c},
- {"CPSR_x", TRUE, PSR_x},
- {"CPSR_s", TRUE, PSR_s},
- {"SPSR_x", FALSE, PSR_x},
- {"SPSR_s", FALSE, PSR_s},
- /* Combinations of flags. */
- {"CPSR_fs", TRUE, PSR_f | PSR_s},
- {"CPSR_fx", TRUE, PSR_f | PSR_x},
- {"CPSR_fc", TRUE, PSR_f | PSR_c},
- {"CPSR_sf", TRUE, PSR_s | PSR_f},
- {"CPSR_sx", TRUE, PSR_s | PSR_x},
- {"CPSR_sc", TRUE, PSR_s | PSR_c},
- {"CPSR_xf", TRUE, PSR_x | PSR_f},
- {"CPSR_xs", TRUE, PSR_x | PSR_s},
- {"CPSR_xc", TRUE, PSR_x | PSR_c},
- {"CPSR_cf", TRUE, PSR_c | PSR_f},
- {"CPSR_cs", TRUE, PSR_c | PSR_s},
- {"CPSR_cx", TRUE, PSR_c | PSR_x},
- {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
- {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
- {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
- {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
- {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
- {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
- {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
- {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
- {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
- {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
- {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
- {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
- {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
- {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
- {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
- {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
- {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
- {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
- {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
- {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
- {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
- {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
- {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
- {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
- {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
- {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
- {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
- {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
- {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
- {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
- {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
- {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
- {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
- {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
- {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
- {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
- {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
- {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
- {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
- {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
- {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
- {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
- {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
- {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
- {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
- {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
- {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
- {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
- {"SPSR_fs", FALSE, PSR_f | PSR_s},
- {"SPSR_fx", FALSE, PSR_f | PSR_x},
- {"SPSR_fc", FALSE, PSR_f | PSR_c},
- {"SPSR_sf", FALSE, PSR_s | PSR_f},
- {"SPSR_sx", FALSE, PSR_s | PSR_x},
- {"SPSR_sc", FALSE, PSR_s | PSR_c},
- {"SPSR_xf", FALSE, PSR_x | PSR_f},
- {"SPSR_xs", FALSE, PSR_x | PSR_s},
- {"SPSR_xc", FALSE, PSR_x | PSR_c},
- {"SPSR_cf", FALSE, PSR_c | PSR_f},
- {"SPSR_cs", FALSE, PSR_c | PSR_s},
- {"SPSR_cx", FALSE, PSR_c | PSR_x},
- {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
- {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
- {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
- {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
- {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
- {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
- {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
- {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
- {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
- {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
- {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
- {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
- {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
- {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
- {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
- {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
- {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
- {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
- {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
- {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
- {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
- {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
- {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
- {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
- {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
- {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
- {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
- {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
- {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
- {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
- {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
- {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
- {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
- {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
- {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
- {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
- {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
- {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
- {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
- {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
- {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
- {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
- {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
- {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
- {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
- {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
- {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
- {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
-};
-
enum iwmmxt_insn_type
{
check_rd,
@@ -2319,74 +2176,67 @@
/* Miscellaneous: PSR flags, endian specifiers, coprocessor
operands. */
-static const struct asm_psr *
-arm_psr_parse (char ** ccp)
+/* Parse the input looking for a PSR flag. */
+static int
+psr_required_here (char **str)
{
- char * start = * ccp;
- char c;
- char * p;
- const struct asm_psr * psr;
+ char *p;
+ bfd_boolean is_spsr;
+ unsigned long psr_field;
- p = start;
-
- /* Skip to the end of the next word in the input stream. */
- do
- {
- c = *p++;
- }
- while (ISALPHA (c) || c == '_');
-
- /* Terminate the word. */
- *--p = 0;
-
/* CPSR's and SPSR's can now be lowercase. This is just a convenience
feature for ease of use and backwards compatibility. */
- if (!strncmp (start, "cpsr", 4))
- strncpy (start, "CPSR", 4);
- else if (!strncmp (start, "spsr", 4))
- strncpy (start, "SPSR", 4);
+ p = *str;
+ if (*p == 's' || *p == 'S')
+ is_spsr = TRUE;
+ else if (*p == 'c' || *p == 'C')
+ is_spsr = FALSE;
+ else
+ goto error;
- /* Now locate the word in the psr hash table. */
- psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
+ p++;
+ if (strncasecmp (p, "PSR", 3) != 0)
+ goto error;
+ p += 3;
- /* Restore the input stream. */
- *p = c;
+ if (*p == '_')
+ {
+ /* A suffix follows. */
+ const struct asm_psr *psr;
+ char *start;
- /* If we found a valid match, advance the
- stream pointer past the end of the word. */
- *ccp = p;
+ p++;
+ start = p;
- return psr;
-}
+ do
+ p++;
+ while (ISALNUM (*p) || *p == '_');
-/* Parse the input looking for a PSR flag. */
+ psr = hash_find_n (arm_psr_hsh, start, p - start);
+ if (!psr)
+ goto error;
-static int
-psr_required_here (char ** str)
-{
- char * start = * str;
- const struct asm_psr * psr;
-
- psr = arm_psr_parse (str);
-
- if (psr)
+ psr_field = psr->field;
+ }
+ else
{
- /* If this is the SPSR that is being modified, set the R bit. */
- if (! psr->cpsr)
- inst.instruction |= SPSR_BIT;
+ if (ISALNUM (*p))
+ goto error; /* Garbage after "[CS]PSR". */
- /* Set the psr flags in the MSR instruction. */
- inst.instruction |= psr->field << PSR_SHIFT;
-
- return SUCCESS;
+ psr_field = (PSR_c | PSR_f);
}
- /* In the few cases where we might be able to accept
- something else this error can be overridden. */
- inst.error = _("flag for {c}psr instruction expected");
+ /* If this is the SPSR that is being modified, set the R bit. */
+ if (is_spsr)
+ inst.instruction |= SPSR_BIT;
- /* Restore the start point. */
- *str = start;
+ /* Set the psr flags in the MSR instruction. */
+ inst.instruction |= psr_field;
+ *str = p;
+ return SUCCESS;
+
+ error:
+ inst.error = _("flag for {c}psr instruction expected");
return FAIL;
}
@@ -9191,6 +9041,85 @@
#undef REGNUM
#undef REGSET
+/* Table of all PSR suffixes. Bare "CPSR" and "SPSR" are handled
+ within psr_required_here. */
+static const struct asm_psr psrs[] =
+{
+ /* Backward compatibility notation. Note that "all" is no longer
+ truly all possible PSR bits. */
+ {"all", PSR_c | PSR_f},
+ {"flg", PSR_f},
+ {"ctl", PSR_c},
+
+ /* Individual flags. */
+ {"f", PSR_f},
+ {"c", PSR_c},
+ {"x", PSR_x},
+ {"s", PSR_s},
+ /* Combinations of flags. */
+ {"fs", PSR_f | PSR_s},
+ {"fx", PSR_f | PSR_x},
+ {"fc", PSR_f | PSR_c},
+ {"sf", PSR_s | PSR_f},
+ {"sx", PSR_s | PSR_x},
+ {"sc", PSR_s | PSR_c},
+ {"xf", PSR_x | PSR_f},
+ {"xs", PSR_x | PSR_s},
+ {"xc", PSR_x | PSR_c},
+ {"cf", PSR_c | PSR_f},
+ {"cs", PSR_c | PSR_s},
+ {"cx", PSR_c | PSR_x},
+ {"fsx", PSR_f | PSR_s | PSR_x},
+ {"fsc", PSR_f | PSR_s | PSR_c},
+ {"fxs", PSR_f | PSR_x | PSR_s},
+ {"fxc", PSR_f | PSR_x | PSR_c},
+ {"fcs", PSR_f | PSR_c | PSR_s},
+ {"fcx", PSR_f | PSR_c | PSR_x},
+ {"sfx", PSR_s | PSR_f | PSR_x},
+ {"sfc", PSR_s | PSR_f | PSR_c},
+ {"sxf", PSR_s | PSR_x | PSR_f},
+ {"sxc", PSR_s | PSR_x | PSR_c},
+ {"scf", PSR_s | PSR_c | PSR_f},
+ {"scx", PSR_s | PSR_c | PSR_x},
+ {"xfs", PSR_x | PSR_f | PSR_s},
+ {"xfc", PSR_x | PSR_f | PSR_c},
+ {"xsf", PSR_x | PSR_s | PSR_f},
+ {"xsc", PSR_x | PSR_s | PSR_c},
+ {"xcf", PSR_x | PSR_c | PSR_f},
+ {"xcs", PSR_x | PSR_c | PSR_s},
+ {"cfs", PSR_c | PSR_f | PSR_s},
+ {"cfx", PSR_c | PSR_f | PSR_x},
+ {"csf", PSR_c | PSR_s | PSR_f},
+ {"csx", PSR_c | PSR_s | PSR_x},
+ {"cxf", PSR_c | PSR_x | PSR_f},
+ {"cxs", PSR_c | PSR_x | PSR_s},
+ {"fsxc", PSR_f | PSR_s | PSR_x | PSR_c},
+ {"fscx", PSR_f | PSR_s | PSR_c | PSR_x},
+ {"fxsc", PSR_f | PSR_x | PSR_s | PSR_c},
+ {"fxcs", PSR_f | PSR_x | PSR_c | PSR_s},
+ {"fcsx", PSR_f | PSR_c | PSR_s | PSR_x},
+ {"fcxs", PSR_f | PSR_c | PSR_x | PSR_s},
+ {"sfxc", PSR_s | PSR_f | PSR_x | PSR_c},
+ {"sfcx", PSR_s | PSR_f | PSR_c | PSR_x},
+ {"sxfc", PSR_s | PSR_x | PSR_f | PSR_c},
+ {"sxcf", PSR_s | PSR_x | PSR_c | PSR_f},
+ {"scfx", PSR_s | PSR_c | PSR_f | PSR_x},
+ {"scxf", PSR_s | PSR_c | PSR_x | PSR_f},
+ {"xfsc", PSR_x | PSR_f | PSR_s | PSR_c},
+ {"xfcs", PSR_x | PSR_f | PSR_c | PSR_s},
+ {"xsfc", PSR_x | PSR_s | PSR_f | PSR_c},
+ {"xscf", PSR_x | PSR_s | PSR_c | PSR_f},
+ {"xcfs", PSR_x | PSR_c | PSR_f | PSR_s},
+ {"xcsf", PSR_x | PSR_c | PSR_s | PSR_f},
+ {"cfsx", PSR_c | PSR_f | PSR_s | PSR_x},
+ {"cfxs", PSR_c | PSR_f | PSR_x | PSR_s},
+ {"csfx", PSR_c | PSR_s | PSR_f | PSR_x},
+ {"csxf", PSR_c | PSR_s | PSR_x | PSR_f},
+ {"cxfs", PSR_c | PSR_x | PSR_f | PSR_s},
+ {"cxsf", PSR_c | PSR_x | PSR_s | PSR_f},
+};
+
+
static const struct asm_opcode insns[] =
{
/* Core ARM Instructions. */