aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-h8300.c
diff options
context:
space:
mode:
authorSteve Chamberlain <sac@cygnus>1992-01-21 22:14:16 +0000
committerSteve Chamberlain <sac@cygnus>1992-01-21 22:14:16 +0000
commit5d9f0ecf62f6d8503f847bbe73bbe009d53c9e0e (patch)
tree17d306b8fc63461b64b4cb327ead19b07090eaff /gas/config/tc-h8300.c
parent7316c642a391e8627120d48f0ee0706b2d31e570 (diff)
downloadgdb-5d9f0ecf62f6d8503f847bbe73bbe009d53c9e0e.zip
gdb-5d9f0ecf62f6d8503f847bbe73bbe009d53c9e0e.tar.gz
gdb-5d9f0ecf62f6d8503f847bbe73bbe009d53c9e0e.tar.bz2
* as.c: change -l to -a[lsn], to avoid conflict with 68000
command line option. * listing.h, listing.c: now prints addresses with ??? instead of 0 when errors in assemble prevent addresses being known. Prints symbol table more tidily. Allows different parts of the listing to be selected.
Diffstat (limited to 'gas/config/tc-h8300.c')
-rw-r--r--gas/config/tc-h8300.c1187
1 files changed, 803 insertions, 384 deletions
diff --git a/gas/config/tc-h8300.c b/gas/config/tc-h8300.c
index 9008cac..735024b 100644
--- a/gas/config/tc-h8300.c
+++ b/gas/config/tc-h8300.c
@@ -20,30 +20,31 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
Written By Steve Chamberlain
-
- steve@cygnus.com
+ sac@cygnus.com
*/
#include <stdio.h>
#include "as.h"
#include "bfd.h"
-#include "h8300-opcode.h"
+#include "opcode/h8300.h"
#include <ctype.h>
+#include "listing.h"
char comment_chars[] = { ';',0 };
char line_separator_chars[] = { '$' ,0};
/* This table describes all the machine specific pseudo-ops the assembler
has to support. The fields are:
- pseudo-op name without dot
- function to call to execute this pseudo-op
- Integer arg to pass to the function
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ Integer arg to pass to the function
*/
void cons();
+
const pseudo_typeS md_pseudo_table[] = {
{ "int", cons, 2 },
- { 0, 0, 0 }
+ { 0,0,0 }
};
int md_reloc_size ;
@@ -60,7 +61,6 @@ const relax_typeS md_relax_table[1];
static struct hash_control *opcode_hash_control; /* Opcode mnemonics */
-static struct hash_control *register_hash_control; /* Register name hash table */
/*
@@ -68,29 +68,106 @@ static struct hash_control *register_hash_control; /* Register name hash table *
set up all the tables, etc that the MD part of the assembler needs
*/
-reloc_howto_type *r16;
-reloc_howto_type *r8;
-reloc_howto_type *r8ff;
-reloc_howto_type *r8pcrel;
+/* encode the size and number into the number field
+ xxnnnn
+ 00 8 bit
+ 01 16 bit
+ 10 ccr
+ nnnnreg number
+*/
+#define WORD_REG 0x10
+#define BYTE_REG 0x00
+#define CCR_REG 0x20
+ struct reg_entry
+{
+ char *name;
+ char number;
+};
+
+struct reg_entry reg_list[] = {
+"r0",WORD_REG +0,
+"r1",WORD_REG +1,
+"r2",WORD_REG +2,
+"r3",WORD_REG +3,
+"r4",WORD_REG +4,
+"r5",WORD_REG +5,
+"r6",WORD_REG +6,
+"r7",WORD_REG +7,
+"fp",WORD_REG +6,
+"sp",WORD_REG +7,
+"r0h",BYTE_REG + 0,
+"r0l",BYTE_REG + 1,
+"r1h",BYTE_REG + 2,
+"r1l",BYTE_REG + 3,
+"r2h",BYTE_REG + 4,
+"r2l",BYTE_REG + 5,
+"r3h",BYTE_REG + 6,
+"r3l",BYTE_REG + 7,
+"r4h",BYTE_REG + 8,
+"r4l",BYTE_REG + 9,
+"r5h",BYTE_REG + 10,
+"r5l",BYTE_REG + 11,
+"r6h",BYTE_REG + 12,
+"r6l",BYTE_REG + 13,
+"r7h",BYTE_REG + 14,
+"r7l",BYTE_REG + 15,
+"ccr",CCR_REG,
+0,0
+}
+;
+
+
+
+
void md_begin ()
{
- bfd_arch_info_type *ai;
- const struct h8_opcode *opcode;
-
+ struct h8_opcode *opcode;
+ const struct reg_entry *reg;
+ char prev_buffer[100];
+ int idx = 0;
+
opcode_hash_control = hash_new();
- for (opcode = h8_opcodes; opcode->name; opcode++) {
- hash_insert(opcode_hash_control, opcode->name, (char *)opcode);
- }
-
- ai = bfd_lookup_arch(bfd_arch_h8300,0);
+ prev_buffer[0] = 0;
- r16 = ai->reloc_type_lookup(ai, BFD_RELOC_16);
- r8 = ai->reloc_type_lookup(ai, BFD_RELOC_8);
- r8ff = ai->reloc_type_lookup(ai, BFD_RELOC_8_FFnn);
- r8pcrel = ai->reloc_type_lookup(ai, BFD_RELOC_8_PCREL);
+ for (opcode = h8_opcodes; opcode->name; opcode++)
+ {
+ /* Strip off any . part when inserting the opcode and only enter
+ unique codes into the hash table
+ */
+ char *src= opcode->name;
+ unsigned int len = strlen(src);
+ char *dst = malloc(len+1);
+ char *buffer = dst;
+ opcode->size = 0;
+ while (*src) {
+ if (*src == '.') {
+ *dst++ = 0;
+ src++;
+ opcode->size = *src;
+ break;
+ }
+ *dst++ = *src++;
+ }
+ if (strcmp(buffer, prev_buffer))
+ {
+ hash_insert(opcode_hash_control, buffer, (char *)opcode);
+ strcpy(prev_buffer, buffer);
+ idx++;
+ }
+ opcode->idx = idx;
+
+
+ /* Find the number of operands */
+ opcode->noperands = 0;
+ while (opcode->args.nib[opcode->noperands] != E)
+ opcode->noperands ++;
+ /* Find the length of the opcode in bytes */
+ opcode->length =0;
+ while (opcode->data.nib[opcode->length*2] != E)
+ opcode->length++;
+ }
-
}
@@ -101,9 +178,10 @@ struct h8_exp {
};
struct h8_op
{
-op_type mode;
- unsigned reg;
- expressionS exp;
+ unsigned int dispreg;
+ op_type mode;
+ unsigned reg;
+ expressionS exp;
};
@@ -124,46 +202,55 @@ op_type r16_sord[] = {RS16, RD16};
op_type rind_sord[] = {RSIND, RDIND};
op_type abs_sord[2] = {ABS16SRC, ABS16DST};
op_type disp_sord[] = {DISPSRC, DISPDST};
+
/* try and parse a reg name, returns number of chars consumed */
-int DEFUN(parse_reg,(src, mode, reg, dst),
- char *src AND
- op_type *mode AND
- unsigned int *reg AND
- int dst)
+int
+DEFUN(parse_reg,(src, mode, reg, dst),
+ char *src AND
+ op_type *mode AND
+ unsigned int *reg AND
+ int dst)
{
- if (src[0] == 's' && src[1] == 'p') {
- *mode = r16_sord[dst];
- *reg = 7;
- return 2;
- }
- if (src[0] == 'c' && src[1] == 'c' && src[2] == 'r') {
- *mode = CCR;
- *reg = 0;
- return 3;
- }
- if (src[0] == 'f' && src[1] == 'p') {
- *mode = r16_sord[dst];
- *reg = 6;
- return 2;
- }
- if (src[0] == 'r') {
- if (src[1] >= '0' && src[1] <= '7') {
- if(src[2] == 'l') {
- *mode = r8_sord[dst];
- *reg = (src[1] - '0') + 8;
- return 3;
- }
- if(src[2] == 'h') {
- *mode = r8_sord[dst];
- *reg = (src[1] - '0') ;
+ if (src[0] == 's' && src[1] == 'p')
+ {
+ *mode = r16_sord[dst];
+ *reg = 7;
+ return 2;
+ }
+ if (src[0] == 'c' && src[1] == 'c' && src[2] == 'r')
+ {
+ *mode = CCR;
+ *reg = 0;
return 3;
- }
- *mode = r16_sord[dst];
- *reg = (src[1] - '0');
- return 2;
}
- }
- return 0;
+ if (src[0] == 'f' && src[1] == 'p')
+ {
+ *mode = r16_sord[dst];
+ *reg = 6;
+ return 2;
+ }
+ if (src[0] == 'r')
+ {
+ if (src[1] >= '0' && src[1] <= '7')
+ {
+ if(src[2] == 'l')
+ {
+ *mode = r8_sord[dst];
+ *reg = (src[1] - '0') + 8;
+ return 3;
+ }
+ if(src[2] == 'h')
+ {
+ *mode = r8_sord[dst];
+ *reg = (src[1] - '0') ;
+ return 3;
+ }
+ *mode = r16_sord[dst];
+ *reg = (src[1] - '0');
+ return 2;
+ }
+ }
+ return 0;
}
char *
@@ -179,23 +266,52 @@ DEFUN(parse_exp,(s, op),
new = input_line_pointer;
input_line_pointer = save;
if (SEG_NORMAL(seg))
- return new;
+ return new;
switch (seg) {
- case SEG_ABSOLUTE:
- case SEG_UNKNOWN:
- case SEG_DIFFERENCE:
- case SEG_BIG:
- case SEG_REGISTER:
- return new;
- case SEG_ABSENT:
- as_bad("Missing operand");
- return new;
- default:
- as_bad("Don't understand operand of type %s", segment_name (seg));
- return new;
- }
+ case SEG_ABSOLUTE:
+ case SEG_UNKNOWN:
+ case SEG_DIFFERENCE:
+ case SEG_BIG:
+ case SEG_REGISTER:
+ return new;
+ case SEG_ABSENT:
+ as_bad("Missing operand");
+ return new;
+ default:
+ as_bad("Don't understand operand of type %s", segment_name (seg));
+ return new;
+ }
+}
+
+static char *
+DEFUN(skip_colonthing,(ptr),
+ char *ptr)
+{
+ if (*ptr == ':') {
+ ptr++;
+ while (isdigit(*ptr))
+ ptr++;
+
+ }
+ return ptr;
}
+/* The many forms of operand:
+
+ Rn Register direct
+ @Rn Register indirect
+ @(exp[:16], Rn) Register indirect with displacement
+ @Rn+
+ @-Rn
+ @aa:8 absolute 8 bit
+ @aa:16 absolute 16 bit
+ @aa absolute 16 bit
+
+ #xx[:size] immediate data
+ @(exp:[8], pc) pc rel
+ @@aa[:8] memory indirect
+
+*/
static void
DEFUN(get_operand,(ptr, op, dst),
@@ -207,21 +323,38 @@ DEFUN(get_operand,(ptr, op, dst),
op_type mode;
unsigned int num;
unsigned int len;
+ unsigned int size;
op->mode = E;
- while (*src == ' ') src++;
len = parse_reg(src, &op->mode, &op->reg, dst);
if (len) {
- *ptr = src + len;
- return ;
- }
+ *ptr = src + len;
+ return ;
+ }
- if (*src == '@') {
+ if (*src == '@')
+ {
src++;
- if (*src == '-') {
+ if (*src == '@')
+ {
+ src++;
+ src = parse_exp(src,&op->exp);
+ src = skip_colonthing(src);
+
+ *ptr = src;
+
+ op->mode = MEMIND;
+ return;
+
+ }
+
+
+ if (*src == '-')
+ {
src++;
len = parse_reg(src, &mode, &num, dst);
- if (len == 0 || mode != r16_sord[dst]) {
+ if (len == 0 || mode != r16_sord[dst])
+ {
as_bad("@- needs word register");
}
op->mode = RDDEC;
@@ -229,29 +362,37 @@ DEFUN(get_operand,(ptr, op, dst),
*ptr = src + len;
return;
}
- if (*src == '(' && ')') {
+ if (*src == '(' && ')')
+ {
/* Disp */
src++;
src = parse_exp(src, &op->exp);
- if (*src == ')') {
+ if (*src == ')')
+ {
src++;
op->mode = abs_sord[dst];
*ptr = src;
return;
}
- if (*src != ',') {
+ src = skip_colonthing(src);
+
+ if (*src != ',')
+ {
as_bad("expected @(exp, reg16)");
}
src++;
len = parse_reg(src, &mode, &op->reg, dst);
if (len == 0 || mode != r16_sord[dst])
- {
- as_bad("expected @(exp, reg16)");
- }
+ {
+ as_bad("expected @(exp, reg16)");
+ }
op->mode = disp_sord[dst];
src += len;
- if (*src != ')' && '(') {
+ src = skip_colonthing(src);
+
+ if (*src != ')' && '(')
+ {
as_bad("expected @(exp, reg16)");
}
@@ -262,46 +403,492 @@ DEFUN(get_operand,(ptr, op, dst),
len = parse_reg(src, &mode, &num, dst);
if(len) {
- src += len;
- if (*src == '+') {
- src++;
- if (mode != RS16) {
- as_bad("@Rn+ needs word register");
+ src += len;
+ if (*src == '+')
+ {
+ src++;
+ if (mode != RS16)
+ {
+ as_bad("@Rn+ needs src word register");
+ }
+ op->mode = RSINC;
+ op->reg = num;
+ *ptr = src;
+ return;
+ }
+ if (mode != r16_sord[dst])
+ {
+ as_bad("@Rn needs word register");
}
- op->mode = RSINC;
+ op->mode =rind_sord[dst];
op->reg = num;
*ptr = src;
return;
}
- if (mode != r16_sord[dst]) {
- as_bad("@Rn needs word register");
- }
- op->mode =rind_sord[dst];
- op->reg = num;
- *ptr = src;
- return;
- }
- else {
+ else
+ {
/* must be a symbol */
op->mode = abs_sord[dst];
- *ptr = parse_exp(src, &op->exp);
+ *ptr = skip_colonthing(parse_exp(src, &op->exp));
+
return;
}
}
if (*src == '#') {
- src++;
- op->mode = IMM16;
- *ptr = parse_exp(src, &op->exp);
- return;
- }
+ src++;
+ op->mode = IMM16;
+ src = parse_exp(src, &op->exp);
+ *ptr= skip_colonthing(src);
+
+ return;
+ }
else {
- *ptr = parse_exp(src, &op->exp);
- op->mode = DISP8;
+ *ptr = parse_exp(src, &op->exp);
+ op->mode = DISP8;
+ }
+}
+
+
+static
+char *
+DEFUN(get_operands,(noperands,op_end, operand),
+ unsigned int noperands AND
+ char *op_end AND
+ struct h8_op *operand)
+{
+ char *ptr = op_end;
+ switch (noperands)
+ {
+ case 0:
+ operand[0].mode = 0;
+ operand[1].mode = 0;
+ break;
+
+ case 1:
+ ptr++;
+ get_operand(& ptr, operand +0,0);
+ operand[1].mode =0;
+ break;
+
+ case 2:
+ ptr++;
+ get_operand(& ptr, operand +0,0);
+ if (*ptr == ',') ptr++;
+ get_operand(& ptr, operand +1, 1);
+ break;
+
+ default:
+ abort();
}
+
+
+ return ptr;
}
+/* Passed a pointer to a list of opcodes which use different
+ addressing modes, return the opcode which matches the opcodes
+ provided
+ */
+static
+struct h8_opcode *
+DEFUN(get_specific,(opcode, operands),
+ struct h8_opcode *opcode AND
+ struct h8_op *operands)
+
+{
+ struct h8_opcode *this_try = opcode ;
+ int found = 0;
+ unsigned int noperands = opcode->noperands;
+
+ unsigned int dispreg;
+ unsigned int this_index = opcode->idx;
+ while (this_index == opcode->idx && !found)
+ {
+ unsigned int i;
+
+ this_try = opcode ++;
+ for (i = 0; i < noperands; i++)
+ {
+ op_type op = (this_try->args.nib[i]) & ~(B30|B31);
+ switch (op)
+ {
+ case Hex0:
+ case Hex1:
+ case Hex2:
+ case Hex3:
+ case Hex4:
+ case Hex5:
+ case Hex6:
+ case Hex7:
+ case Hex8:
+ case Hex9:
+ case HexA:
+ case HexB:
+ case HexC:
+ case HexD:
+ case HexE:
+ case HexF:
+ break;
+ case DISPSRC:
+ case DISPDST:
+ operands[0].dispreg = operands[i].reg;
+ case RD8:
+ case RS8:
+ case RDIND:
+ case RSIND:
+ case RD16:
+ case RS16:
+ case CCR:
+ case RSINC:
+ case RDDEC:
+ if (operands[i].mode != op) goto fail;
+ break;
+ case KBIT:
+ case IMM16:
+ case IMM3:
+ case IMM8:
+ if (operands[i].mode != IMM16) goto fail;
+ break;
+ case MEMIND:
+ if (operands[i].mode != MEMIND) goto fail;
+ break;
+ case ABS16SRC:
+ case ABS8SRC:
+ case ABS16OR8SRC:
+ case ABS16ORREL8SRC:
+
+ if (operands[i].mode != ABS16SRC) goto fail;
+ break;
+ case ABS16OR8DST:
+ case ABS16DST:
+ case ABS8DST:
+ if (operands[i].mode != ABS16DST) goto fail;
+ break;
+ }
+ }
+ found =1;
+ fail: ;
+ }
+ if (found)
+ return this_try;
+ else
+ return 0;
+}
+
+static void
+DEFUN(check_operand,(operand, width, string),
+ struct h8_op *operand AND
+ unsigned int width AND
+ char *string)
+{
+ if (operand->exp.X_add_symbol == 0
+ && operand->exp.X_subtract_symbol == 0)
+ {
+
+ /* No symbol involved, let's look at offset, it's dangerous if any of
+ the high bits are not 0 or ff's, find out by oring or anding with
+ the width and seeing if the answer is 0 or all fs*/
+ 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);
+ }
+ }
+
+}
+
+/* Now we know what sort of opcodes it is, lets build the bytes -
+ */
+static void
+DEFUN (build_bytes,(this_try, operand),
+ struct h8_opcode *this_try AND
+ struct h8_op *operand)
+
+{
+ unsigned int i;
+
+ char *output = frag_more(this_try->length);
+ char *output_ptr = output;
+ op_type *nibble_ptr = this_try->data.nib;
+ char part;
+ op_type c;
+ char high;
+ int nib;
+ top: ;
+ while (*nibble_ptr != E)
+ {
+ int nibble;
+ for (nibble = 0; nibble <2; nibble++)
+ {
+ c = *nibble_ptr & ~(B30|B31);
+ switch (c)
+ {
+ default:
+ abort();
+ case KBIT:
+ switch (operand[0].exp.X_add_number)
+ {
+ case 1:
+ nib = 0;
+ break;
+ case 2:
+ nib = 8;
+ break;
+ default:
+ as_bad("Need #1 or #2 here");
+ break;
+ }
+ /* stop it making a fix */
+ operand[0].mode = 0;
+ break;
+ case 0:
+ case 1:
+ case 2: case 3: case 4: case 5: case 6:
+ case 7: case 8: case 9: case 10: case 11:
+ case 12: case 13: case 14: case 15:
+ nib = c;
+ break;
+ case DISPREG:
+ nib = operand[0].dispreg;
+ break;
+ case IMM8:
+ operand[0].mode = IMM8;
+ nib = 0;
+ break;
+
+ case DISPDST:
+ nib = 0;
+ break;
+ case IMM3:
+ if (operand[0].exp.X_add_symbol == 0) {
+ operand[0].mode = 0; /* stop it making a fix */
+ nib = (operand[0].exp.X_add_number);
+ }
+ else as_bad("can't have symbol for bit number");
+ if (nib < 0 || nib > 7)
+ {
+ as_bad("Bit number out of range %d", nib);
+ }
+
+ break;
+
+ case ABS16DST:
+ nib = 0;
+ break;
+ case ABS8DST:
+ operand[1].mode = ABS8DST;
+ nib = 0;
+ break;
+ case ABS8SRC:
+ operand[0].mode = ABS8SRC;
+ nib = 0;
+ break;
+ case ABS16OR8DST:
+ operand[1].mode = c;
+
+ nib = 0;
+
+ break;
+
+ case ABS16ORREL8SRC:
+ operand[0].mode = c;
+ nib=0;
+ break;
+
+ case ABS16OR8SRC:
+ operand[0].mode = ABS16OR8SRC;
+ nib = 0;
+ break;
+ case DISPSRC:
+ operand[0].mode = ABS16SRC;
+ nib = 0;
+ break;
+
+ case DISP8:
+ operand[0].mode = DISP8;
+ nib = 0;
+ break;
+
+ case ABS16SRC:
+ case IMM16:
+ case IGNORE:
+ case MEMIND:
+
+ nib=0;
+ break;
+ case RS8:
+ case RS16:
+ case RSIND:
+ case RSINC:
+ nib = operand[0].reg;
+ break;
+
+ case RD8:
+ case RD16:
+ case RDDEC:
+ case RDIND:
+ nib = operand[1].reg;
+ break;
+
+ case E:
+ abort();
+ break;
+ }
+ if (*nibble_ptr & B31) {
+ nib |=0x8;
+ }
+
+ if (nibble == 0) {
+ *output_ptr = nib << 4;
+ }
+ else {
+ *output_ptr |= nib;
+ output_ptr++;
+ }
+ nibble_ptr++;
+ }
+
+ }
+
+ /* output any fixes */
+ for (i = 0; i < 2; i++)
+ {
+ switch (operand[i].mode) {
+ case 0:
+ break;
+
+ case DISP8:
+ check_operand(operand+i, 0x7f,"@");
+
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 1,
+ 1,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number -1,
+ 1,
+ R_PCRBYTE);
+ break;
+ case IMM8:
+ check_operand(operand+i, 0xff,"#");
+ /* If there is nothing else going on we can safely
+ reloc in place */
+ if (operand[i].exp.X_add_symbol == 0)
+ {
+ output[1] = operand[i].exp.X_add_number;
+ }
+ else
+ {
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 1,
+ 1,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number,
+ 0,
+ R_RELBYTE);
+ }
+
+ break;
+ case MEMIND:
+ check_operand(operand+i, 0xff,"@@");
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 1,
+ 1,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number,
+ 0,
+ R_RELBYTE);
+ break;
+ case ABS8DST:
+ case ABS8SRC:
+ check_operand(operand+i, 0xff,"@");
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 1,
+ 1,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number,
+ 0,
+ R_RELBYTE);
+ break;
+
+ case ABS16OR8SRC:
+ case ABS16OR8DST:
+ check_operand(operand+i, 0xffff,"@");
+
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 2,
+ 2,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number,
+ 0,
+ R_MOVB1);
+ break;
+
+ case ABS16ORREL8SRC:
+ check_operand(operand+i, 0xffff,"@");
+
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 2,
+ 2,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number,
+ 0,
+ R_JMP1);
+ break;
+
+
+ case ABS16SRC:
+ case ABS16DST:
+ case IMM16:
+ case DISPSRC:
+ case DISPDST:
+ check_operand(operand+i, 0xffff,"@");
+ if (operand[i].exp.X_add_symbol == 0)
+ {
+ /* This should be done with bfd */
+ output[3] = operand[i].exp.X_add_number & 0xff;
+ output[2] = operand[i].exp.X_add_number >> 8;
+
+ }
+ else
+ {
+
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 2,
+ 2,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number,
+ 0,
+ R_RELWORD);
+ }
+
+ break;
+ case RS8:
+ case RD8:
+ case RS16:
+ case RD16:
+ case RDDEC:
+ case KBIT:
+ case RSINC:
+ case RDIND:
+ case RSIND:
+ case CCR:
+
+ break;
+ default:
+ abort();
+ }
+ }
+
+}
/* This is the guts of the machine-dependent assembler. STR points to a
machine dependent instruction. This funciton is supposed to emit
the frags/bytes it assembles to.
@@ -315,291 +902,74 @@ DEFUN(md_assemble,(str),
char *op_start;
char *op_end;
unsigned int i;
-
+ struct h8_op operand[2];
struct h8_opcode * opcode;
+ char *dot = 0;
+ char c;
/* Drop leading whitespace */
while (*str == ' ')
str++;
-
/* find the op code end */
for (op_start = op_end = str;
*op_end != 0 && *op_end != ' ';
- op_end ++)
- ;
+ op_end ++)
+ {
+ if (*op_end == '.') {
+ dot = op_end+1;
+ *op_end = 0;
+ op_end+=2;
+ break;
+ }
+ }
+
+ ;
- if (op_end == op_start) {
- as_bad("can't find opcode ");
- }
+ if (op_end == op_start)
+ {
+ as_bad("can't find opcode ");
+ }
+ c = *op_end;
+
*op_end = 0;
+
opcode = (struct h8_opcode *) hash_find(opcode_hash_control,
op_start);
- if (opcode == NULL) {
- as_bad("unknown opcode");
- return;
- }
-
-
-{
- int ok = 1;
- int j,i;
- int dispreg = 0;
- struct h8_op operand[2];
- char *ptr = op_end+1;
- if (opcode->noperands)
- get_operand(& ptr, &operand[0],0);
- else operand[0].mode = 0;
- if (opcode->noperands==2) {
- if (*ptr == ',') ptr++;
- get_operand(& ptr, &operand[1], 1);
- }
- else operand[1].mode = 0;
-
-
+ if (opcode == NULL)
+ {
+ as_bad("unknown opcode");
+ return;
+ }
-{
- struct h8_opcode *this_try ;
- int found = 0;
- for (j = 0; j < opcode->nopcodes && !found; j++) {
- this_try = opcode + j;
- for (i = 0; i < opcode->noperands; i++) {
- op_type op = (this_try->args.nib[i]) & ~(B30|B31);
- switch (op) {
- case Hex0:
- case Hex1:
- case Hex2:
- case Hex3:
- case Hex4:
- case Hex5:
- case Hex6:
- case Hex7:
- case Hex8:
- case Hex9:
- case HexA:
- case HexB:
- case HexC:
- case HexD:
- case HexE:
- case HexF:
- break;
- case DISPSRC:
- case DISPDST:
- dispreg = operand[i].reg;
- case RD8:
- case RS8:
- case RDIND:
- case RSIND:
- case RD16:
- case RS16:
- case CCR:
- case RSINC:
- case RDDEC:
- if (operand[i].mode != op) goto fail;
- break;
- case IMM8:
- /* We have an expression, called IMM16, but we know we
- want an 8 bit value here */
- if (operand[i].mode != IMM16) goto fail;
- operand[i].mode = IMM8;
- break;
- case KBIT:
- case IMM16:
- case IMM3:
- if (operand[i].mode != IMM16) goto fail;
- break;
- case ABS16SRC:
- case ABS8SRC:
- if (operand[i].mode != ABS16SRC) goto fail;
- break;
- case ABS16DST:
- case ABS8DST:
- if (operand[i].mode != ABS16DST) goto fail;
-
- break;
- }
- }
- found =1;
- fail: ;
+
+ input_line_pointer = get_operands(opcode->noperands, op_end,
+ operand);
+ *op_end = c;
+ opcode = get_specific(opcode, operand);
+
+ if (opcode == 0)
+ {
+ /* Allocate 2 bytes for the insn anyway */
+ char *where =frag_more(2);
+ where[0] = 0xde;
+ where[1] = 0xad;
+
+
+ as_bad("illegal operands for opcode");
+ return;
+ }
+ if (opcode->size && dot)
+ {
+ if (opcode->size != *dot)
+ {
+ as_warn("mismatch between opcode size and operand size");
}
- if (found == 0)
- as_bad("illegal operands for opcode");
-
-
- /* Now we know what sort of opcodes etc, lets build the bytes -
- actually we know how big the instruction will be too. So we
- can get
- */
-{
- char *output = frag_more(this_try->length);
- char *output_ptr = output;
- op_type *nibble_ptr = this_try->data.nib;
- char part;
- op_type c;
- char high;
- int nib;
- top: ;
- while (*nibble_ptr != E) {
- int nibble;
- for (nibble = 0; nibble <2; nibble++) {
- c = *nibble_ptr & ~(B30|B31);
- switch (c) {
- default:
- abort();
- case KBIT:
- switch (operand[0].exp.X_add_number) {
- case 1:
- nib = 0;
- break;
- case 2:
- nib = 8;
- break;
- default:
- as_bad("Need #1 or #2 here");
- break;
- }
- /* stop it making a fix */
- operand[0].mode = 0;
- break;
- case 0:
- case 1:
- case 2: case 3: case 4: case 5: case 6:
- case 7: case 8: case 9: case 10: case 11:
- case 12: case 13: case 14: case 15:
- nib = c;
- break;
- case DISPREG:
- nib = dispreg;
- break;
- case IMM8:
- nib = 0;
- break;
-
- case DISPDST:
- nib = 0;
- break;
- case IMM3:
- if (operand[0].exp.X_add_symbol == 0) {
- operand[0].mode = 0; /* stop it making a fix */
- nib = (operand[0].exp.X_add_number);
- }
- else as_bad("can't have symbol for bit number");
- break;
-
- case ABS16DST:
- nib = 0;
- break;
- case DISPSRC:
- case ABS16SRC:
- case IMM16:
- nib=0;
- break;
-
-
- case ABS8DST:
- case ABS8SRC:
- case IGNORE:
-
-
- nib = 0;
- break;
- case DISP8:
- nib = 0;
- break;
-
-
- case RS8:
- case RS16:
- case RSIND:
- case RSINC:
-
- nib= operand[0].reg;
- break;
- case RD8:
- case RD16:
- case RDDEC:
- case RDIND:
- nib = operand[1].reg;
-
- break;
- case E:
- abort();
- break;
- }
- if (*nibble_ptr & B31) nib|=0x8;
- if (nibble == 0) {
- *output_ptr = nib << 4;
- }
- else {
- *output_ptr |= nib;
- output_ptr++;
- }
- nibble_ptr++;
- }
-
- }
-
- /* output any fixes */
- for (i = 0; i < 2; i++)
- {
- switch (operand[i].mode) {
- case 0:
- break;
- case DISP8:
- fix_new(frag_now,
- output - frag_now->fr_literal + 1,
- 1,
- operand[i].exp.X_add_symbol,
- operand[i].exp.X_subtract_symbol,
- operand[i].exp.X_add_number -1,
- 1,
- (int)r8pcrel);
- break;
- case IMM8:
- fix_new(frag_now,
- output - frag_now->fr_literal + 1,
- 1,
- operand[i].exp.X_add_symbol,
- operand[i].exp.X_subtract_symbol,
- operand[i].exp.X_add_number,
- 0,
- 0);
- break;
-
- case ABS16SRC:
- case ABS16DST:
- case IMM16:
- case DISPSRC:
- case DISPDST:
- fix_new(frag_now,
- output - frag_now->fr_literal + 2,
- 2,
- operand[i].exp.X_add_symbol,
- operand[i].exp.X_subtract_symbol,
- operand[i].exp.X_add_number,
- 0,
- (int)r16);
- break;
- case RS8:
- case RD8:
- case RS16:
- case RD16:
- case RDDEC:
- case KBIT:
- case RSINC:
- case RDIND:
- case RSIND:
- break;
- default:
- abort();
- }
- }
+ }
+ build_bytes(opcode, operand);
}
-}
-}
-}
void
DEFUN(tc_crawl_symbol_chain, (headers),
@@ -692,7 +1062,9 @@ md_parse_option(argP, cntP, vecP)
int *cntP;
char ***vecP;
- {abort();
+ {
+ return 0;
+
}
int md_short_jump_size;
@@ -770,7 +1142,8 @@ int
md_estimate_size_before_relax(fragP, segment_type)
register fragS *fragP;
register segT segment_type;
-{ printf("call tomd_estimate_size_before_relax \n"); abort(); }
+{
+printf("call tomd_estimate_size_before_relax \n"); abort(); }
/* Put number into target byte order */
void DEFUN(md_number_to_chars,(ptr, use, nbytes),
@@ -792,3 +1165,49 @@ long md_pcrel_from(fixP)
fixS *fixP; { abort(); }
void tc_coff_symbol_emit_hook() { }
+
+
+void tc_reloc_mangle(fix_ptr, intr, base)
+fixS *fix_ptr;
+struct internal_reloc *intr;
+bfd_vma base;
+
+{
+ symbolS *symbol_ptr;
+
+ 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 == RELOC_32) {
+ /* cons likes to create reloc32's whatever the size of the reloc..
+ */
+ switch (fix_ptr->fx_size)
+ {
+
+ case 2:
+ intr->r_type = R_RELWORD;
+ break;
+ case 1:
+ intr->r_type = R_RELBYTE;
+ break;
+ default:
+ abort();
+
+ }
+
+ }
+ else {
+ intr->r_type = fix_ptr->fx_r_type;
+ }
+
+ intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where +base;
+ intr->r_offset = fix_ptr->fx_offset;
+
+ if (symbol_ptr)
+ intr->r_symndx = symbol_ptr->sy_number;
+ else
+ intr->r_symndx = -1;
+
+
+}