This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[RFA] h8300 assembler
- From: Michael Snyder <msnyder at redhat dot com>
- To: kazu at cs dot umass dot edu, dvenkat at noida dot hcltech dot com, binutils at sources dot redhat dot com
- Date: Tue, 03 Jun 2003 16:46:42 -0700
- Subject: [RFA] h8300 assembler
- Organization: Red Hat, Inc.
These are a couple of recent changes for h8300-elf-as:
2003-05-23 Michael Snyder <msnyder@redhat.com>
* config/tc-h8300.c (get_specific): Distinguish h8h from h8s ops.
(build_bytes): Ditto.
2003-05-23 Richard Sandiford <rsandifo@redhat.com>
* config/tc-h8300.c (DMODE): Remove.
(colonmod24): Don't choose a default if the operand is a 16-bit
constant integer.
(fix_operand_size): New function.
(md_assemble): Use it to choose between @(d:2, ERn) and @(d:16,ERn).
Adjust @(d:2,ERn) operands before choosing the specific opcodes.
Index: tc-h8300.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-h8300.c,v
retrieving revision 1.29
diff -p -r1.29 tc-h8300.c
*** tc-h8300.c 3 Jun 2003 21:29:08 -0000 1.29
--- tc-h8300.c 3 Jun 2003 22:54:29 -0000
*************** int Nmode;
*** 58,64 ****
int SXmode;
#define PSIZE (Hmode ? L_32 : L_16)
- #define DMODE (L_16)
#define DSYMMODE (Hmode ? L_24 : L_16)
int bsize = L_8; /* Default branch displacement. */
--- 58,63 ----
*************** struct h8_op
*** 320,325 ****
--- 319,325 ----
};
static void clever_message PARAMS ((const struct h8_instruction *, struct h8_op *));
+ static void fix_operand_size PARAMS ((struct h8_op *, int));
static void build_bytes PARAMS ((const struct h8_instruction *, struct h8_op *));
static void do_a_fix_imm PARAMS ((int, int, struct h8_op *, int));
static void check_operand PARAMS ((struct h8_op *, unsigned int, char *));
*************** colonmod24 (op, src)
*** 536,542 ****
if (!mode)
{
! /* Choose a default mode. */
if (op->exp.X_add_number < -32768
|| op->exp.X_add_number > 32767)
{
--- 536,543 ----
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)
{
*************** colonmod24 (op, src)
*** 548,555 ****
else if (op->exp.X_add_symbol
|| op->exp.X_op_symbol)
mode = DSYMMODE;
- else
- mode = DMODE;
}
op->mode |= mode;
--- 549,554 ----
*************** get_specific (instruction, operands, siz
*** 1316,1321 ****
--- 1315,1321 ----
if (found)
{
if ((this_try->opcode->available == AV_H8SX && ! SXmode)
+ || (this_try->opcode->available == AV_H8S && ! Smode)
|| (this_try->opcode->available == AV_H8H && ! Hmode))
found = 0, found_other = this_try;
else if (this_size != size && (this_size != SN && size != SN))
*************** build_bytes (this_try, operand)
*** 1524,1532 ****
char *p = asnibbles;
int high, low;
! if (!(this_try->opcode->available == AV_H8 || Hmode))
as_warn (_("Opcode `%s' with these operand types not available in H8/300 mode"),
this_try->opcode->name);
while (*nibble_ptr != (op_type) E)
{
--- 1524,1543 ----
char *p = asnibbles;
int high, low;
! if (!Hmode && this_try->opcode->available != AV_H8)
as_warn (_("Opcode `%s' with these operand types not available in H8/300 mode"),
this_try->opcode->name);
+ else if (!Smode
+ && this_try->opcode->available != AV_H8
+ && this_try->opcode->available != AV_H8H)
+ as_warn (_("Opcode `%s' with these operand types not available in H8/300H mode"),
+ this_try->opcode->name);
+ else if (!SXmode
+ && this_try->opcode->available != AV_H8
+ && this_try->opcode->available != AV_H8H
+ && this_try->opcode->available != AV_H8S)
+ as_warn (_("Opcode `%s' with these operand types not available in H8/300S mode"),
+ this_try->opcode->name);
while (*nibble_ptr != (op_type) E)
{
*************** clever_message (instruction, operand)
*** 1857,1862 ****
--- 1868,1923 ----
as_bad (_("invalid operands"));
}
+
+ /* Adjust OPERAND's value and size given that it is accessing a field
+ of 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
+ displacement in an @(d:2,ERn) operand. */
+
+ static void
+ fix_operand_size (operand, size)
+ struct h8_op *operand;
+ int size;
+ {
+ if ((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
+ && (operand->exp.X_add_number == size
+ || operand->exp.X_add_number == size * 2
+ || operand->exp.X_add_number == size * 3))
+ operand->mode |= L_2;
+
+ /* Scale down the displacement in an @(d:2,ERn) operand.
+ X_add_number then contains the desired field value. */
+ if ((operand->mode & SIZE) == L_2)
+ {
+ if (operand->exp.X_add_number % size != 0)
+ as_warn (_("operand/size mis-match"));
+ operand->exp.X_add_number /= size;
+ }
+ }
+
+ /* 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 DISP:
+ case INDEXB:
+ case INDEXW:
+ case INDEXL:
+ case ABS:
+ operand->mode |= L_16;
+ break;
+ }
+ }
+
+
/* This is the guts of the machine-dependent assembler. STR points to
a machine dependent instruction. This function is supposed to emit
the frags/bytes it assembles. */
*************** md_assemble (str)
*** 1948,2014 ****
break;
}
}
- instruction = get_specific (instruction, operand, size);
-
- if (instruction == 0)
- {
- /* Couldn't find an opcode which matched the operands. */
- char *where = frag_more (2);
-
- where[0] = 0x0;
- where[1] = 0x0;
- clever_message (prev_instruction, operand);
-
- return;
- }
-
- /* This is the earliest point at which we can do this:
- any DISP2 operands need to be fixed-up according to
- the size of the operation. */
- /* MOVA is a whole different set of rules... */
if (OP_KIND (instruction->opcode->how) == O_MOVAB ||
OP_KIND (instruction->opcode->how) == O_MOVAW ||
OP_KIND (instruction->opcode->how) == O_MOVAL)
{
! if ((operand[1].mode & MODE) == DISP &&
! (operand[1].mode & SIZE) == L_2)
! switch (operand[0].mode & MODE) {
case INDEXB:
default:
break;
case INDEXW:
! if (operand[1].exp.X_add_number % 2)
! as_warn (_("operand/size mis-match"));
! operand[1].exp.X_add_number /= 2;
break;
case INDEXL:
! if (operand[1].exp.X_add_number % 4)
! as_warn (_("operand/size mis-match"));
! operand[1].exp.X_add_number /= 4;
break;
}
}
else
{
! for (i = 0; i < instruction->noperands; i++)
! if ((operand[i].mode & MODE) == DISP &&
! (operand[i].mode & SIZE) == L_2)
! switch (size) {
case SN:
case SB:
default:
break;
case SW:
! if (operand[i].exp.X_add_number % 2)
! as_warn (_("operand/size mis-match"));
! operand[i].exp.X_add_number /= 2;
break;
case SL:
! if (operand[i].exp.X_add_number % 4)
! as_warn (_("operand/size mis-match"));
! operand[i].exp.X_add_number /= 4;
break;
}
}
build_bytes (instruction, operand);
--- 2009,2063 ----
break;
}
}
if (OP_KIND (instruction->opcode->how) == O_MOVAB ||
OP_KIND (instruction->opcode->how) == O_MOVAW ||
OP_KIND (instruction->opcode->how) == O_MOVAL)
{
! switch (operand[0].mode & MODE)
! {
case INDEXB:
default:
+ fix_operand_size (&operand[1], 1);
break;
case INDEXW:
! fix_operand_size (&operand[1], 2);
break;
case INDEXL:
! fix_operand_size (&operand[1], 4);
break;
}
}
else
{
! for (i = 0; i < 3 && operand[i].mode != 0; i++)
! switch (size)
! {
case SN:
case SB:
default:
+ fix_operand_size (&operand[i], 1);
break;
case SW:
! fix_operand_size (&operand[i], 2);
break;
case SL:
! fix_operand_size (&operand[i], 4);
break;
}
+ }
+
+ instruction = get_specific (instruction, operand, size);
+
+ if (instruction == 0)
+ {
+ /* Couldn't find an opcode which matched the operands. */
+ char *where = frag_more (2);
+
+ where[0] = 0x0;
+ where[1] = 0x0;
+ clever_message (prev_instruction, operand);
+
+ return;
}
build_bytes (instruction, operand);