aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-z8k.c
diff options
context:
space:
mode:
authorChristian Groessler <chris@groessler.org>2003-12-15 22:02:42 +0000
committerChristian Groessler <chris@groessler.org>2003-12-15 22:02:42 +0000
commitbb5737a7203b8470c3ef554db2b803fb6a0cdcc9 (patch)
tree51f191217b6c159feb90f9c69929613fc2c2c860 /gas/config/tc-z8k.c
parenta0bd404eacfd838498f1fac90997f732735cc00a (diff)
downloadgdb-bb5737a7203b8470c3ef554db2b803fb6a0cdcc9.zip
gdb-bb5737a7203b8470c3ef554db2b803fb6a0cdcc9.tar.gz
gdb-bb5737a7203b8470c3ef554db2b803fb6a0cdcc9.tar.bz2
* config/tc-z8k.c (struct z8k_exp): Remove, not used anywhere.
(ctrl_table): Add "flags" keyword and some comments. (flag_table): Convert to uppercase. (get_flags_operand): Be case insensitive. (get_interrupt_operand): Be case insensitive. Support notation where the inperrupt arguments are separated by commas. (get_operands): Check whether get_flags_operand consumed all arguments. Return failure if get_ctrl_operand didn't recognize a valid control register. (get_specific): Add case CLASS_CTRL: Test for valid control register for ldctlb opcode. (build_bytes): Check for valid control registers.
Diffstat (limited to 'gas/config/tc-z8k.c')
-rw-r--r--gas/config/tc-z8k.c91
1 files changed, 65 insertions, 26 deletions
diff --git a/gas/config/tc-z8k.c b/gas/config/tc-z8k.c
index c62b9ef..f2aa9ad 100644
--- a/gas/config/tc-z8k.c
+++ b/gas/config/tc-z8k.c
@@ -177,12 +177,6 @@ md_begin (void)
}
}
-struct z8k_exp {
- char *e_beg;
- char *e_end;
- expressionS e_exp;
-};
-
typedef struct z8k_op {
/* CLASS_REG_xxx. */
int regsize;
@@ -399,7 +393,8 @@ struct ctrl_names {
};
static struct ctrl_names ctrl_table[] = {
- { 0x2, "fcw" },
+ { 0x1, "flags" }, /* ldctlb only. */
+ { 0x2, "fcw" }, /* ldctl only. Applies to all remaining control registers. */
{ 0x3, "refresh" },
{ 0x4, "psapseg" },
{ 0x5, "psapoff" },
@@ -441,12 +436,13 @@ struct flag_names {
};
static struct flag_names flag_table[] = {
- { 0x1, "p" },
- { 0x1, "v" },
- { 0x2, "s" },
- { 0x4, "z" },
- { 0x8, "c" },
+ { 0x1, "P" },
+ { 0x1, "V" },
+ { 0x2, "S" },
+ { 0x4, "Z" },
+ { 0x8, "C" },
{ 0x0, "+" },
+ { 0x0, "," },
{ 0, 0 }
};
@@ -454,6 +450,7 @@ static void
get_flags_operand (char **ptr, struct z8k_op *mode, unsigned int dst ATTRIBUTE_UNUSED)
{
char *src = *ptr;
+ char c;
int i;
int j;
@@ -466,9 +463,10 @@ get_flags_operand (char **ptr, struct z8k_op *mode, unsigned int dst ATTRIBUTE_U
{
if (!src[j])
goto done;
+ c = TOUPPER(src[j]);
for (i = 0; flag_table[i].name; i++)
{
- if (flag_table[i].name[0] == src[j])
+ if (flag_table[i].name[0] == c)
{
the_flags = the_flags | flag_table[i].value;
goto match;
@@ -499,27 +497,48 @@ static void
get_interrupt_operand (char **ptr, struct z8k_op *mode, unsigned int dst ATTRIBUTE_UNUSED)
{
char *src = *ptr;
- int i;
+ int i, l;
while (*src == ' ')
src++;
mode->mode = CLASS_IMM;
- for (i = 0; intr_table[i].name; i++)
- {
- int j;
+ the_interrupt = 0;
- for (j = 0; intr_table[i].name[j]; j++)
+ while (*src)
+ {
+ for (i = 0; intr_table[i].name; i++)
+ {
+ l = strlen (intr_table[i].name);
+ if (! strncasecmp (intr_table[i].name, src, l))
+ {
+ the_interrupt |= intr_table[i].value;
+ if (*(src + l) && *(src + l) != ',')
+ {
+ *ptr = src + l;
+ invalid:
+ as_bad (_("unknown interrupt %s"), src);
+ while (**ptr && ! is_end_of_line[(unsigned char) **ptr])
+ (*ptr)++; /* Consume rest of line. */
+ return;
+ }
+ src += l;
+ if (! *src)
+ {
+ *ptr = src;
+ return;
+ }
+ }
+ }
+ if (*src == ',')
+ src++;
+ else
{
- if (intr_table[i].name[j] != src[j])
- goto fail;
+ *ptr = src;
+ goto invalid;
}
- the_interrupt = intr_table[i].value;
- *ptr = src + j;
- return;
- fail:
- ;
}
+
/* No interrupt type specified, opcode won't do anything. */
as_warn (_("opcode has no effect"));
the_interrupt = 0x0;
@@ -720,7 +739,17 @@ get_operands (const opcode_entry_type *opcode, char *op_end, op_type *operand)
}
}
else if (opcode->arg_info[0] == CLASS_FLAGS)
- get_flags_operand (&ptr, operand + 0, 0);
+ {
+ get_flags_operand (&ptr, operand + 0, 0);
+ while (*ptr == ' ')
+ ptr++;
+ if (*ptr && ! is_end_of_line[(unsigned char) *ptr])
+ {
+ as_bad (_("invalid flag '%s'"), ptr);
+ while (*ptr && ! is_end_of_line[(unsigned char) *ptr])
+ ptr++; /* Consume rest of line. */
+ }
+ }
else if (opcode->arg_info[0] == (CLASS_IMM + (ARG_IMM2)))
get_interrupt_operand (&ptr, operand + 0, 0);
else
@@ -760,6 +789,8 @@ get_operands (const opcode_entry_type *opcode, char *op_end, op_type *operand)
if (*ptr == ',')
ptr++;
get_ctrl_operand (&ptr, operand + 1, 1);
+ if (the_ctrl == 0)
+ return NULL;
return ptr;
}
}
@@ -889,6 +920,10 @@ get_specific (opcode_entry_type *opcode, op_type *operands)
case CLASS_REGN0:
reg[this_try->arg_info[i] & ARG_MASK] = operands[i].reg;
break;
+ case CLASS_CTRL:
+ if (this_try->opcode == OPC_ldctlb && the_ctrl != 1)
+ as_bad (_("invalid control register name"));
+ break;
}
}
@@ -1035,9 +1070,13 @@ build_bytes (opcode_entry_type *this_try, struct z8k_op *operand ATTRIBUTE_UNUSE
*output_ptr++ = the_cc;
break;
case CLASS_0CCC:
+ if (the_ctrl < 2 || the_ctrl > 7)
+ as_bad (_("invalid control register name"));
*output_ptr++ = the_ctrl;
break;
case CLASS_1CCC:
+ if (the_ctrl < 2 || the_ctrl > 7)
+ as_bad (_("invalid control register name"));
*output_ptr++ = the_ctrl | 0x8;
break;
case CLASS_00II: