/* tc-w65.c -- Assemble code for the W65816
- Copyright 1995, 1998, 2000 Free Software Foundation, Inc.
+ Copyright 1995, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
#include "subsegs.h"
#define DEFINE_TABLE
#include "../opcodes/w65-opc.h"
-#include <ctype.h>
const char comment_chars[] = "!";
-CONST char line_separator_chars[] = ";";
+const char line_separator_chars[] = ";";
const char line_comment_chars[] = "!#";
/* This table describes all the machine specific pseudo-ops the assembler
#define OP_BVC 0x50
#define OP_BVS 0x70
-void s_longa ();
+static void s_longa PARAMS ((int));
+static char *parse_exp PARAMS ((char *));
+static char *get_operands PARAMS ((const struct opinfo *, char *));
+static const struct opinfo *get_specific PARAMS ((const struct opinfo *));
+static void build_Mytes PARAMS ((const struct opinfo *));
+
const pseudo_typeS md_pseudo_table[] = {
{"int", cons, 2},
{0, 0, 0}
};
-void cons ();
-void s_align_bytes ();
-
#if 0
int md_reloc_size;
#endif
-static int relax; /* set if -relax seen */
-
const char EXP_CHARS[] = "eE";
/* Chars that mean this number is a floating point constant. */
#define WORD_F 32767
#define WORD_B 32768
-relax_typeS md_relax_table[C (END, 0)];
+relax_typeS md_relax_table[C (END, 0)] = {
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+
+ /* COND_BRANCH */
+ { 0, 0, 0, 0 }, /* UNDEF_BYTE_DISP */
+ { BYTE_F, BYTE_B, 2, C (COND_BRANCH, WORD_DISP) }, /* BYTE_DISP */
+ { WORD_F, WORD_B, 5, 0 }, /* WORD_DISP */
+ { 0, 0, 5, 0 }, /* UNDEF_WORD_DISP */
+
+ /* UNCOND_BRANCH */
+ { 0, 0, 0, 0 }, /* UNDEF_BYTE_DISP */
+ { BYTE_F, BYTE_B, 2, C (UNCOND_BRANCH, WORD_DISP) }, /* BYTE_DISP */
+ { WORD_F, WORD_B, 3, 0 }, /* WORD_DISP */
+ { 0, 0, 3, 0 } /* UNDEF_WORD_DISP */
+
+};
/* This function is called once, at assembler startup time. This
should set up all the tables, etc that the MD part of the assembler
needs. */
-void
+static void
s_longa (xmode)
+ int xmode;
{
int *p = xmode ? &X : &M;
while (*input_line_pointer == ' ')
void
md_begin ()
{
- relax_typeS *table;
- struct opinfo *opcode;
+ const struct opinfo *opcode;
char *prev_name = "";
opcode_hash_control = hash_new ();
prev_name = opcode->name;
hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
}
- else
- {
- /* Make all the opcodes with the same name point to the same
- string. */
- opcode->name = prev_name;
- }
}
- /* Initialize the relax table. We use a local variable to avoid
- warnings about modifying a supposedly const data structure. */
- table = (relax_typeS *) md_relax_table;
- table[C (COND_BRANCH, BYTE_DISP)].rlx_forward = BYTE_F;
- table[C (COND_BRANCH, BYTE_DISP)].rlx_backward = BYTE_B;
- table[C (COND_BRANCH, BYTE_DISP)].rlx_length = 2;
- table[C (COND_BRANCH, BYTE_DISP)].rlx_more = C (COND_BRANCH, WORD_DISP);
-
- table[C (COND_BRANCH, WORD_DISP)].rlx_forward = WORD_F;
- table[C (COND_BRANCH, WORD_DISP)].rlx_backward = WORD_B;
- table[C (COND_BRANCH, WORD_DISP)].rlx_length = 5;
- table[C (COND_BRANCH, WORD_DISP)].rlx_more = 0;
-
- table[C (UNCOND_BRANCH, BYTE_DISP)].rlx_forward = BYTE_F;
- table[C (UNCOND_BRANCH, BYTE_DISP)].rlx_backward = BYTE_B;
- table[C (UNCOND_BRANCH, BYTE_DISP)].rlx_length = 2;
- table[C (UNCOND_BRANCH, BYTE_DISP)].rlx_more = C (UNCOND_BRANCH, WORD_DISP);
-
- table[C (UNCOND_BRANCH, WORD_DISP)].rlx_forward = WORD_F;
- table[C (UNCOND_BRANCH, WORD_DISP)].rlx_backward = WORD_B;
- table[C (UNCOND_BRANCH, WORD_DISP)].rlx_length = 3;
- table[C (UNCOND_BRANCH, WORD_DISP)].rlx_more = 0;
-
flag_signed_overflow_ok = 1;
}
static expressionS immediate; /* absolute expression */
static expressionS immediate1; /* absolute expression */
-
-static symbolS *
-dot ()
-{
- const char *fake;
-
- /* JF: '.' is pseudo symbol with value of current location
- in current segment. */
- fake = FAKE_LABEL_NAME;
- return symbol_new (fake,
- now_seg,
- (valueT) frag_now_fix (),
- frag_now);
-
-}
-
int expr_size;
int expr_shift;
int tc_cons_reloc;
void
-w65_expression (dest, bytes)
+w65_expression (dest)
expressionS *dest;
- unsigned int bytes;
{
expr_size = 0;
expr_shift = 0;
int amode;
static char *
-parse_exp (s, bytes)
+parse_exp (s)
char *s;
- int bytes;
{
char *save;
char *new;
save = input_line_pointer;
input_line_pointer = s;
- w65_expression (&immediate, bytes);
+ w65_expression (&immediate);
if (immediate.X_op == O_absent)
as_bad (_("missing operand"));
new = input_line_pointer;
static char *
get_operands (info, ptr)
- struct opinfo *info;
+ const struct opinfo *info;
char *ptr;
{
register int override_len = 0;
}
else
{
- ptr = parse_exp (ptr, 2);
+ ptr = parse_exp (ptr);
if (ptr[0] == ',')
{
if (ptr[1] == 'y')
addressing modes, return the opcode which matches the opcodes
provided. */
-static struct opinfo *
+static const struct opinfo *
get_specific (opcode)
- struct opinfo *opcode;
+ const struct opinfo *opcode;
{
int ocode = opcode->code;
return 0;
}
-int
-check (operand, low, high)
- expressionS *operand;
- int low;
- int high;
-{
- if (operand->X_op != O_constant
- || operand->X_add_number < low
- || operand->X_add_number > high)
- {
- as_bad ("operand must be absolute in range %d..%d", low, high);
- }
- return operand->X_add_number;
-}
-
-static int log2[] = { 0, 0, 1, 0, 2 };
-
/* Now we know what sort of opcodes it is, let's build the bytes. */
static void
build_Mytes (opcode)
- struct opinfo *opcode;
+ const struct opinfo *opcode;
{
int size;
int type;
switch (opcode->amode)
{
GETINFO (size, type, pcrel);
+ default:
+ abort ();
}
/* If something special was done in the expression modify the
md_assemble (str)
char *str;
{
- unsigned char *op_start;
- unsigned char *op_end;
- struct opinfo *opcode;
+ const struct opinfo *opcode;
char name[20];
- int nlen = 0;
- char *p;
/* Drop leading whitespace */
while (*str == ' ')
build_Mytes (opcode);
}
-void
-tc_crawl_symbol_chain (headers)
- object_headers *headers;
-{
- printf (_("call to tc_crawl_symbol_chain \n"));
-}
-
symbolS *
md_undefined_symbol (name)
- char *name;
+ char *name ATTRIBUTE_UNUSED;
{
return 0;
}
-void
-tc_headers_hook (headers)
- object_headers *headers;
-{
- printf (_("call to tc_headers_hook \n"));
-}
-
/* Various routines to kill one day. */
/* Equal to MAX_PRECISION in atof-ieee.c. */
#define MAX_LITTLENUMS 6
LITTLENUM_TYPE words[MAX_LITTLENUMS];
LITTLENUM_TYPE *wordP;
char *t;
- char *atof_ieee ();
switch (type)
{
int
md_parse_option (c, a)
- int c;
- char *a;
+ int c ATTRIBUTE_UNUSED;
+ char *a ATTRIBUTE_UNUSED;
{
- return 1;
-}
-
-void
-tc_Nout_fix_to_chars ()
-{
- printf (_("call to tc_Nout_fix_to_chars \n"));
- abort ();
+ return 0;
}
/* Called after relaxing, change the frags so they know how big they
void
md_convert_frag (headers, seg, fragP)
- object_headers *headers;
- segT seg;
+ object_headers *headers ATTRIBUTE_UNUSED;
+ segT seg ATTRIBUTE_UNUSED;
fragS *fragP;
{
int disp_size = 0;
}
void
-md_apply_fix (fixP, val)
+md_apply_fix3 (fixP, valP, seg)
fixS *fixP;
- long val;
+ valueT * valP;
+ segT seg ATTRIBUTE_UNUSED;
{
+ long val = * (long *) valP;
char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
int addr = fixP->fx_frag->fr_address + fixP->fx_where;
default:
abort ();
}
+
+ if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
+ fixP->fx_done = 1;
}
-/* Put number into target byte order */
+/* Put number into target byte order. */
void
md_number_to_chars (ptr, use, nbytes)
void
tc_coff_symbol_emit_hook (x)
- symbolS *x;
+ symbolS *x ATTRIBUTE_UNUSED;
{
}
register fragS *fragP;
register segT segment_type;
{
- int what = GET_WHAT (fragP->fr_subtype);
+ int what;
switch (fragP->fr_subtype)
{
default:
abort ();
+
case C (COND_BRANCH, UNDEF_BYTE_DISP):
case C (UNCOND_BRANCH, UNDEF_BYTE_DISP):
+ what = GET_WHAT (fragP->fr_subtype);
/* Used to be a branch to somewhere which was unknown. */
if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
{
/* Got a symbol and it's defined in this segment, become byte
sized - maybe it will fix up. */
fragP->fr_subtype = C (what, BYTE_DISP);
- fragP->fr_var = md_relax_table[C (what, BYTE_DISP)].rlx_length;
}
else
{
/* Its got a segment, but its not ours, so it will always be
long. */
fragP->fr_subtype = C (what, UNDEF_WORD_DISP);
- fragP->fr_var = md_relax_table[C (what, WORD_DISP)].rlx_length;
- return md_relax_table[C (what, WORD_DISP)].rlx_length;
}
+ break;
+
+ case C (COND_BRANCH, BYTE_DISP):
+ case C (COND_BRANCH, WORD_DISP):
+ case C (COND_BRANCH, UNDEF_WORD_DISP):
+ case C (UNCOND_BRANCH, BYTE_DISP):
+ case C (UNCOND_BRANCH, WORD_DISP):
+ case C (UNCOND_BRANCH, UNDEF_WORD_DISP):
+ /* When relaxing a section for the second time, we don't need to
+ do anything besides return the current size. */
+ break;
}
+
+ fragP->fr_var = md_relax_table[fragP->fr_subtype].rlx_length;
return fragP->fr_var;
}
-CONST char *md_shortopts = "";
+const char *md_shortopts = "";
struct option md_longopts[] = {
#define OPTION_RELAX (OPTION_MD_BASE)
{NULL, no_argument, NULL, 0}
void
md_show_usage (stream)
- FILE *stream;
+ FILE *stream ATTRIBUTE_UNUSED;
{
}