-/* tc-z8k.c -- Assemble code for the Zilog Z800N
- Copyright (C) 1992 Free Software Foundation.
+/* tc-z8k.c -- Assemble code for the Zilog Z800n
+ Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 1999 Free Software Foundation.
This file is part of GAS, the GNU Assembler.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with GAS; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/*
Written By Steve Chamberlain
#define DEFINE_TABLE
#include <stdio.h>
-#include "../opcodes/z8k-opc.h"
+#include "opcodes/z8k-opc.h"
#include "as.h"
#include "bfd.h"
void
even ()
{
- frag_align (1, 0);
+ frag_align (1, 0, 0);
record_alignment (now_seg, 1);
}
/* or 0d1.2345e12 */
const char FLT_CHARS[] = "rRsSfFdDxXpP";
-const relax_typeS md_relax_table[1];
-
static struct hash_control *opcode_hash_control; /* Opcode mnemonics */
void
fake_opcode->name = md_pseudo_table[idx].poc_name,
fake_opcode->func = (void *) (md_pseudo_table + idx);
fake_opcode->opcode = 250;
-
hash_insert (opcode_hash_control, fake_opcode->name, fake_opcode);
-
}
+
+ linkrelax = 1;
}
struct z8k_exp
int reg[16];
int the_cc;
+int the_ctrl;
+int the_flags;
+int the_interrupt;
char *
DEFUN (whatreg, (reg, src),
unsigned int *reg)
{
char *res = 0;
+ char regno;
if (src[0] == 's' && src[1] == 'p')
{
if (segmented_mode)
- {
- *mode = CLASS_REG_LONG;
- *reg = 14;
- }
+ {
+ *mode = CLASS_REG_LONG;
+ *reg = 14;
+ }
else
- {
- *mode = CLASS_REG_WORD;
- *reg = 15;
- }
+ {
+ *mode = CLASS_REG_WORD;
+ *reg = 15;
+ }
return src + 2;
}
if (src[0] == 'r')
{
if (src[1] == 'r')
- {
- *mode = CLASS_REG_LONG;
- res = whatreg (reg, src + 2);
- }
+ {
+ *mode = CLASS_REG_LONG;
+ res = whatreg (reg, src + 2);
+ regno = *reg;
+ if (regno > 14)
+ as_warn (_("register rr%d, out of range."),regno);
+ }
else if (src[1] == 'h')
- {
- *mode = CLASS_REG_BYTE;
- res = whatreg (reg, src + 2);
- }
+ {
+ *mode = CLASS_REG_BYTE;
+ res = whatreg (reg, src + 2);
+ regno = *reg;
+ if (regno > 7)
+ as_warn (_("register rh%d, out of range."),regno);
+ }
else if (src[1] == 'l')
- {
- *mode = CLASS_REG_BYTE;
- res = whatreg (reg, src + 2);
- *reg += 8;
- }
+ {
+ *mode = CLASS_REG_BYTE;
+ res = whatreg (reg, src + 2);
+ regno = *reg;
+ if (regno > 7)
+ as_warn (_("register rl%d, out of range."),regno);
+ *reg += 8;
+ }
else if (src[1] == 'q')
- {
- *mode = CLASS_REG_QUAD;
- res = whatreg (reg, src + 2);
- }
+ {
+ *mode = CLASS_REG_QUAD;
+ res = whatreg (reg, src + 2);
+ regno = *reg;
+ if (regno > 12)
+ as_warn (_("register rq%d, out of range."),regno);
+ }
else
- {
- *mode = CLASS_REG_WORD;
- res = whatreg (reg, src + 1);
- }
+ {
+ *mode = CLASS_REG_WORD;
+ res = whatreg (reg, src + 1);
+ regno = *reg;
+ if (regno > 15)
+ as_warn (_("register r%d, out of range."),regno);
+ }
}
return res;
input_line_pointer = s;
expression (op);
if (op->X_op == O_absent)
- as_bad ("missing operand");
+ as_bad (_("missing operand"));
new = input_line_pointer;
input_line_pointer = save;
return new;
ptr++;
else
{
- as_bad ("expected %c", what);
+ as_bad (_("expected %c"), what);
}
return ptr;
}
ok = CLASS_REG_WORD;
if (ok != mode)
{
- as_bad ("register is wrong size for a word %s", string);
+ as_bad (_("register is wrong size for a word %s"), string);
}
}
ok = segmented_mode ? CLASS_REG_LONG : CLASS_REG_WORD;
if (ok != mode)
{
- as_bad ("register is wrong size for address %s", string);
+ as_bad (_("register is wrong size for address %s"), string);
+ }
+}
+
+struct ctrl_names
+{
+ int value;
+ char *name;
+};
+
+struct ctrl_names ctrl_table[] =
+{
+ 0x2, "fcw",
+ 0X3, "refresh",
+ 0x4, "psapseg",
+ 0x5, "psapoff",
+ 0x5, "psap",
+ 0x6, "nspseg",
+ 0x7, "nspoff",
+ 0x7, "nsp",
+ 0, 0
+};
+
+static void
+DEFUN (get_ctrl_operand, (ptr, mode, dst),
+ char **ptr AND
+ struct z8k_op *mode AND
+ unsigned int dst)
+{
+ char *src = *ptr;
+ int r;
+ int i;
+
+ while (*src == ' ')
+ src++;
+
+ mode->mode = CLASS_CTRL;
+ for (i = 0; ctrl_table[i].name; i++)
+ {
+ int j;
+
+ for (j = 0; ctrl_table[i].name[j]; j++)
+ {
+ if (ctrl_table[i].name[j] != src[j])
+ goto fail;
+ }
+ the_ctrl = ctrl_table[i].value;
+ *ptr = src + j;
+ return;
+ fail:;
+ }
+ the_ctrl = 0;
+ return;
+}
+
+struct flag_names
+{
+ int value;
+ char *name;
+
+};
+
+struct flag_names flag_table[] =
+{
+ 0x1, "p",
+ 0x1, "v",
+ 0x2, "s",
+ 0x4, "z",
+ 0x8, "c",
+ 0x0, "+",
+ 0, 0
+};
+
+static void
+DEFUN (get_flags_operand, (ptr, mode, dst),
+ char **ptr AND
+ struct z8k_op *mode AND
+ unsigned int dst)
+{
+ char *src = *ptr;
+ int r;
+ int i;
+ int j;
+
+ while (*src == ' ')
+ src++;
+
+ mode->mode = CLASS_FLAGS;
+ the_flags = 0;
+ for (j = 0; j <= 9; j++)
+ {
+ if (!src[j])
+ goto done;
+ for (i = 0; flag_table[i].name; i++)
+ {
+ if (flag_table[i].name[0] == src[j])
+ {
+ the_flags = the_flags | flag_table[i].value;
+ goto match;
+ }
+ }
+ goto done;
+ match:
+ ;
+ }
+ done:
+ *ptr = src + j;
+ return;
+}
+
+
+struct interrupt_names
+{
+ int value;
+ char *name;
+
+};
+
+struct interrupt_names intr_table[] =
+{
+ 0x1, "nvi",
+ 0x2, "vi",
+ 0x3, "both",
+ 0x3, "all",
+ 0, 0
+};
+
+static void
+DEFUN (get_interrupt_operand, (ptr, mode, dst),
+ char **ptr AND
+ struct z8k_op *mode AND
+ unsigned int dst)
+{
+ char *src = *ptr;
+ int r;
+ int i;
+
+ while (*src == ' ')
+ src++;
+
+ mode->mode = CLASS_IMM;
+ for (i = 0; intr_table[i].name; i++)
+ {
+ int j;
+
+ for (j = 0; intr_table[i].name[j]; j++)
+ {
+ if (intr_table[i].name[j] != src[j])
+ goto fail;
+ }
+ the_interrupt = intr_table[i].value;
+ *ptr = src + j;
+ return;
+ fail:;
}
+ the_interrupt = 0x0;
+ return;
}
struct cc_names
fail:;
}
the_cc = 0x8;
- return;
}
static void
if (*src != ')')
{
- as_bad ("Missing ) in ra(rb)");
+ as_bad (_("Missing ) in ra(rb)"));
}
else
{
op_type *operand;
{
char *ptr = op_end;
-
+char *savptr;
switch (opcode->noperands)
{
case 0:
case 1:
ptr++;
if (opcode->arg_info[0] == CLASS_CC)
- {
- get_cc_operand (&ptr, operand + 0, 0);
- }
+ {
+ get_cc_operand (&ptr, operand + 0, 0);
+ }
+ else if (opcode->arg_info[0] == CLASS_FLAGS)
+ {
+ get_flags_operand (&ptr, operand + 0, 0);
+ }
+ else if (opcode->arg_info[0] == (CLASS_IMM +(ARG_IMM2)))
+ {
+ get_interrupt_operand (&ptr, operand + 0, 0);
+ }
else
- {
-
- get_operand (&ptr, operand + 0, 0);
- }
+ {
+ get_operand (&ptr, operand + 0, 0);
+ }
operand[1].mode = 0;
break;
case 2:
ptr++;
+ savptr = ptr;
if (opcode->arg_info[0] == CLASS_CC)
- {
- get_cc_operand (&ptr, operand + 0, 0);
- }
+ {
+ get_cc_operand (&ptr, operand + 0, 0);
+ }
+ else if (opcode->arg_info[0] == CLASS_CTRL)
+ {
+ get_ctrl_operand (&ptr, operand + 0, 0);
+ if (the_ctrl == 0)
+ {
+ ptr = savptr;
+ get_operand (&ptr, operand + 0, 0);
+ if (ptr == 0)
+ return;
+ if (*ptr == ',')
+ ptr++;
+ get_ctrl_operand (&ptr, operand + 1, 1);
+ return ptr;
+ }
+ }
else
- {
-
- get_operand (&ptr, operand + 0, 0);
- }
+ {
+ get_operand (&ptr, operand + 0, 0);
+ }
if (ptr == 0)
- return;
+ return;
if (*ptr == ',')
- ptr++;
+ ptr++;
get_operand (&ptr, operand + 1, 1);
break;
if ((operand->exp.X_add_number & ~width) != 0 &&
(operand->exp.X_add_number | width) != (~0))
{
- as_warn ("operand %s0x%x out of range.", string, operand->exp.X_add_number);
+ as_warn (_("operand %s0x%x out of range."), string, operand->exp.X_add_number);
}
}
/* pc rel 7 bit */
*output_ptr = 0x80;
output_ptr = apply_fix (output_ptr, R_DISP7, da_operand, 2);
+ output_ptr[-2] = 0x8;
da_operand = 0;
break;
}
else if (imm_operand->X_add_number != 1)
{
- as_bad ("immediate must be 1 or 2");
+ as_bad (_("immediate must be 1 or 2"));
}
}
else
{
- as_bad ("immediate 1 or 2 expected");
+ as_bad (_("immediate 1 or 2 expected"));
}
output_ptr++;
break;
case CLASS_CC:
*output_ptr++ = the_cc;
break;
+ case CLASS_0CCC:
+ *output_ptr++ = the_ctrl;
+ break;
+ case CLASS_1CCC:
+ *output_ptr++ = the_ctrl | 0x8;
+ break;
+ case CLASS_00II:
+ *output_ptr++ = (~the_interrupt & 0x3);
+ break;
+ case CLASS_01II:
+ *output_ptr++ = (~the_interrupt & 0x3) | 0x4;
+ break;
+ case CLASS_FLAGS:
+ *output_ptr++ = the_flags;
+ break;
case CLASS_BIT:
*output_ptr++ = c & 0xf;
break;
case CLASS_REGN0:
if (reg[c & 0xf] == 0)
{
- as_bad ("can't use R0 here");
+ as_bad (_("can't use R0 here"));
}
case CLASS_REG:
case CLASS_REG_BYTE:
if (op_end == op_start)
{
- as_bad ("can't find opcode ");
+ as_bad (_("can't find opcode "));
}
c = *op_end;
if (opcode == NULL)
{
- as_bad ("unknown opcode");
+ as_bad (_("unknown opcode"));
return;
}
where[0] = 0x0;
where[1] = 0x0;
- as_bad ("Can't find opcode to match operands");
+ as_bad (_("Can't find opcode to match operands"));
return;
}
DEFUN (tc_crawl_symbol_chain, (headers),
object_headers * headers)
{
- printf ("call to tc_crawl_symbol_chain \n");
+ printf (_("call to tc_crawl_symbol_chain \n"));
}
symbolS *
DEFUN (tc_headers_hook, (headers),
object_headers * headers)
{
- printf ("call to tc_headers_hook \n");
-}
-
-void
-DEFUN_VOID (md_end)
-{
+ printf (_("call to tc_headers_hook \n"));
}
/* Various routines to kill one day */
default:
*sizeP = 0;
- return "Bad call to MD_ATOF()";
+ return _("Bad call to MD_ATOF()");
}
t = atof_ieee (input_line_pointer, type, words);
if (t)
}
return 0;
}
+\f
+CONST char *md_shortopts = "z:";
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
int
-md_parse_option (argP, cntP, vecP)
- char **argP;
- int *cntP;
- char ***vecP;
-
+md_parse_option (c, arg)
+ int c;
+ char *arg;
{
- if (!strcmp (*argP, "z8001"))
- {
- s_segm ();
- }
- else if (!strcmp (*argP, "z8002"))
+ switch (c)
{
- s_unseg ();
- }
- else
- return 0;
- **argP = 0;
- return 1;
-}
+ case 'z':
+ if (!strcmp (arg, "8001"))
+ s_segm ();
+ else if (!strcmp (arg, "8002"))
+ s_unseg ();
+ else
+ {
+ as_bad (_("invalid architecture -z%s"), arg);
+ return 0;
+ }
+ break;
-int md_short_jump_size;
+ default:
+ return 0;
+ }
-void
-tc_aout_fix_to_chars ()
-{
- printf ("call to tc_aout_fix_to_chars \n");
- abort ();
+ return 1;
}
void
-md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
- char *ptr;
- addressT from_addr;
- addressT to_addr;
- fragS *frag;
- symbolS *to_symbol;
+md_show_usage (stream)
+ FILE *stream;
{
- as_fatal ("failed sanity check.");
+ fprintf(stream, _("\
+Z8K options:\n\
+-z8001 generate segmented code\n\
+-z8002 generate unsegmented code\n"));
}
-
+\f
void
-md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
- char *ptr;
- addressT from_addr, to_addr;
- fragS *frag;
- symbolS *to_symbol;
+tc_aout_fix_to_chars ()
{
- as_fatal ("failed sanity check.");
+ printf (_("call to tc_aout_fix_to_chars \n"));
+ abort ();
}
void
-md_convert_frag (headers, fragP)
+md_convert_frag (headers, seg, fragP)
object_headers *headers;
+ segT seg;
fragS *fragP;
-
{
- printf ("call to md_convert_frag \n");
+ printf (_("call to md_convert_frag \n"));
abort ();
}
break;
#endif
+ case 0:
+ md_number_to_chars (buf, val, fixP->fx_size);
+ break;
+
default:
abort ();
}
}
-void
-DEFUN (md_operand, (expressionP), expressionS * expressionP)
-{
-}
-
-int md_long_jump_size;
int
md_estimate_size_before_relax (fragP, segment_type)
register fragS *fragP;
register segT segment_type;
{
- printf ("call tomd_estimate_size_before_relax \n");
+ printf (_("call tomd_estimate_size_before_relax \n"));
abort ();
}
valueT use AND
int nbytes)
{
- switch (nbytes)
- {
- case 4:
- *ptr++ = (use >> 24) & 0xff;
- case 3:
- *ptr++ = (use >> 16) & 0xff;
- case 2:
- *ptr++ = (use >> 8) & 0xff;
- case 1:
- *ptr++ = (use >> 0) & 0xff;
- break;
- default:
- abort ();
- }
+ number_to_chars_bigendian (ptr, use, nbytes);
}
long
md_pcrel_from (fixP)
}
void
-tc_coff_symbol_emit_hook ()
+tc_coff_symbol_emit_hook (s)
+ symbolS *s;
{
}
{
symbolS *symbol_ptr;
+ if (fix_ptr->fx_addsy &&
+ fix_ptr->fx_subsy)
+ {
+ symbolS *add = fix_ptr->fx_addsy;
+ symbolS *sub = fix_ptr->fx_subsy;
+ if (S_GET_SEGMENT(add) != S_GET_SEGMENT(sub))
+ {
+ as_bad(_("Can't subtract symbols in different sections %s %s"),
+ S_GET_NAME(add), S_GET_NAME(sub));
+ }
+ else {
+ int diff = S_GET_VALUE(add) - S_GET_VALUE(sub);
+ fix_ptr->fx_addsy = 0;
+ fix_ptr->fx_subsy = 0;
+ fix_ptr->fx_offset += diff;
+ }
+ }
symbol_ptr = fix_ptr->fx_addsy;
/* If this relocation is attached to a symbol then it's ok
to output it */
if (fix_ptr->fx_r_type == 0)
{
- /* cons likes to create reloc32's whatever the size of the reloc..
- */
+ /* cons likes to create reloc32's whatever the size of the reloc.. */
switch (fix_ptr->fx_size)
{
-
case 2:
intr->r_type = R_IMM16;
break;
break;
default:
abort ();
-
}
}
intr->r_symndx = symbol_ptr->sy_number;
else
intr->r_symndx = -1;
-
}
+