diff options
Diffstat (limited to 'gas/config/tc-h8300.c')
-rw-r--r-- | gas/config/tc-h8300.c | 1595 |
1 files changed, 0 insertions, 1595 deletions
diff --git a/gas/config/tc-h8300.c b/gas/config/tc-h8300.c deleted file mode 100644 index 115ada15423..00000000000 --- a/gas/config/tc-h8300.c +++ /dev/null @@ -1,1595 +0,0 @@ -/* tc-h8300.c -- Assemble code for the Hitachi H8/300 - Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation. - - This file is part of GAS, the GNU Assembler. - - GAS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - GAS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - 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, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - - -/* - Written By Steve Chamberlain - sac@cygnus.com - */ - -#include <stdio.h> -#include "as.h" -#include "subsegs.h" -#include "bfd.h" -#define DEFINE_TABLE -#define h8_opcodes ops -#include "opcode/h8300.h" -#include <ctype.h> - -const char comment_chars[] = -{';', 0}; -const char line_separator_chars[] = -{0}; -const char line_comment_chars[] = "#"; - -/* 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 - */ - -void cons (); - -int Hmode; -int Smode; -#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 */ - - -void -h8300hmode () -{ - Hmode = 1; - Smode = 0; -} - -void -h8300smode () -{ - Smode = 1; - Hmode = 1; -} -void -sbranch (size) - int size; -{ - bsize = size; -} - -static void pint () -{ - cons (Hmode ? 4 : 2); -} - -const pseudo_typeS md_pseudo_table[] = -{ - - {"h8300h", h8300hmode, 0}, - {"h8300s", h8300smode, 0}, - {"sbranch", sbranch, L_8}, - {"lbranch", sbranch, L_16}, - - {"int", pint, 0}, - {"data.b", cons, 1}, - {"data.w", cons, 2}, - {"data.l", cons, 4}, - {"form", listing_psize, 0}, - {"heading", listing_title, 0}, - {"import", s_ignore, 0}, - {"page", listing_eject, 0}, - {"program", s_ignore, 0}, - {0, 0, 0} -}; - -const int md_reloc_size; - -const char EXP_CHARS[] = "eE"; - -/* Chars that mean this number is a floating point constant */ -/* As in 0f12.456 */ -/* or 0d1.2345e12 */ -const char FLT_CHARS[] = "rRsSfFdDxXpP"; - -static struct hash_control *opcode_hash_control; /* Opcode mnemonics */ - -/* - 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 -md_begin () -{ - struct h8_opcode *opcode; - char prev_buffer[100]; - int idx = 0; - - opcode_hash_control = hash_new (); - prev_buffer[0] = 0; - - 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 == '.') - { - src++; - opcode->size = *src; - break; - } - *dst++ = *src++; - } - *dst++ = 0; - 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++; - } - - linkrelax = 1; -} - - -struct h8_exp -{ - char *e_beg; - char *e_end; - expressionS e_exp; -}; -int dispreg; -int opsize; /* Set when a register size is seen */ - - -struct h8_op -{ - op_type mode; - unsigned reg; - expressionS exp; -}; - -/* - parse operands - WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp - r0l,r0h,..r7l,r7h - @WREG - @WREG+ - @-WREG - #const - ccr -*/ - -/* try and parse a reg name, returns number of chars consumed */ -int -parse_reg (src, mode, reg, direction) - char *src; - op_type *mode; - unsigned int *reg; - int direction; - -{ - char *end; - int len; - - /* Cribbed from get_symbol_end(). */ - if (!is_name_beginner (*src) || *src == '\001') - return 0; - end = src+1; - while (is_part_of_name (*end) || *end == '\001') - end++; - len = end - src; - - if (len == 2 && src[0] == 's' && src[1] == 'p') - { - *mode = PSIZE | REG | direction; - *reg = 7; - return len; - } - if (len == 3 && src[0] == 'c' && src[1] == 'c' && src[2] == 'r') - { - *mode = CCR; - *reg = 0; - return len; - } - if (len == 3 && src[0] == 'e' && src[1] == 'x' && src[2] == 'r') - { - *mode = EXR; - *reg = 0; - return len; - } - if (len == 2 && src[0] == 'f' && src[1] == 'p') - { - *mode = PSIZE | REG | direction; - *reg = 6; - return len; - } - if (len == 3 && src[0] == 'e' && src[1] == 'r' - && src[2] >= '0' && src[2] <= '7') - { - *mode = L_32 | REG | direction; - *reg = src[2] - '0'; - if (!Hmode) - as_warn (_("Reg not valid for H8/300")); - return len; - } - if (len == 2 && src[0] == 'e' && src[1] >= '0' && src[1] <= '7') - { - *mode = L_16 | REG | direction; - *reg = src[1] - '0' + 8; - if (!Hmode) - as_warn (_("Reg not valid for H8/300")); - return len; - } - - if (src[0] == 'r') - { - if (src[1] >= '0' && src[1] <= '7') - { - if (len == 3 && src[2] == 'l') - { - *mode = L_8 | REG | direction; - *reg = (src[1] - '0') + 8; - return len; - } - if (len == 3 && src[2] == 'h') - { - *mode = L_8 | REG | direction; - *reg = (src[1] - '0'); - return len; - } - if (len == 2) - { - *mode = L_16 | REG | direction; - *reg = (src[1] - '0'); - return len; - } - } - } - - return 0; -} - -char * -parse_exp (s, op) - char *s; - expressionS * op; -{ - char *save = input_line_pointer; - char *new; - - input_line_pointer = s; - expression (op); - if (op->X_op == O_absent) - as_bad (_("missing operand")); - new = input_line_pointer; - input_line_pointer = save; - return new; -} - -static char * -skip_colonthing (ptr, exp, mode) - char *ptr; - expressionS *exp; - int *mode; -{ - if (*ptr == ':') - { - ptr++; - *mode &= ~SIZE; - if (*ptr == '8') - { - ptr++; - /* ff fill any 8 bit quantity */ - /* exp->X_add_number -= 0x100;*/ - *mode |= L_8; - } - else - { - if (*ptr == '2') - { - *mode |= L_24; - } - else if (*ptr == '3') - { - *mode |= L_32; - } - else if (*ptr == '1') - { - *mode |= L_16; - } - 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 - - */ - -char * -colonmod24 (op, src) - struct h8_op *op; - char *src; - -{ - int mode = 0; - src = skip_colonthing (src, &op->exp, &mode); - - if (!mode) - { - /* Choose a default mode */ - 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; - else - mode = DMODE; - } - op->mode |= mode; - return src; - -} - - -static void -get_operand (ptr, op, dst, direction) - char **ptr; - struct h8_op *op; - unsigned int dst; - int direction; -{ - char *src = *ptr; - op_type mode; - unsigned int num; - unsigned int len; - - op->mode = E; - - /* Gross. Gross. ldm and stm have a format not easily handled - by get_operand. We deal with it explicitly here. */ - if (src[0] == 'e' && src[1] == 'r' && isdigit(src[2]) - && src[3] == '-' && src[4] == 'e' && src[5] == 'r' && isdigit(src[6])) - { - int low, high; - - low = src[2] - '0'; - high = src[6] - '0'; - - if (high < low) - as_bad (_("Invalid register list for ldm/stm\n")); - - if (low % 2) - as_bad (_("Invalid register list for ldm/stm\n")); - - if (high - low > 3) - as_bad (_("Invalid register list for ldm/stm\n")); - - if (high - low != 1 - && low % 4) - as_bad (_("Invalid register list for ldm/stm\n")); - - /* Even sicker. We encode two registers into op->reg. One - for the low register to save, the other for the high - register to save; we also set the high bit in op->reg - so we know this is "very special". */ - op->reg = 0x80000000 | (high << 8) | low; - op->mode = REG; - *ptr = src + 7; - return; - } - - len = parse_reg (src, &op->mode, &op->reg, direction); - if (len) - { - *ptr = src + len; - return; - } - - if (*src == '@') - { - src++; - if (*src == '@') - { - src++; - src = parse_exp (src, &op->exp); - - src = skip_colonthing (src, &op->exp, &op->mode); - - *ptr = src; - - op->mode = MEMIND; - return; - - } - - - if (*src == '-') - { - src++; - len = parse_reg (src, &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); - - return; - - - } - - - if ((mode & SIZE) != PSIZE) - as_bad (_("Wrong size pointer register for architecture.")); - op->mode = RDDEC; - op->reg = num; - *ptr = src + len; - return; - } - if (*src == '(') - { - /* Disp */ - src++; - - /* Start off assuming a 16 bit offset */ - - - src = parse_exp (src, &op->exp); - - src = colonmod24 (op, src); - - if (*src == ')') - { - src++; - op->mode |= ABS | direction; - *ptr = src; - return; - } - - if (*src != ',') - { - as_bad (_("expected @(exp, reg16)")); - return; - - } - src++; - - len = parse_reg (src, &mode, &op->reg, direction); - if (len == 0 || !(mode & REG)) - { - as_bad (_("expected @(exp, reg16)")); - return; - } - op->mode |= DISP | direction; - dispreg = op->reg; - src += len; - src = skip_colonthing (src, &op->exp, &op->mode); - - if (*src != ')' && '(') - { - as_bad (_("expected @(exp, reg16)")); - return; - } - *ptr = src + 1; - - return; - } - len = parse_reg (src, &mode, &num, direction); - - if (len) - { - src += len; - if (*src == '+') - { - src++; - if ((mode & SIZE) != PSIZE) - as_bad (_("Wrong size pointer register for architecture.")); - op->mode = RSINC; - op->reg = num; - *ptr = src; - return; - } - if ((mode & SIZE) != PSIZE) - as_bad (_("Wrong size pointer register for architecture.")); - - op->mode = direction | IND | PSIZE; - op->reg = num; - *ptr = src; - - return; - } - else - { - /* must be a symbol */ - - op->mode = ABS | direction; - src = parse_exp (src, &op->exp); - - *ptr = colonmod24 (op, src); - - return; - } - } - - - if (*src == '#') - { - src++; - op->mode = IMM; - src = parse_exp (src, &op->exp); - *ptr = skip_colonthing (src, &op->exp, &op->mode); - - return; - } - else if (strncmp (src, "mach", 4) == 0 - || strncmp (src, "macl", 4) == 0) - { - op->reg = src[3] == 'l'; - op->mode = MACREG; - *ptr = src + 4; - return; - } - 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 - { - op->mode = PCREL | bsize; - } - *ptr = src; - } -} - - -static -char * -get_operands (noperands, op_end, operand) - unsigned int noperands; - char *op_end; - 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, SRC); - if (*ptr == ',') - { - ptr++; - get_operand (&ptr, operand + 1, 1, DST); - } - else - { - operand[1].mode = 0; - } - - break; - case 2: - ptr++; - get_operand (&ptr, operand + 0, 0, SRC); - if (*ptr == ',') - ptr++; - get_operand (&ptr, operand + 1, 1, DST); - 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 * -get_specific (opcode, operands, size) - struct h8_opcode *opcode; - struct h8_op *operands; - int size; -{ - struct h8_opcode *this_try = opcode; - int found = 0; - - unsigned int this_index = opcode->idx; - - /* There's only one ldm/stm and it's easier to just - get out quick for them. */ - if (strcmp (opcode->name, "stm.l") == 0 - || strcmp (opcode->name, "ldm.l") == 0) - return this_try; - - while (this_index == opcode->idx && !found) - { - found = 1; - - this_try = opcode++; - if (this_try->noperands == 0) - { - int this_size; - - this_size = this_try->how & SN; - if (this_size != size && (this_size != SB || size != SN)) - found = 0; - } - else - { - unsigned int i; - - for (i = 0; i < this_try->noperands && found; i++) - { - op_type op = this_try->args.nib[i]; - int x = operands[i].mode; - - if ((op & (DISP | REG)) == (DISP | REG) - && ((x & (DISP | REG)) == (DISP | REG))) - { - dispreg = operands[i].reg; - } - else if (op & REG) - { - if (!(x & REG)) - found = 0; - - if (x & L_P) - x = (x & ~L_P) | (Hmode ? L_32 : L_16); - if (op & L_P) - op = (op & ~L_P) | (Hmode ? L_32 : L_16); - - opsize = op & SIZE; - - /* The size of the reg is v important */ - if ((op & SIZE) != (x & SIZE)) - found = 0; - } - else if ((op & ABSJMP) && (x & ABS)) - { - operands[i].mode &= ~ABS; - operands[i].mode |= ABSJMP; - /* But it may not be 24 bits long */ - if (!Hmode) - { - operands[i].mode &= ~SIZE; - operands[i].mode |= L_16; - } - } - else if ((op & (KBIT | DBIT)) && (x & IMM)) - { - /* This is ok if the immediate value is sensible */ - } - else if (op & PCREL) - { - /* The size of the displacement is important */ - if ((op & SIZE) != (x & SIZE)) - found = 0; - } - else if ((op & (DISP | IMM | ABS)) - && (op & (DISP | IMM | ABS)) == (x & (DISP | IMM | ABS))) - { - /* Promote a L_24 to L_32 if it makes us match. */ - if ((x & L_24) && (op & L_32)) - { - x &= ~L_24; - x |= L_32; - } - /* Promote an L8 to L_16 if it makes us match. */ - if (op & ABS && op & L_8 && op & DISP) - { - if (x & L_16) - found= 1; - } - else if ((x & SIZE) != 0 - && ((op & SIZE) != (x & SIZE))) - found = 0; - } - else if ((op & MACREG) != (x & MACREG)) - { - found = 0; - } - else if ((op & MODE) != (x & MODE)) - { - found = 0; - } - } - } - } - if (found) - return this_try; - else - return 0; -} - -static void -check_operand (operand, width, string) - struct h8_op *operand; - unsigned int width; - char *string; -{ - if (operand->exp.X_add_symbol == 0 - && operand->exp.X_op_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)) - { - if (width == 255 - && (operand->exp.X_add_number & 0xff00) == 0xff00) - { - /* Just ignore this one - which happens when trying to - fit a 16 bit address truncated into an 8 bit address - of something like bset. */ - } - else - { - as_warn (_("operand %s0x%lx out of range."), string, - (unsigned long) operand->exp.X_add_number); - } - } - } - -} - -/* RELAXMODE has one of 3 values: - - 0 Output a "normal" reloc, no relaxing possible for this insn/reloc - - 1 Output a relaxable 24bit absolute mov.w address relocation - (may relax into a 16bit absolute address). - - 2 Output a relaxable 16/24 absolute mov.b address relocation - (may relax into an 8bit absolute address). */ - -static void -do_a_fix_imm (offset, operand, relaxmode) - int offset; - struct h8_op *operand; - int relaxmode; -{ - int idx; - int size; - int where; - - - char *t = operand->mode & IMM ? "#" : "@"; - - if (operand->exp.X_add_symbol == 0) - { - char *bytes = frag_now->fr_literal + offset; - switch (operand->mode & SIZE) - { - case L_2: - check_operand (operand, 0x3, t); - bytes[0] |= (operand->exp.X_add_number) << 4; - break; - case L_3: - check_operand (operand, 0x7, t); - bytes[0] |= (operand->exp.X_add_number) << 4; - break; - case L_8: - check_operand (operand, 0xff, t); - bytes[0] = operand->exp.X_add_number; - break; - case L_16: - check_operand (operand, 0xffff, t); - bytes[0] = operand->exp.X_add_number >> 8; - bytes[1] = operand->exp.X_add_number >> 0; - break; - case L_24: - check_operand (operand, 0xffffff, t); - bytes[0] = operand->exp.X_add_number >> 16; - bytes[1] = operand->exp.X_add_number >> 8; - bytes[2] = operand->exp.X_add_number >> 0; - break; - - case L_32: - /* This should be done with bfd */ - bytes[0] = operand->exp.X_add_number >> 24; - bytes[1] = operand->exp.X_add_number >> 16; - bytes[2] = operand->exp.X_add_number >> 8; - bytes[3] = operand->exp.X_add_number >> 0; - break; - } - - } - else - { - switch (operand->mode & SIZE) - { - - case L_24: - case L_32: - size = 4; - where = (operand->mode & SIZE) == L_24 ? -1 : 0; - if (relaxmode == 2) - idx = R_MOV24B1; - else if (relaxmode == 1) - idx = R_MOVL1; - else - idx = R_RELLONG; - break; - default: - as_bad(_("Can't work out size of operand.\n")); - case L_16: - size = 2; - where = 0; - if (relaxmode == 2) - idx = R_MOV16B1; - else - idx = R_RELWORD; - operand->exp.X_add_number = (short)operand->exp.X_add_number; - break; - case L_8: - size = 1; - where = 0; - idx = R_RELBYTE; - /* This used to use a cast to char, but that fails if char is an - unsigned type. We can't use `signed char', as that isn't valid - K&R C. */ - if (operand->exp.X_add_number & 0x80) - operand->exp.X_add_number |= ((offsetT) -1 << 8); - else - operand->exp.X_add_number &= 0xff; - } - - fix_new_exp (frag_now, - offset + where, - size, - &operand->exp, - 0, - idx); - } - -} - -/* Now we know what sort of opcodes it is, lets build the bytes - - */ -static void -build_bytes (this_try, operand) - struct h8_opcode *this_try; - struct h8_op *operand; -{ - unsigned int i; - - char *output = frag_more (this_try->length); - op_type *nibble_ptr = this_try->data.nib; - op_type c; - unsigned int nibble_count = 0; - int absat; - int immat; - int nib; - int movb = 0; - char asnibbles[30]; - char *p = asnibbles; - - if (!(this_try->inbase || Hmode)) - as_warn (_("Opcode `%s' with these operand types not available in H8/300 mode"), - this_try->name); - - while (*nibble_ptr != E) - { - int d; - c = *nibble_ptr++; - - d = (c & (DST | SRC_IN_DST)) != 0; - - if (c < 16) - { - nib = c; - } - else - { - - if (c & (REG | IND | INC | DEC)) - { - nib = operand[d].reg; - } - else if ((c & DISPREG) == (DISPREG)) - { - nib = dispreg; - } - else if (c & ABS ) - { - operand[d].mode = c; - absat = nibble_count / 2; - nib = 0; - } - else if (c & (IMM | PCREL | ABS | ABSJMP | DISP)) - { - operand[d].mode = c; - immat = nibble_count / 2; - nib = 0; - } - else if (c & IGNORE) - { - nib = 0; - } - else if (c & DBIT) - { - switch (operand[0].exp.X_add_number) - { - case 1: - nib = c; - break; - case 2: - nib = 0x8 | c; - break; - default: - as_bad (_("Need #1 or #2 here")); - } - } - else if (c & KBIT) - { - switch (operand[0].exp.X_add_number) - { - case 1: - nib = 0; - break; - case 2: - nib = 8; - break; - case 4: - if (!Hmode) - as_warn (_("#4 not valid on H8/300.")); - nib = 9; - break; - - default: - as_bad (_("Need #1 or #2 here")); - break; - } - /* stop it making a fix */ - operand[0].mode = 0; - } - - if (c & MEMRELAX) - { - operand[d].mode |= MEMRELAX; - } - - if (c & B31) - { - nib |= 0x8; - } - - if (c & MACREG) - { - nib = 2 + operand[d].reg; - } - } - nibble_count++; - - *p++ = nib; - } - - /* Disgusting. Why, oh why didn't someone ask us for advice - on the assembler format. */ - if (strcmp (this_try->name, "stm.l") == 0 - || strcmp (this_try->name, "ldm.l") == 0) - { - int high, low; - high = (operand[this_try->name[0] == 'l' ? 1 : 0].reg >> 8) & 0xf; - low = operand[this_try->name[0] == 'l' ? 1 : 0].reg & 0xf; - - asnibbles[2] = high - low; - asnibbles[7] = (this_try->name[0] == 'l') ? high : low; - } - - for (i = 0; i < this_try->length; i++) - { - output[i] = (asnibbles[i * 2] << 4) | asnibbles[i * 2 + 1]; - } - - /* Note if this is a movb instruction -- there's a special relaxation - which only applies to them. */ - if (strcmp (this_try->name, "mov.b") == 0) - movb = 1; - - /* output any fixes */ - for (i = 0; i < 2; i++) - { - int x = operand[i].mode; - - if (x & (IMM | DISP)) - { - do_a_fix_imm (output - frag_now->fr_literal + immat, - operand + i, x & MEMRELAX != 0); - } - else if (x & ABS) - { - do_a_fix_imm (output - frag_now->fr_literal + absat, - operand + i, x & MEMRELAX ? movb + 1 : 0); - } - else if (x & PCREL) - { - int size16 = x & L_16; - int where = size16 ? 2 : 1; - int size = size16 ? 2 : 1; - int type = size16 ? R_PCRWORD : R_PCRBYTE; - - check_operand (operand + i, size16 ? 0x7fff : 0x7f, "@"); - - if (operand[i].exp.X_add_number & 1) - { - as_warn (_("branch operand has odd offset (%lx)\n"), - (unsigned long) operand->exp.X_add_number); - } - - operand[i].exp.X_add_number -= 1; - /* This used to use a cast to char, but that fails if char is an - unsigned type. We can't use `signed char', as that isn't valid - K&R C. */ - if (operand[i].exp.X_add_number & 0x80) - operand[i].exp.X_add_number |= ((offsetT) -1 << 8); - else - operand[i].exp.X_add_number &= 0xff; - - fix_new_exp (frag_now, - output - frag_now->fr_literal + where, - size, - &operand[i].exp, - 1, - type); - } - else if (x & MEMIND) - { - - check_operand (operand + i, 0xff, "@@"); - fix_new_exp (frag_now, - output - frag_now->fr_literal + 1, - 1, - &operand[i].exp, - 0, - R_MEM_INDIRECT); - } - else if (x & ABSJMP) - { - /* This jmp may be a jump or a branch */ - - check_operand (operand + i, Hmode ? 0xffffff : 0xffff, "@"); - if (operand[i].exp.X_add_number & 1) - { - as_warn (_("branch operand has odd offset (%lx)\n"), - (unsigned long) operand->exp.X_add_number); - } - if (!Hmode) - operand[i].exp.X_add_number = (short) operand[i].exp.X_add_number; - fix_new_exp (frag_now, - output - frag_now->fr_literal, - 4, - &operand[i].exp, - 0, - R_JMPL1); - } - } - -} - -/* - try and give an intelligent error message for common and simple to - detect errors - */ - -static void -clever_message (opcode, operand) - struct h8_opcode *opcode; - struct h8_op *operand; -{ - /* Find out if there was more than one possible opccode */ - - if ((opcode + 1)->idx != opcode->idx) - { - unsigned int argn; - - /* Only one opcode of this flavour, try and guess which operand - didn't match */ - for (argn = 0; argn < opcode->noperands; argn++) - { - switch (opcode->args.nib[argn]) - { - case RD16: - if (operand[argn].mode != RD16) - { - as_bad (_("destination operand must be 16 bit register")); - return; - - } - break; - - case RS8: - - if (operand[argn].mode != RS8) - { - as_bad (_("source operand must be 8 bit register")); - return; - } - break; - - case ABS16DST: - if (operand[argn].mode != ABS16DST) - { - as_bad (_("destination operand must be 16bit absolute address")); - return; - } - break; - case RD8: - if (operand[argn].mode != RD8) - { - as_bad (_("destination operand must be 8 bit register")); - return; - } - break; - - - case ABS16SRC: - if (operand[argn].mode != ABS16SRC) - { - as_bad (_("source operand must be 16bit absolute address")); - return; - } - break; - - } - } - } - as_bad (_("invalid operands")); -} - -/* 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. - */ - - - -void -md_assemble (str) - char *str; -{ - char *op_start; - char *op_end; - struct h8_op operand[2]; - struct h8_opcode *opcode; - struct h8_opcode *prev_opcode; - - char *dot = 0; - char c; - int size; - - /* Drop leading whitespace */ - while (*str == ' ') - str++; - - /* find the op code end */ - for (op_start = op_end = str; - *op_end != 0 && *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 ")); - } - 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; - } - - /* We use to set input_line_pointer to the result of get_operands, - but that is wrong. Our caller assumes we don't change it. */ - - (void) get_operands (opcode->noperands, op_end, operand); - *op_end = c; - prev_opcode = opcode; - - size = SN; - if (dot) - { - switch (*dot) - { - case 'b': - size = SB; - break; - - case 'w': - size = SW; - break; - - case 'l': - size = SL; - break; - } - } - opcode = get_specific (opcode, operand, size); - - if (opcode == 0) - { - /* Couldn't find an opcode which matched the operands */ - char *where = frag_more (2); - - where[0] = 0x0; - where[1] = 0x0; - clever_message (prev_opcode, operand); - - return; - } - if (opcode->size && dot) - { - if (opcode->size != *dot) - { - as_warn (_("mismatch between opcode size and operand size")); - } - } - - build_bytes (opcode, operand); - -} - -void -tc_crawl_symbol_chain (headers) - object_headers * headers; -{ - printf (_("call to tc_crawl_symbol_chain \n")); -} - -symbolS * -md_undefined_symbol (name) - char *name; -{ - 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 - -/* Turn a string in input_line_pointer into a floating point constant of type - type, and store the appropriate bytes in *litP. The number of LITTLENUMS - emitted is stored in *sizeP . An error message is returned, or NULL on OK. - */ -char * -md_atof (type, litP, sizeP) - char type; - char *litP; - int *sizeP; -{ - int prec; - LITTLENUM_TYPE words[MAX_LITTLENUMS]; - LITTLENUM_TYPE *wordP; - char *t; - char *atof_ieee (); - - switch (type) - { - case 'f': - case 'F': - case 's': - case 'S': - prec = 2; - break; - - case 'd': - case 'D': - case 'r': - case 'R': - prec = 4; - break; - - case 'x': - case 'X': - prec = 6; - break; - - case 'p': - case 'P': - prec = 6; - break; - - default: - *sizeP = 0; - return _("Bad call to MD_ATOF()"); - } - t = atof_ieee (input_line_pointer, type, words); - if (t) - input_line_pointer = t; - - *sizeP = prec * sizeof (LITTLENUM_TYPE); - for (wordP = words; prec--;) - { - md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE)); - litP += sizeof (LITTLENUM_TYPE); - } - return 0; -} - -CONST char *md_shortopts = ""; -struct option md_longopts[] = { - {NULL, no_argument, NULL, 0} -}; -size_t md_longopts_size = sizeof(md_longopts); - -int -md_parse_option (c, arg) - int c; - char *arg; -{ - return 0; -} - -void -md_show_usage (stream) - FILE *stream; -{ -} - -void -tc_aout_fix_to_chars () -{ - printf (_("call to tc_aout_fix_to_chars \n")); - abort (); -} - -void -md_convert_frag (headers, seg, fragP) - object_headers *headers; - segT seg; - fragS *fragP; -{ - printf (_("call to md_convert_frag \n")); - abort (); -} - -valueT -md_section_align (seg, size) - segT seg; - valueT size; -{ - return ((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg])); - -} - -void -md_apply_fix (fixP, val) - fixS *fixP; - long val; -{ - char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; - - switch (fixP->fx_size) - { - case 1: - *buf++ = val; - break; - case 2: - *buf++ = (val >> 8); - *buf++ = val; - break; - case 4: - *buf++ = (val >> 24); - *buf++ = (val >> 16); - *buf++ = (val >> 8); - *buf++ = val; - break; - default: - abort (); - } -} - -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 (); -} - -/* Put number into target byte order */ - -void -md_number_to_chars (ptr, use, nbytes) - char *ptr; - valueT use; - int nbytes; -{ - number_to_chars_bigendian (ptr, use, nbytes); -} -long -md_pcrel_from (fixP) - fixS *fixP; -{ - abort (); -} - - -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 == TC_CONS_RELOC) - { - /* cons likes to create reloc32's whatever the size of the reloc.. - */ - switch (fix_ptr->fx_size) - { - case 4: - intr->r_type = R_RELLONG; - break; - 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) - { - if (symbol_ptr->sy_number != -1) - intr->r_symndx = symbol_ptr->sy_number; - else - { - symbolS *segsym; - - /* This case arises when a reference is made to `.'. */ - segsym = seg_info (S_GET_SEGMENT (symbol_ptr))->dot; - if (segsym == NULL) - intr->r_symndx = -1; - else - { - intr->r_symndx = segsym->sy_number; - intr->r_offset += S_GET_VALUE (symbol_ptr); - } - } - } - else - intr->r_symndx = -1; - - -} - -/* end of tc-h8300.c */ |