const char line_comment_chars[] = "#";
const char line_separator_chars[] = "";
-void cons PARAMS ((int));
-void sbranch PARAMS ((int));
-void h8300hmode PARAMS ((int));
-void h8300smode PARAMS ((int));
-void h8300hnmode PARAMS ((int));
-void h8300snmode PARAMS ((int));
-void h8300sxmode PARAMS ((int));
-static void pint PARAMS ((int));
+void cons PARAMS ((int));
+void sbranch PARAMS ((int));
+void h8300hmode PARAMS ((int));
+void h8300smode PARAMS ((int));
+void h8300hnmode PARAMS ((int));
+void h8300snmode PARAMS ((int));
+void h8300sxmode PARAMS ((int));
+void h8300sxnmode PARAMS ((int));
+static void pint PARAMS ((int));
int Hmode;
int Smode;
int SXmode;
#define PSIZE (Hmode ? L_32 : L_16)
-#define DSYMMODE (Hmode ? L_24 : L_16)
int bsize = L_8; /* Default branch displacement. */
static void do_a_fix_imm PARAMS ((int, int, struct h8_op *, int));
static void check_operand PARAMS ((struct h8_op *, unsigned int, char *));
static const struct h8_instruction * get_specific PARAMS ((const struct h8_instruction *, struct h8_op *, int));
-static char * get_operands PARAMS ((unsigned, char *, struct h8_op *));
-static void get_operand PARAMS ((char **, struct h8_op *, int));
-static char * skip_colonthing PARAMS ((char *, expressionS *, int *));
-static char * parse_exp PARAMS ((char *, expressionS *));
-static int parse_reg PARAMS ((char *, op_type *, unsigned *, int));
-char * colonmod24 PARAMS ((struct h8_op *, char *));
+static char *get_operands PARAMS ((unsigned, char *, struct h8_op *));
+static void get_operand PARAMS ((char **, struct h8_op *, int));
+static int parse_reg PARAMS ((char *, op_type *, unsigned *, int));
+static char *skip_colonthing PARAMS ((char *, int *));
+static char *parse_exp PARAMS ((char *, struct h8_op *));
static int constant_fits_width_p PARAMS ((struct h8_op *, unsigned int));
static int constant_fits_size_p PARAMS ((struct h8_op *, int, int));
return 0;
}
+
+/* Parse an immediate or address-related constant and store it in OP.
+ If the user also specifies the operand's size, store that size
+ in OP->MODE, otherwise leave it for later code to decide. */
+
static char *
-parse_exp (s, op)
- char *s;
- expressionS *op;
+parse_exp (src, op)
+ char *src;
+ struct h8_op *op;
{
- char *save = input_line_pointer;
- char *new;
+ char *save;
- input_line_pointer = s;
- expression (op);
- if (op->X_op == O_absent)
+ save = input_line_pointer;
+ input_line_pointer = src;
+ expression (&op->exp);
+ if (op->exp.X_op == O_absent)
as_bad (_("missing operand"));
- new = input_line_pointer;
+ src = input_line_pointer;
input_line_pointer = save;
- return new;
+
+ return skip_colonthing (src, &op->mode);
}
+
+/* If SRC starts with an explicit operand size, skip it and store the size
+ in *MODE. Leave *MODE unchanged otherwise. */
+
static char *
-skip_colonthing (ptr, exp, mode)
- char *ptr;
- expressionS *exp ATTRIBUTE_UNUSED;
+skip_colonthing (src, mode)
+ char *src;
int *mode;
{
- if (*ptr == ':')
+ if (*src == ':')
{
- ptr++;
+ src++;
*mode &= ~SIZE;
- if (ptr[0] == '8' && ! ISDIGIT (ptr[1]))
+ if (src[0] == '8' && !ISDIGIT (src[1]))
*mode |= L_8;
- else if (ptr[0] == '2' && ! ISDIGIT (ptr[1]))
+ else if (src[0] == '2' && !ISDIGIT (src[1]))
*mode |= L_2;
- else if (ptr[0] == '3' && ! ISDIGIT (ptr[1]))
+ else if (src[0] == '3' && !ISDIGIT (src[1]))
*mode |= L_3;
- else if (ptr[0] == '4' && ! ISDIGIT (ptr[1]))
+ else if (src[0] == '4' && !ISDIGIT (src[1]))
*mode |= L_4;
- else if (ptr[0] == '5' && ! ISDIGIT (ptr[1]))
+ else if (src[0] == '5' && !ISDIGIT (src[1]))
*mode |= L_5;
- else if (ptr[0] == '2' && ptr[1] == '4')
+ else if (src[0] == '2' && src[1] == '4' && !ISDIGIT (src[2]))
*mode |= L_24;
- else if (ptr[0] == '3' && ptr[1] == '2')
+ else if (src[0] == '3' && src[1] == '2' && !ISDIGIT (src[2]))
*mode |= L_32;
- else if (ptr[0] == '1' && ptr[1] == '6')
+ else if (src[0] == '1' && src[1] == '6' && !ISDIGIT (src[2]))
*mode |= L_16;
else
as_bad (_("invalid operand size requested"));
- while (ISDIGIT (*ptr))
- ptr++;
+ while (ISDIGIT (*src))
+ src++;
}
- return ptr;
+ return src;
}
/* The many forms of operand:
@(exp:[8], pc) pc rel
@@aa[:8] memory indirect. */
-char *
-colonmod24 (op, src)
- struct h8_op *op;
- char *src;
-{
- int mode = 0;
- src = skip_colonthing (src, &op->exp, &mode);
-
- if (!mode)
- {
- /* If the operand is a 16-bit constant integer, leave fix_operand_size
- to calculate its size. Otherwise choose a default here. */
- if (op->exp.X_add_number < -32768
- || op->exp.X_add_number > 32767)
- {
- if (Hmode)
- mode = L_24;
- else
- mode = L_16;
- }
- else if (op->exp.X_add_symbol
- || op->exp.X_op_symbol)
- mode = DSYMMODE;
- }
-
- op->mode |= mode;
- return src;
-}
-
static int
constant_fits_width_p (operand, width)
struct h8_op *operand;
src++;
if (*src == '@')
{
- src++;
- src = parse_exp (src, &op->exp);
-
- src = skip_colonthing (src, &op->exp, &op->mode);
-
- *ptr = src;
-
+ *ptr = parse_exp (src + 1, op);
if (op->exp.X_add_number >= 0x100)
{
int divisor;
}
else
op->mode = MEMIND;
-
return;
}
if (*src == '-' || *src == '+')
{
- char c = *src;
- src++;
- len = parse_reg (src, &mode, &num, direction);
+ len = parse_reg (src + 1, &mode, &num, direction);
if (len == 0)
{
/* Oops, not a reg after all, must be ordinary exp. */
- src--;
- /* Must be a symbol. */
- op->mode = ABS | PSIZE | direction;
- *ptr = skip_colonthing (parse_exp (src, &op->exp),
- &op->exp, &op->mode);
-
+ op->mode = ABS | direction;
+ *ptr = parse_exp (src, op);
return;
}
if ((mode & SIZE) != PSIZE)
as_bad (_("Wrong size pointer register for architecture."));
- op->mode = c == '-' ? RDPREDEC : RDPREINC;
+
+ op->mode = src[0] == '-' ? RDPREDEC : RDPREINC;
op->reg = num;
- *ptr = src + len;
+ *ptr = src + 1 + len;
return;
}
if (*src == '(')
/* Start off assuming a 16 bit offset. */
- src = parse_exp (src, &op->exp);
-
- src = colonmod24 (op, src);
-
+ src = parse_exp (src, op);
if (*src == ')')
{
- src++;
op->mode |= ABS | direction;
- *ptr = src;
+ *ptr = src + 1;
return;
}
{
as_bad (_("expected @(exp, reg16)"));
return;
-
}
src++;
}
else
op->mode |= DISP | direction;
- src = skip_colonthing (src, &op->exp, &op->mode);
+ src = skip_colonthing (src, &op->mode);
if (*src != ')' && '(')
{
return;
}
*ptr = src + 1;
-
return;
}
len = parse_reg (src, &mode, &num, direction);
/* must be a symbol */
op->mode = ABS | direction;
- src = parse_exp (src, &op->exp);
-
- *ptr = colonmod24 (op, src);
-
+ *ptr = parse_exp (src, op);
return;
}
}
if (*src == '#')
{
- src++;
op->mode = IMM;
- src = parse_exp (src, &op->exp);
- *ptr = skip_colonthing (src, &op->exp, &op->mode);
-
+ *ptr = parse_exp (src + 1, op);
return;
}
else if (strncmp (src, "mach", 4) == 0 ||
}
else
{
- src = parse_exp (src, &op->exp);
- /* Trailing ':' size ? */
- if (*src == ':')
- {
- if (src[1] == '1' && src[2] == '6')
- {
- op->mode = PCREL | L_16;
- src += 3;
- }
- else if (src[1] == '8')
- {
- op->mode = PCREL | L_8;
- src += 2;
- }
- else
- as_bad (_("expect :8 or :16 here"));
- }
- else
- {
- int val = op->exp.X_add_number;
-
- op->mode = PCREL;
- if (-128 < val && val < 127)
- op->mode |= L_8;
- else
- op->mode |= L_16;
- }
-
- *ptr = src;
+ op->mode = PCREL;
+ *ptr = parse_exp (src, op);
}
}
goto error;
ptr += 3;
operand[0].mode = 0;
- ptr = parse_exp (ptr, &operand[0].exp);
- ptr = colonmod24 (operand + 0, ptr);
+ ptr = parse_exp (ptr, &operand[0]);
if (*ptr !=',')
goto error;
}
-/* Adjust OPERAND's value and size given that it is accessing a field
- of SIZE bytes.
+/* If OPERAND is part of an address, adjust its size and value given
+ that it addresses SIZE bytes.
- This function handles the choice between @(d:2,ERn) and @(d:16,ERn)
- when no size is explicitly given. It also scales down the assembly-level
+ This function decides how big non-immediate constants are when no
+ size was explicitly given. It also scales down the assembly-level
displacement in an @(d:2,ERn) operand. */
static void
struct h8_op *operand;
int size;
{
- if ((operand->mode & MODE) == DISP)
+ if (SXmode && (operand->mode & MODE) == DISP)
{
/* If the user didn't specify an operand width, see if we
can use @(d:2,ERn). */
- if (SXmode
- && (operand->mode & SIZE) == 0
+ if ((operand->mode & SIZE) == 0
+ && operand->exp.X_add_symbol == 0
+ && operand->exp.X_op_symbol == 0
&& (operand->exp.X_add_number == size
|| operand->exp.X_add_number == size * 2
|| operand->exp.X_add_number == size * 3))
}
}
- /* If the operand needs a size but doesn't have one yet, it must be
- a 16-bit integer (see colonmod24). */
if ((operand->mode & SIZE) == 0)
switch (operand->mode & MODE)
{
case INDEXW:
case INDEXL:
case ABS:
- operand->mode |= L_16;
+ /* Pick a 24-bit address unless we know that a 16-bit address
+ is safe. get_specific() will relax L_24 into L_32 where
+ necessary. */
+ if (Hmode
+ && (operand->exp.X_add_number < -32768
+ || operand->exp.X_add_number > 32767
+ || operand->exp.X_add_symbol != 0
+ || operand->exp.X_op_symbol != 0))
+ operand->mode |= L_24;
+ else
+ operand->mode |= L_16;
+ break;
+
+ case PCREL:
+ /* This condition is long standing, though somewhat suspect. */
+ if (operand->exp.X_add_number > -128
+ && operand->exp.X_add_number < 127)
+ operand->mode |= L_8;
+ else
+ operand->mode |= L_16;
break;
}
}
Disassembly of section \.text:
0+00 <\.text>:
- * 0: 01 75 68 08 * 01 75 68 08 80 02 add.b #0x2,@\(0x1:2,r0\)
- * 4: 80 02 *
- * 6: 01 76 68 08 * 01 76 68 08 80 02 add.b #0x2,@\(0x2:2,r0\)
- * a: 80 02 *
- * c: 01 77 68 08 * 01 77 68 08 80 02 add.b #0x2,@\(0x3:2,r0\)
- *10: 80 02 *
- *12: 01 74 6e 08 * 01 74 6e 08 00 04 80 02 add.b #0x2,@\(0x4:16,r0\)
- *16: 00 04 80 02 *
- *1a: 01 5e c0 10 * 01 5e c0 10 00 01 00 02 add.w #0x2,@\(0x1:16,r0\)
- *1e: 00 01 00 02 *
- *22: 01 5e 10 10 * 01 5e 10 10 00 02 add.w #0x2,@\(0x2:2,r0\)
- *26: 00 02 *
- *28: 01 5e 20 10 * 01 5e 20 10 00 02 add.w #0x2,@\(0x4:2,r0\)
- *2c: 00 02 *
- *2e: 01 5e 30 10 * 01 5e 30 10 00 02 add.w #0x2,@\(0x6:2,r0\)
- *32: 00 02 *
- *34: 01 5e c0 10 * 01 5e c0 10 00 08 00 02 add.w #0x2,@\(0x8:16,r0\)
- *38: 00 08 00 02 *
- *3c: 01 0e c0 10 * 01 0e c0 10 00 01 00 02 add.l #0x2,@\(0x1:16,r0\)
- *40: 00 01 00 02 *
- *44: 01 0e c0 10 * 01 0e c0 10 00 02 00 02 add.l #0x2,@\(0x2:16,r0\)
- *48: 00 02 00 02 *
- *4c: 01 0e 10 10 * 01 0e 10 10 00 02 add.l #0x2,@\(0x4:2,r0\)
- *50: 00 02 *
- *52: 01 0e 20 10 * 01 0e 20 10 00 02 add.l #0x2,@\(0x8:2,r0\)
- *56: 00 02 *
- *58: 01 0e 30 10 * 01 0e 30 10 00 02 add.l #0x2,@\(0xc:2,r0\)
- *5c: 00 02 *
- *5e: 01 0e c0 10 * 01 0e c0 10 00 10 00 02 add.l #0x2,@\(0x10:16,r0\)
- *62: 00 10 00 02 *
+ .*: 01 75 68 08 * 01 75 68 08 80 02 add.b #0x2,@\(0x1:2,r0\)
+ .*: 80 02 *
+ .*: 01 76 68 08 * 01 76 68 08 80 02 add.b #0x2,@\(0x2:2,r0\)
+ .*: 80 02 *
+ .*: 01 77 68 08 * 01 77 68 08 80 02 add.b #0x2,@\(0x3:2,r0\)
+ .*: 80 02 *
+ .*: 01 74 6e 08 * 01 74 6e 08 00 04 80 02 add.b #0x2,@\(0x4:16,r0\)
+ .*: 00 04 80 02 *
+ .*: 78 04 6a 28 * 78 04 6a 28 00 00 00 00 80 02 add.b #0x2,@\(0x0:32,r0\)
+ .*: 00 00 00 00 *
+ .*: 80 02 *
+ .*: 01 5e c0 10 * 01 5e c0 10 00 01 00 02 add.w #0x2,@\(0x1:16,r0\)
+ .*: 00 01 00 02 *
+ .*: 01 5e 10 10 * 01 5e 10 10 00 02 add.w #0x2,@\(0x2:2,r0\)
+ .*: 00 02 *
+ .*: 01 5e 20 10 * 01 5e 20 10 00 02 add.w #0x2,@\(0x4:2,r0\)
+ .*: 00 02 *
+ .*: 01 5e 30 10 * 01 5e 30 10 00 02 add.w #0x2,@\(0x6:2,r0\)
+ .*: 00 02 *
+ .*: 01 5e c0 10 * 01 5e c0 10 00 08 00 02 add.w #0x2,@\(0x8:16,r0\)
+ .*: 00 08 00 02 *
+ .*: 01 5e c8 10 * 01 5e c8 10 00 00 00 00 00 02 add.w #0x2,@\(0x0:32,r0\)
+ .*: 00 00 00 00 *
+ .*: 00 02 *
+ .*: 01 0e c0 10 * 01 0e c0 10 00 01 00 02 add.l #0x2,@\(0x1:16,r0\)
+ .*: 00 01 00 02 *
+ .*: 01 0e c0 10 * 01 0e c0 10 00 02 00 02 add.l #0x2,@\(0x2:16,r0\)
+ .*: 00 02 00 02 *
+ .*: 01 0e 10 10 * 01 0e 10 10 00 02 add.l #0x2,@\(0x4:2,r0\)
+ .*: 00 02 *
+ .*: 01 0e 20 10 * 01 0e 20 10 00 02 add.l #0x2,@\(0x8:2,r0\)
+ .*: 00 02 *
+ .*: 01 0e 30 10 * 01 0e 30 10 00 02 add.l #0x2,@\(0xc:2,r0\)
+ .*: 00 02 *
+ .*: 01 0e c0 10 * 01 0e c0 10 00 10 00 02 add.l #0x2,@\(0x10:16,r0\)
+ .*: 00 10 00 02 *
+ .*: 01 0e c8 10 * 01 0e c8 10 00 00 00 00 00 02 add.l #0x2,@\(0x0:32,r0\)
+ .*: 00 00 00 00 *
+ .*: 00 02 *