diff options
author | Christian Groessler <chris@groessler.org> | 2003-12-15 22:02:42 +0000 |
---|---|---|
committer | Christian Groessler <chris@groessler.org> | 2003-12-15 22:02:42 +0000 |
commit | bb5737a7203b8470c3ef554db2b803fb6a0cdcc9 (patch) | |
tree | 51f191217b6c159feb90f9c69929613fc2c2c860 /gas/config/tc-z8k.c | |
parent | a0bd404eacfd838498f1fac90997f732735cc00a (diff) | |
download | gdb-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.c | 91 |
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: |