This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
z8k fixes
- From: Christian Groessler <chris at groessler dot org>
- To: binutils at sources dot redhat dot com
- Cc: chris at groessler dot org
- Date: 15 Dec 2003 23:19:31 +0100
- Subject: z8k fixes
Hi,
I've checked in some fixes for z8k:
- Be case insensitive when parsing control register and
interrupt operands.
- Comma-separated interrupt operands (EI/DI opcodes) are now
supported. This is the syntax which is used in the Zilog
documentation.
- The disassembler disassembles flags (SETFLG, RESFLG, COMFLG
opcodes) and interrupt operands now in a format the assembler
understands.
- Updated testsuite with new EI/DI syntax.
regards,
chris
ChangeLogs:
opcodes/ChangeLog:
2003-12-15 Christian Groessler <chris@groessler.org>
* z8k-dis.c (intr_names): Removed.
(print_intr, print_flags): New functions.
(unparse_instr): Use new functions.
gas/ChangeLog:
2003-12-15 Christian Groessler <chris@groessler.org>
* 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.
gas/testsuite/ChangeLog:
2003-12-15 Christian Groessler <chris@groessler.org>
* gas/z8k/eidi.s: Add uppercase forms. Add forms with comma
separated parameters.
Index: gas/config/tc-z8k.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-z8k.c,v
retrieving revision 1.28
diff -u -p -r1.28 tc-z8k.c
--- gas/config/tc-z8k.c 10 Dec 2003 06:41:08 -0000 1.28
+++ gas/config/tc-z8k.c 15 Dec 2003 21:58:57 -0000
@@ -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 z8
{
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++)
{
- if (intr_table[i].name[j] != src[j])
- goto fail;
+ 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
+ {
+ *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 *o
}
}
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 *o
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,
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
*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:
Index: gas/testsuite/gas/z8k/eidi.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/z8k/eidi.s,v
retrieving revision 1.1
diff -u -p -r1.1 eidi.s
--- gas/testsuite/gas/z8k/eidi.s 21 Jun 2003 12:20:08 -0000 1.1
+++ gas/testsuite/gas/z8k/eidi.s 15 Dec 2003 21:59:06 -0000
@@ -1,4 +1,5 @@
.text
+
ei all
di all
ei both
@@ -8,3 +9,22 @@
ei nvi
di nvi
+ ei vi,nvi
+ ei nvi,vi
+ di vi,nvi
+ di nvi,vi
+
+
+ EI ALL
+ DI ALL
+ EI BOTH
+ DI BOTH
+ EI VI
+ DI VI
+ EI NVI
+ DI NVI
+
+ EI VI,NVI
+ EI NVI,VI
+ DI VI,NVI
+ DI NVI,VI
Index: opcodes/z8k-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/z8k-dis.c,v
retrieving revision 1.15
diff -u -p -r1.15 z8k-dis.c
--- opcodes/z8k-dis.c 28 Nov 2003 20:12:17 -0000 1.15
+++ opcodes/z8k-dis.c 15 Dec 2003 21:59:14 -0000
@@ -26,7 +26,7 @@
#include "z8k-opc.h"
#include <setjmp.h>
-
+
typedef struct
{
/* These are all indexed by nibble number (i.e only every other entry
@@ -472,12 +472,53 @@ unpack_instr (instr_data_s *instr_data,
}
}
-static char *intr_names[] = {
- "all", /* 0 */
- "vi", /* 1 */
- "nvi", /* 2 */
- "none" /* 3 */
-};
+static void
+print_intr(char *tmp_str, unsigned long interrupts)
+{
+ int comma = 0;
+
+ *tmp_str = 0;
+ if (! (interrupts & 2))
+ {
+ strcat (tmp_str, "vi");
+ comma = 1;
+ }
+ if (! (interrupts & 1))
+ {
+ if (comma) strcat (tmp_str, ",");
+ strcat (tmp_str, "nvi");
+ }
+}
+
+static void
+print_flags(char *tmp_str, unsigned long flags)
+{
+ int comma = 0;
+
+ *tmp_str = 0;
+ if (flags & 8)
+ {
+ strcat (tmp_str, "c");
+ comma = 1;
+ }
+ if (flags & 4)
+ {
+ if (comma) strcat (tmp_str, ",");
+ strcat (tmp_str, "z");
+ comma = 1;
+ }
+ if (flags & 2)
+ {
+ if (comma) strcat (tmp_str, ",");
+ strcat (tmp_str, "s");
+ comma = 1;
+ }
+ if (flags & 1)
+ {
+ if (comma) strcat (tmp_str, ",");
+ strcat (tmp_str, "p");
+ }
+}
static void
unparse_instr (instr_data_s *instr_data, int is_segmented)
@@ -529,12 +570,12 @@ unparse_instr (instr_data_s *instr_data,
strcat (out_str, tmp_str);
break;
case CLASS_IMM:
- if (datum_value == ARG_IMM2) /* True with EI/DI instructions only. */
- {
- sprintf (tmp_str, "%s", intr_names[instr_data->interrupts]);
- strcat (out_str, tmp_str);
- break;
- }
+ if (datum_value == ARG_IMM2) /* True with EI/DI instructions only. */
+ {
+ print_intr (tmp_str, instr_data->interrupts);
+ strcat (out_str, tmp_str);
+ break;
+ }
sprintf (tmp_str, "#0x%0lx", instr_data->immediate);
strcat (out_str, tmp_str);
break;
@@ -563,7 +604,7 @@ unparse_instr (instr_data_s *instr_data,
strcat (out_str, tmp_str);
break;
case CLASS_FLAGS:
- sprintf (tmp_str, "0x%0lx", instr_data->flags);
+ print_flags(tmp_str, instr_data->flags);
strcat (out_str, tmp_str);
break;
case CLASS_REG_BYTE: