old-cross-binutils/gas/config/tc-h8300.c

1447 lines
26 KiB
C
Raw Normal View History

/* tc-h8300.c -- Assemble code for the Hitachi H8/300
Copyright (C) 1991, 1992 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
1992-01-24 18:30:47 +00:00
/*
1991-10-06 19:02:50 +00:00
Written By Steve Chamberlain
sac@cygnus.com
*/
1991-10-06 19:02:50 +00:00
#include <stdio.h>
#include "as.h"
#include "bfd.h"
#define DEFINE_TABLE
#define h8_opcodes ops
#include "opcode/h8300.h"
1991-10-06 19:02:50 +00:00
#include <ctype.h>
const char comment_chars[] =
{';', 0};
const char line_separator_chars[] =
{'$', 0};
const char line_comment_chars[] = "#";
1991-10-06 19:02:50 +00:00
/* 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;
#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;
}
void
sbranch (size)
int size;
{
bsize = size;
}
const pseudo_typeS md_pseudo_table[] =
{
{"h8300h", h8300hmode, 0},
{"sbranch", sbranch, L_8},
{"lbranch", sbranch, L_16},
{"int", cons, 2},
{"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}
1991-10-06 19:02:50 +00:00
};
const int md_reloc_size;
1991-10-06 19:02:50 +00:00
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";
1991-10-06 19:02:50 +00:00
const relax_typeS md_relax_table[1];
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;
const struct reg_entry *reg;
char prev_buffer[100];
int idx = 0;
opcode_hash_control = hash_new ();
prev_buffer[0] = 0;
1991-10-06 19:02:50 +00:00
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++;
}
1991-10-06 19:02:50 +00:00
}
struct h8_exp
1991-10-06 19:02:50 +00:00
{
char *e_beg;
char *e_end;
expressionS e_exp;
1991-10-06 19:02:50 +00:00
};
int dispreg;
int opsize; /* Set when a register size is seen */
1991-10-06 19:02:50 +00:00
struct h8_op
{
op_type mode;
unsigned reg;
expressionS exp;
};
1991-10-06 19:02:50 +00:00
/*
parse operands
WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp
r0l,r0h,..r7l,r7h
@WREG
@WREG+
@-WREG
#const
1991-10-06 19:02:50 +00:00
*/
1991-10-06 19:02:50 +00:00
/* 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;
1991-10-06 19:02:50 +00:00
{
if (src[0] == 's' && src[1] == 'p')
{
*mode = PSIZE | REG | direction;
*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 = PSIZE | REG | direction;
*reg = 6;
return 2;
}
if (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 only legal for H8/300-H");
return 3;
}
if (src[0] == 'e'
&& src[1] >= '0' && src[1] <= '7')
{
*mode = L_16 | REG | direction;
*reg = src[1] - '0' + 8;
if (!Hmode)
as_warn ("Reg only legal for H8/300-H");
return 2;
}
if (src[0] == 'r')
{
if (src[1] >= '0' && src[1] <= '7')
{
if (src[2] == 'l')
{
*mode = L_8 | REG | direction;
*reg = (src[1] - '0') + 8;
return 3;
}
if (src[2] == 'h')
{
*mode = L_8 | REG | direction;
*reg = (src[1] - '0');
return 3;
}
*mode = L_16 | REG | direction;
*reg = (src[1] - '0');
return 2;
}
}
return 0;
1991-10-06 19:02:50 +00:00
}
char *
DEFUN (parse_exp, (s, op),
char *s AND
expressionS * op)
1991-10-06 19:02:50 +00:00
{
char *save = input_line_pointer;
char *new;
input_line_pointer = s;
* Extensive changes to permit symbols to contain any expression type and to delay the computation of the expression until the value is actually needed. This permits setting symbols to values calculated based on object code size. Expressions were changed to no longer be in a section, to stop the overloading of segment and expression type that previously occurred. * as.c (big_section, pass1_section, diff_section, absent_section): Removed. (expr_section): Added (used for dummy symbols which hold intermediate expression values). (perform_an_assembly_pass): Create expr_section, do not create the sections now removed. * as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and SEG_DIFFERENCE. Added SEG_EXPR. (SEG_NORMAL): Corresponding changes. * subsegs.c (seg_name, subsegs_begin): Changed accordingly. * write.c (write_object_file): Ditto. * config/obj-aout.c (seg_N_TYPE): Ditto. * config/obj-bout.c (seg_N_TYPE): Ditto. * config/obj-coff.c (seg_N_TYPE): Ditto. * config/obj-coffbfd.c (seg_N_TYPE): Ditto. * config/obj-vms.c (seg_N_TYPE): Ditto. * expr.h (operatorT): Moved in from expr.c, added some values. (expressionS): Added X_op field, removed X_seg field; renamed X_subtract_symbol to X_op_symbol. * expr.c: Extensive changes to assign expression types rather than sections and to simplify the parsing. * write.c (fix_new_internal): New static function. (fix_new): Removed sub_symbol argument. (fix_new_exp): New function, takes expression argument. * write.h: Prototype changes for fix_new and fix_new_exp. * cond.c (s_if): Changed accordingly. * read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons, parse_repeat_cons, get_segmented_expression, get_known_segmented_expression, get_absolute_expression): Ditto. * symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE): Ditto. * write.c (write_object_file): Ditto. * config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto. * config/obj-coffbfd.c (obj_coff_def, obj_coff_val, obj_coff_endef, yank_symbols): Ditto. * config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto. * config/tc-a29k.c (md_assemble, parse_operand, machine_ip, print_insn, md_operand): Ditto. * config/tc-h8300.c (parse_exp, colonmod24, check_operand, do_a_fix_imm, build_bytes): Ditto. * config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist, get_specific, check, insert, md_convert_frag): Ditto. * config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa, md_assemble, pa_ip, getExpression, getAbsoluteExpression, evaluateAbsolute, pa_build_unwind_subspace, pa_entry, process_exit): Ditto. * config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative, is_complex): Ditto. * config/tc-i386.c (pe, md_assemble, i386_operand, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-i860.c (md_assemble, getExpression, print_insn): Ditto. * config/tc-i960.c (parse_expr, subs, segs, md_convert_frag, get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc, i960_handle_align): Ditto. * config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op, subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1, md_estimate_size_before_relax, md_create_long_jump, get_num): Ditto. * config/tc-m88k.c (md_assemble, get_imm16, get_pcr, md_create_short_jump, md_create_long_jump): Ditto. * config/tc-mips.c (md_assemble, append_insn, gp_reference, macro_build, macro, my_getExpression): Ditto. Also removed get_optional_absolute_expression; just use get_absolute_expression instead. * config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif, fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto. * config/tc-ns32k.h (fix_new_ns32k prototype): Ditto. * config/tc-sh.c (parse_exp, check, insert, md_convert_frag): Ditto. * config/tc-sparc.c (md_assemble, sparc_ip, getExpression, print_insn): Ditto. * config/tc-tahoe.c (struct top, md_estimate_size_before_relax, tip_op, md_assemble): Ditto. * config/tc-vax.c (seg_of_operand, md_assemble, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto.
1993-07-21 00:41:42 +00:00
if (expression (op) == O_absent)
as_bad ("missing operand");
new = input_line_pointer;
input_line_pointer = save;
* Extensive changes to permit symbols to contain any expression type and to delay the computation of the expression until the value is actually needed. This permits setting symbols to values calculated based on object code size. Expressions were changed to no longer be in a section, to stop the overloading of segment and expression type that previously occurred. * as.c (big_section, pass1_section, diff_section, absent_section): Removed. (expr_section): Added (used for dummy symbols which hold intermediate expression values). (perform_an_assembly_pass): Create expr_section, do not create the sections now removed. * as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and SEG_DIFFERENCE. Added SEG_EXPR. (SEG_NORMAL): Corresponding changes. * subsegs.c (seg_name, subsegs_begin): Changed accordingly. * write.c (write_object_file): Ditto. * config/obj-aout.c (seg_N_TYPE): Ditto. * config/obj-bout.c (seg_N_TYPE): Ditto. * config/obj-coff.c (seg_N_TYPE): Ditto. * config/obj-coffbfd.c (seg_N_TYPE): Ditto. * config/obj-vms.c (seg_N_TYPE): Ditto. * expr.h (operatorT): Moved in from expr.c, added some values. (expressionS): Added X_op field, removed X_seg field; renamed X_subtract_symbol to X_op_symbol. * expr.c: Extensive changes to assign expression types rather than sections and to simplify the parsing. * write.c (fix_new_internal): New static function. (fix_new): Removed sub_symbol argument. (fix_new_exp): New function, takes expression argument. * write.h: Prototype changes for fix_new and fix_new_exp. * cond.c (s_if): Changed accordingly. * read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons, parse_repeat_cons, get_segmented_expression, get_known_segmented_expression, get_absolute_expression): Ditto. * symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE): Ditto. * write.c (write_object_file): Ditto. * config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto. * config/obj-coffbfd.c (obj_coff_def, obj_coff_val, obj_coff_endef, yank_symbols): Ditto. * config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto. * config/tc-a29k.c (md_assemble, parse_operand, machine_ip, print_insn, md_operand): Ditto. * config/tc-h8300.c (parse_exp, colonmod24, check_operand, do_a_fix_imm, build_bytes): Ditto. * config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist, get_specific, check, insert, md_convert_frag): Ditto. * config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa, md_assemble, pa_ip, getExpression, getAbsoluteExpression, evaluateAbsolute, pa_build_unwind_subspace, pa_entry, process_exit): Ditto. * config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative, is_complex): Ditto. * config/tc-i386.c (pe, md_assemble, i386_operand, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-i860.c (md_assemble, getExpression, print_insn): Ditto. * config/tc-i960.c (parse_expr, subs, segs, md_convert_frag, get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc, i960_handle_align): Ditto. * config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op, subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1, md_estimate_size_before_relax, md_create_long_jump, get_num): Ditto. * config/tc-m88k.c (md_assemble, get_imm16, get_pcr, md_create_short_jump, md_create_long_jump): Ditto. * config/tc-mips.c (md_assemble, append_insn, gp_reference, macro_build, macro, my_getExpression): Ditto. Also removed get_optional_absolute_expression; just use get_absolute_expression instead. * config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif, fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto. * config/tc-ns32k.h (fix_new_ns32k prototype): Ditto. * config/tc-sh.c (parse_exp, check, insert, md_convert_frag): Ditto. * config/tc-sparc.c (md_assemble, sparc_ip, getExpression, print_insn): Ditto. * config/tc-tahoe.c (struct top, md_estimate_size_before_relax, tip_op, md_assemble): Ditto. * config/tc-vax.c (seg_of_operand, md_assemble, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto.
1993-07-21 00:41:42 +00:00
return new;
}
static char *
skip_colonthing (ptr, exp, mode)
char *ptr;
expressionS *exp;
int *mode;
{
if (*ptr == ':')
{
ptr++;
if (*ptr == '8')
{
ptr++;
/* ff fill any 8 bit quantity */
exp->X_add_number |= 0xff00;
}
else
{
*mode &= ~SIZE;
if (*ptr == '2')
{
*mode |= L_24;
}
else if (*ptr == '1')
{
*mode |= L_16;
}
while (isdigit (*ptr))
ptr++;
}
}
return ptr;
1991-10-06 19:02:50 +00:00
}
/* 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
*/
1991-10-06 19:02:50 +00:00
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
* Extensive changes to permit symbols to contain any expression type and to delay the computation of the expression until the value is actually needed. This permits setting symbols to values calculated based on object code size. Expressions were changed to no longer be in a section, to stop the overloading of segment and expression type that previously occurred. * as.c (big_section, pass1_section, diff_section, absent_section): Removed. (expr_section): Added (used for dummy symbols which hold intermediate expression values). (perform_an_assembly_pass): Create expr_section, do not create the sections now removed. * as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and SEG_DIFFERENCE. Added SEG_EXPR. (SEG_NORMAL): Corresponding changes. * subsegs.c (seg_name, subsegs_begin): Changed accordingly. * write.c (write_object_file): Ditto. * config/obj-aout.c (seg_N_TYPE): Ditto. * config/obj-bout.c (seg_N_TYPE): Ditto. * config/obj-coff.c (seg_N_TYPE): Ditto. * config/obj-coffbfd.c (seg_N_TYPE): Ditto. * config/obj-vms.c (seg_N_TYPE): Ditto. * expr.h (operatorT): Moved in from expr.c, added some values. (expressionS): Added X_op field, removed X_seg field; renamed X_subtract_symbol to X_op_symbol. * expr.c: Extensive changes to assign expression types rather than sections and to simplify the parsing. * write.c (fix_new_internal): New static function. (fix_new): Removed sub_symbol argument. (fix_new_exp): New function, takes expression argument. * write.h: Prototype changes for fix_new and fix_new_exp. * cond.c (s_if): Changed accordingly. * read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons, parse_repeat_cons, get_segmented_expression, get_known_segmented_expression, get_absolute_expression): Ditto. * symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE): Ditto. * write.c (write_object_file): Ditto. * config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto. * config/obj-coffbfd.c (obj_coff_def, obj_coff_val, obj_coff_endef, yank_symbols): Ditto. * config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto. * config/tc-a29k.c (md_assemble, parse_operand, machine_ip, print_insn, md_operand): Ditto. * config/tc-h8300.c (parse_exp, colonmod24, check_operand, do_a_fix_imm, build_bytes): Ditto. * config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist, get_specific, check, insert, md_convert_frag): Ditto. * config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa, md_assemble, pa_ip, getExpression, getAbsoluteExpression, evaluateAbsolute, pa_build_unwind_subspace, pa_entry, process_exit): Ditto. * config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative, is_complex): Ditto. * config/tc-i386.c (pe, md_assemble, i386_operand, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-i860.c (md_assemble, getExpression, print_insn): Ditto. * config/tc-i960.c (parse_expr, subs, segs, md_convert_frag, get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc, i960_handle_align): Ditto. * config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op, subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1, md_estimate_size_before_relax, md_create_long_jump, get_num): Ditto. * config/tc-m88k.c (md_assemble, get_imm16, get_pcr, md_create_short_jump, md_create_long_jump): Ditto. * config/tc-mips.c (md_assemble, append_insn, gp_reference, macro_build, macro, my_getExpression): Ditto. Also removed get_optional_absolute_expression; just use get_absolute_expression instead. * config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif, fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto. * config/tc-ns32k.h (fix_new_ns32k prototype): Ditto. * config/tc-sh.c (parse_exp, check, insert, md_convert_frag): Ditto. * config/tc-sparc.c (md_assemble, sparc_ip, getExpression, print_insn): Ditto. * config/tc-tahoe.c (struct top, md_estimate_size_before_relax, tip_op, md_assemble): Ditto. * config/tc-vax.c (seg_of_operand, md_assemble, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto.
1993-07-21 00:41:42 +00:00
|| 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;
1991-10-06 19:02:50 +00:00
{
char *src = *ptr;
op_type mode;
unsigned int num;
unsigned int len;
unsigned int size;
op->mode = E;
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 = DISP | 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
{
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 *
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, 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;
1991-10-06 19:02:50 +00:00
}
/* 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)
struct h8_opcode *opcode;
struct h8_op *operands;
{
struct h8_opcode *this_try = opcode;
int found = 0;
unsigned int this_index = opcode->idx;
while (this_index == opcode->idx && !found)
{
unsigned int i;
found = 1;
this_try = opcode++;
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)))
{
/* Got a diplacement,will fit if no size or same size as try */
if ((x & SIZE) != 0
&& ((op & SIZE) != (x & SIZE)))
found = 0;
}
else if ((op & ABSMOV) && (x & ABS))
{
/* Ok */
}
else if ((op & MODE) != (x & MODE))
{
found = 0;
}
}
}
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
* Extensive changes to permit symbols to contain any expression type and to delay the computation of the expression until the value is actually needed. This permits setting symbols to values calculated based on object code size. Expressions were changed to no longer be in a section, to stop the overloading of segment and expression type that previously occurred. * as.c (big_section, pass1_section, diff_section, absent_section): Removed. (expr_section): Added (used for dummy symbols which hold intermediate expression values). (perform_an_assembly_pass): Create expr_section, do not create the sections now removed. * as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and SEG_DIFFERENCE. Added SEG_EXPR. (SEG_NORMAL): Corresponding changes. * subsegs.c (seg_name, subsegs_begin): Changed accordingly. * write.c (write_object_file): Ditto. * config/obj-aout.c (seg_N_TYPE): Ditto. * config/obj-bout.c (seg_N_TYPE): Ditto. * config/obj-coff.c (seg_N_TYPE): Ditto. * config/obj-coffbfd.c (seg_N_TYPE): Ditto. * config/obj-vms.c (seg_N_TYPE): Ditto. * expr.h (operatorT): Moved in from expr.c, added some values. (expressionS): Added X_op field, removed X_seg field; renamed X_subtract_symbol to X_op_symbol. * expr.c: Extensive changes to assign expression types rather than sections and to simplify the parsing. * write.c (fix_new_internal): New static function. (fix_new): Removed sub_symbol argument. (fix_new_exp): New function, takes expression argument. * write.h: Prototype changes for fix_new and fix_new_exp. * cond.c (s_if): Changed accordingly. * read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons, parse_repeat_cons, get_segmented_expression, get_known_segmented_expression, get_absolute_expression): Ditto. * symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE): Ditto. * write.c (write_object_file): Ditto. * config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto. * config/obj-coffbfd.c (obj_coff_def, obj_coff_val, obj_coff_endef, yank_symbols): Ditto. * config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto. * config/tc-a29k.c (md_assemble, parse_operand, machine_ip, print_insn, md_operand): Ditto. * config/tc-h8300.c (parse_exp, colonmod24, check_operand, do_a_fix_imm, build_bytes): Ditto. * config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist, get_specific, check, insert, md_convert_frag): Ditto. * config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa, md_assemble, pa_ip, getExpression, getAbsoluteExpression, evaluateAbsolute, pa_build_unwind_subspace, pa_entry, process_exit): Ditto. * config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative, is_complex): Ditto. * config/tc-i386.c (pe, md_assemble, i386_operand, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-i860.c (md_assemble, getExpression, print_insn): Ditto. * config/tc-i960.c (parse_expr, subs, segs, md_convert_frag, get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc, i960_handle_align): Ditto. * config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op, subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1, md_estimate_size_before_relax, md_create_long_jump, get_num): Ditto. * config/tc-m88k.c (md_assemble, get_imm16, get_pcr, md_create_short_jump, md_create_long_jump): Ditto. * config/tc-mips.c (md_assemble, append_insn, gp_reference, macro_build, macro, my_getExpression): Ditto. Also removed get_optional_absolute_expression; just use get_absolute_expression instead. * config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif, fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto. * config/tc-ns32k.h (fix_new_ns32k prototype): Ditto. * config/tc-sh.c (parse_exp, check, insert, md_convert_frag): Ditto. * config/tc-sparc.c (md_assemble, sparc_ip, getExpression, print_insn): Ditto. * config/tc-tahoe.c (struct top, md_estimate_size_before_relax, tip_op, md_assemble): Ditto. * config/tc-vax.c (seg_of_operand, md_assemble, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto.
1993-07-21 00:41:42 +00:00
&& 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))
{
as_warn ("operand %s0x%x out of range.", string, operand->exp.X_add_number);
}
}
}
static void
do_a_fix_imm (offset, operand, relaxing)
int offset;
struct h8_op *operand;
int relaxing;
{
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_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)
{
default:
abort ();
case L_24:
size = 4;
where = -1;
idx = relaxing ? R_MOVLB1 : R_RELLONG;
break;
case L_32:
size = 4;
where = 0;
idx = R_RELLONG;
break;
case L_16:
size = 2;
where = 0;
idx = relaxing ? R_MOVB1 : R_RELWORD;
break;
case L_8:
size = 1;
where = 0;
idx = R_RELBYTE;
}
* Extensive changes to permit symbols to contain any expression type and to delay the computation of the expression until the value is actually needed. This permits setting symbols to values calculated based on object code size. Expressions were changed to no longer be in a section, to stop the overloading of segment and expression type that previously occurred. * as.c (big_section, pass1_section, diff_section, absent_section): Removed. (expr_section): Added (used for dummy symbols which hold intermediate expression values). (perform_an_assembly_pass): Create expr_section, do not create the sections now removed. * as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and SEG_DIFFERENCE. Added SEG_EXPR. (SEG_NORMAL): Corresponding changes. * subsegs.c (seg_name, subsegs_begin): Changed accordingly. * write.c (write_object_file): Ditto. * config/obj-aout.c (seg_N_TYPE): Ditto. * config/obj-bout.c (seg_N_TYPE): Ditto. * config/obj-coff.c (seg_N_TYPE): Ditto. * config/obj-coffbfd.c (seg_N_TYPE): Ditto. * config/obj-vms.c (seg_N_TYPE): Ditto. * expr.h (operatorT): Moved in from expr.c, added some values. (expressionS): Added X_op field, removed X_seg field; renamed X_subtract_symbol to X_op_symbol. * expr.c: Extensive changes to assign expression types rather than sections and to simplify the parsing. * write.c (fix_new_internal): New static function. (fix_new): Removed sub_symbol argument. (fix_new_exp): New function, takes expression argument. * write.h: Prototype changes for fix_new and fix_new_exp. * cond.c (s_if): Changed accordingly. * read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons, parse_repeat_cons, get_segmented_expression, get_known_segmented_expression, get_absolute_expression): Ditto. * symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE): Ditto. * write.c (write_object_file): Ditto. * config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto. * config/obj-coffbfd.c (obj_coff_def, obj_coff_val, obj_coff_endef, yank_symbols): Ditto. * config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto. * config/tc-a29k.c (md_assemble, parse_operand, machine_ip, print_insn, md_operand): Ditto. * config/tc-h8300.c (parse_exp, colonmod24, check_operand, do_a_fix_imm, build_bytes): Ditto. * config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist, get_specific, check, insert, md_convert_frag): Ditto. * config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa, md_assemble, pa_ip, getExpression, getAbsoluteExpression, evaluateAbsolute, pa_build_unwind_subspace, pa_entry, process_exit): Ditto. * config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative, is_complex): Ditto. * config/tc-i386.c (pe, md_assemble, i386_operand, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-i860.c (md_assemble, getExpression, print_insn): Ditto. * config/tc-i960.c (parse_expr, subs, segs, md_convert_frag, get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc, i960_handle_align): Ditto. * config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op, subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1, md_estimate_size_before_relax, md_create_long_jump, get_num): Ditto. * config/tc-m88k.c (md_assemble, get_imm16, get_pcr, md_create_short_jump, md_create_long_jump): Ditto. * config/tc-mips.c (md_assemble, append_insn, gp_reference, macro_build, macro, my_getExpression): Ditto. Also removed get_optional_absolute_expression; just use get_absolute_expression instead. * config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif, fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto. * config/tc-ns32k.h (fix_new_ns32k prototype): Ditto. * config/tc-sh.c (parse_exp, check, insert, md_convert_frag): Ditto. * config/tc-sparc.c (md_assemble, sparc_ip, getExpression, print_insn): Ditto. * config/tc-tahoe.c (struct top, md_estimate_size_before_relax, tip_op, md_assemble): Ditto. * config/tc-vax.c (seg_of_operand, md_assemble, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto.
1993-07-21 00:41:42 +00:00
operand->exp.X_add_number = (short) operand->exp.X_add_number;
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);
char *output_ptr = output;
op_type *nibble_ptr = this_try->data.nib;
char part;
op_type c;
char high;
unsigned int nibble_count = 0;
int immat;
int nib;
char asnibbles[30];
char *p = asnibbles;
if (!(this_try->inbase || Hmode))
{
as_warn ("Opcode `%s' only available on H8/300-H", this_try->name);
}
while (*nibble_ptr != E)
{
int d;
c = *nibble_ptr++;
d = (c & 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 & ABSMOV)
{
operand[d].mode &= ~ABS;
operand[d].mode |= ABSMOV;
immat = 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 only valid in h8/300 mode.");
nib = 9;
break;
default:
as_bad ("Need #1 or #2 here");
break;
}
/* stop it making a fix */
operand[0].mode = 0;
}
if (c & B31)
{
nib |= 0x8;
}
}
nibble_count++;
*p++ = nib;
}
for (i = 0; i < this_try->length; i++)
{
output[i] = (asnibbles[i * 2] << 4) | asnibbles[i * 2 + 1];
}
/* output any fixes */
for (i = 0; i < 2; i++)
{
int x = operand[i].mode;
if (x & (IMM | ABS | DISP))
{
do_a_fix_imm (output - frag_now->fr_literal + immat, operand + i,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 (%x)\n",
operand->exp.X_add_number);
}
1993-07-22 18:02:01 +00:00
operand[i].exp.X_add_number =
* Extensive changes to permit symbols to contain any expression type and to delay the computation of the expression until the value is actually needed. This permits setting symbols to values calculated based on object code size. Expressions were changed to no longer be in a section, to stop the overloading of segment and expression type that previously occurred. * as.c (big_section, pass1_section, diff_section, absent_section): Removed. (expr_section): Added (used for dummy symbols which hold intermediate expression values). (perform_an_assembly_pass): Create expr_section, do not create the sections now removed. * as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and SEG_DIFFERENCE. Added SEG_EXPR. (SEG_NORMAL): Corresponding changes. * subsegs.c (seg_name, subsegs_begin): Changed accordingly. * write.c (write_object_file): Ditto. * config/obj-aout.c (seg_N_TYPE): Ditto. * config/obj-bout.c (seg_N_TYPE): Ditto. * config/obj-coff.c (seg_N_TYPE): Ditto. * config/obj-coffbfd.c (seg_N_TYPE): Ditto. * config/obj-vms.c (seg_N_TYPE): Ditto. * expr.h (operatorT): Moved in from expr.c, added some values. (expressionS): Added X_op field, removed X_seg field; renamed X_subtract_symbol to X_op_symbol. * expr.c: Extensive changes to assign expression types rather than sections and to simplify the parsing. * write.c (fix_new_internal): New static function. (fix_new): Removed sub_symbol argument. (fix_new_exp): New function, takes expression argument. * write.h: Prototype changes for fix_new and fix_new_exp. * cond.c (s_if): Changed accordingly. * read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons, parse_repeat_cons, get_segmented_expression, get_known_segmented_expression, get_absolute_expression): Ditto. * symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE): Ditto. * write.c (write_object_file): Ditto. * config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto. * config/obj-coffbfd.c (obj_coff_def, obj_coff_val, obj_coff_endef, yank_symbols): Ditto. * config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto. * config/tc-a29k.c (md_assemble, parse_operand, machine_ip, print_insn, md_operand): Ditto. * config/tc-h8300.c (parse_exp, colonmod24, check_operand, do_a_fix_imm, build_bytes): Ditto. * config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist, get_specific, check, insert, md_convert_frag): Ditto. * config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa, md_assemble, pa_ip, getExpression, getAbsoluteExpression, evaluateAbsolute, pa_build_unwind_subspace, pa_entry, process_exit): Ditto. * config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative, is_complex): Ditto. * config/tc-i386.c (pe, md_assemble, i386_operand, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-i860.c (md_assemble, getExpression, print_insn): Ditto. * config/tc-i960.c (parse_expr, subs, segs, md_convert_frag, get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc, i960_handle_align): Ditto. * config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op, subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1, md_estimate_size_before_relax, md_create_long_jump, get_num): Ditto. * config/tc-m88k.c (md_assemble, get_imm16, get_pcr, md_create_short_jump, md_create_long_jump): Ditto. * config/tc-mips.c (md_assemble, append_insn, gp_reference, macro_build, macro, my_getExpression): Ditto. Also removed get_optional_absolute_expression; just use get_absolute_expression instead. * config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif, fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto. * config/tc-ns32k.h (fix_new_ns32k prototype): Ditto. * config/tc-sh.c (parse_exp, check, insert, md_convert_frag): Ditto. * config/tc-sparc.c (md_assemble, sparc_ip, getExpression, print_insn): Ditto. * config/tc-tahoe.c (struct top, md_estimate_size_before_relax, tip_op, md_assemble): Ditto. * config/tc-vax.c (seg_of_operand, md_assemble, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto.
1993-07-21 00:41:42 +00:00
(char) (operand[i].exp.X_add_number - 1);
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, "@@");
* Extensive changes to permit symbols to contain any expression type and to delay the computation of the expression until the value is actually needed. This permits setting symbols to values calculated based on object code size. Expressions were changed to no longer be in a section, to stop the overloading of segment and expression type that previously occurred. * as.c (big_section, pass1_section, diff_section, absent_section): Removed. (expr_section): Added (used for dummy symbols which hold intermediate expression values). (perform_an_assembly_pass): Create expr_section, do not create the sections now removed. * as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and SEG_DIFFERENCE. Added SEG_EXPR. (SEG_NORMAL): Corresponding changes. * subsegs.c (seg_name, subsegs_begin): Changed accordingly. * write.c (write_object_file): Ditto. * config/obj-aout.c (seg_N_TYPE): Ditto. * config/obj-bout.c (seg_N_TYPE): Ditto. * config/obj-coff.c (seg_N_TYPE): Ditto. * config/obj-coffbfd.c (seg_N_TYPE): Ditto. * config/obj-vms.c (seg_N_TYPE): Ditto. * expr.h (operatorT): Moved in from expr.c, added some values. (expressionS): Added X_op field, removed X_seg field; renamed X_subtract_symbol to X_op_symbol. * expr.c: Extensive changes to assign expression types rather than sections and to simplify the parsing. * write.c (fix_new_internal): New static function. (fix_new): Removed sub_symbol argument. (fix_new_exp): New function, takes expression argument. * write.h: Prototype changes for fix_new and fix_new_exp. * cond.c (s_if): Changed accordingly. * read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons, parse_repeat_cons, get_segmented_expression, get_known_segmented_expression, get_absolute_expression): Ditto. * symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE): Ditto. * write.c (write_object_file): Ditto. * config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto. * config/obj-coffbfd.c (obj_coff_def, obj_coff_val, obj_coff_endef, yank_symbols): Ditto. * config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto. * config/tc-a29k.c (md_assemble, parse_operand, machine_ip, print_insn, md_operand): Ditto. * config/tc-h8300.c (parse_exp, colonmod24, check_operand, do_a_fix_imm, build_bytes): Ditto. * config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist, get_specific, check, insert, md_convert_frag): Ditto. * config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa, md_assemble, pa_ip, getExpression, getAbsoluteExpression, evaluateAbsolute, pa_build_unwind_subspace, pa_entry, process_exit): Ditto. * config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative, is_complex): Ditto. * config/tc-i386.c (pe, md_assemble, i386_operand, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-i860.c (md_assemble, getExpression, print_insn): Ditto. * config/tc-i960.c (parse_expr, subs, segs, md_convert_frag, get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc, i960_handle_align): Ditto. * config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op, subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1, md_estimate_size_before_relax, md_create_long_jump, get_num): Ditto. * config/tc-m88k.c (md_assemble, get_imm16, get_pcr, md_create_short_jump, md_create_long_jump): Ditto. * config/tc-mips.c (md_assemble, append_insn, gp_reference, macro_build, macro, my_getExpression): Ditto. Also removed get_optional_absolute_expression; just use get_absolute_expression instead. * config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif, fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto. * config/tc-ns32k.h (fix_new_ns32k prototype): Ditto. * config/tc-sh.c (parse_exp, check, insert, md_convert_frag): Ditto. * config/tc-sparc.c (md_assemble, sparc_ip, getExpression, print_insn): Ditto. * config/tc-tahoe.c (struct top, md_estimate_size_before_relax, tip_op, md_assemble): Ditto. * config/tc-vax.c (seg_of_operand, md_assemble, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto.
1993-07-21 00:41:42 +00:00
fix_new_exp (frag_now,
output - frag_now->fr_literal + 1,
1,
&operand[i].exp,
0,
R_RELBYTE);
}
else if (x & ABSMOV)
{
/* This mov is either absolute long or thru a memory loc */
do_a_fix_imm (output - frag_now->fr_literal + immat, operand + i,1);
}
else if (x & ABSJMP)
{
/* This jmp may be a jump or a branch */
check_operand (operand + i, Hmode ? 0xfffff : 0xffff, "@");
if (operand[i].exp.X_add_number & 1)
{
as_warn ("branch operand has odd offset (%x)\n",
operand->exp.X_add_number);
}
1993-07-22 18:02:01 +00:00
operand[i].exp.X_add_number = (short) operand[i].exp.X_add_number;
* Extensive changes to permit symbols to contain any expression type and to delay the computation of the expression until the value is actually needed. This permits setting symbols to values calculated based on object code size. Expressions were changed to no longer be in a section, to stop the overloading of segment and expression type that previously occurred. * as.c (big_section, pass1_section, diff_section, absent_section): Removed. (expr_section): Added (used for dummy symbols which hold intermediate expression values). (perform_an_assembly_pass): Create expr_section, do not create the sections now removed. * as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and SEG_DIFFERENCE. Added SEG_EXPR. (SEG_NORMAL): Corresponding changes. * subsegs.c (seg_name, subsegs_begin): Changed accordingly. * write.c (write_object_file): Ditto. * config/obj-aout.c (seg_N_TYPE): Ditto. * config/obj-bout.c (seg_N_TYPE): Ditto. * config/obj-coff.c (seg_N_TYPE): Ditto. * config/obj-coffbfd.c (seg_N_TYPE): Ditto. * config/obj-vms.c (seg_N_TYPE): Ditto. * expr.h (operatorT): Moved in from expr.c, added some values. (expressionS): Added X_op field, removed X_seg field; renamed X_subtract_symbol to X_op_symbol. * expr.c: Extensive changes to assign expression types rather than sections and to simplify the parsing. * write.c (fix_new_internal): New static function. (fix_new): Removed sub_symbol argument. (fix_new_exp): New function, takes expression argument. * write.h: Prototype changes for fix_new and fix_new_exp. * cond.c (s_if): Changed accordingly. * read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons, parse_repeat_cons, get_segmented_expression, get_known_segmented_expression, get_absolute_expression): Ditto. * symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE): Ditto. * write.c (write_object_file): Ditto. * config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto. * config/obj-coffbfd.c (obj_coff_def, obj_coff_val, obj_coff_endef, yank_symbols): Ditto. * config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto. * config/tc-a29k.c (md_assemble, parse_operand, machine_ip, print_insn, md_operand): Ditto. * config/tc-h8300.c (parse_exp, colonmod24, check_operand, do_a_fix_imm, build_bytes): Ditto. * config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist, get_specific, check, insert, md_convert_frag): Ditto. * config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa, md_assemble, pa_ip, getExpression, getAbsoluteExpression, evaluateAbsolute, pa_build_unwind_subspace, pa_entry, process_exit): Ditto. * config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative, is_complex): Ditto. * config/tc-i386.c (pe, md_assemble, i386_operand, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-i860.c (md_assemble, getExpression, print_insn): Ditto. * config/tc-i960.c (parse_expr, subs, segs, md_convert_frag, get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc, i960_handle_align): Ditto. * config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op, subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1, md_estimate_size_before_relax, md_create_long_jump, get_num): Ditto. * config/tc-m88k.c (md_assemble, get_imm16, get_pcr, md_create_short_jump, md_create_long_jump): Ditto. * config/tc-mips.c (md_assemble, append_insn, gp_reference, macro_build, macro, my_getExpression): Ditto. Also removed get_optional_absolute_expression; just use get_absolute_expression instead. * config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif, fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto. * config/tc-ns32k.h (fix_new_ns32k prototype): Ditto. * config/tc-sh.c (parse_exp, check, insert, md_convert_frag): Ditto. * config/tc-sparc.c (md_assemble, sparc_ip, getExpression, print_insn): Ditto. * config/tc-tahoe.c (struct top, md_estimate_size_before_relax, tip_op, md_assemble): Ditto. * config/tc-vax.c (seg_of_operand, md_assemble, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto.
1993-07-21 00:41:42 +00:00
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
DEFUN (clever_message, (opcode, operand),
struct h8_opcode *opcode AND
struct h8_op *operand)
{
struct h8_opcode *scan = opcode;
/* 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");
}
1991-10-06 19:02:50 +00:00
/* 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.
*/
1991-10-06 19:02:50 +00:00
void
DEFUN (md_assemble, (str),
char *str)
1991-10-06 19:02:50 +00:00
{
char *op_start;
char *op_end;
unsigned int i;
struct h8_op operand[2];
struct h8_opcode *opcode;
struct h8_opcode *prev_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++)
{
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;
}
input_line_pointer = get_operands (opcode->noperands, op_end,
operand);
*op_end = c;
prev_opcode = opcode;
opcode = get_specific (opcode, operand);
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);
1991-10-06 19:02:50 +00:00
}
void
DEFUN (tc_crawl_symbol_chain, (headers),
object_headers * headers)
1991-10-06 19:02:50 +00:00
{
printf ("call to tc_crawl_symbol_chain \n");
1991-10-06 19:02:50 +00:00
}
symbolS *
DEFUN (md_undefined_symbol, (name),
char *name)
1991-10-06 19:02:50 +00:00
{
return 0;
1991-10-06 19:02:50 +00:00
}
void
DEFUN (tc_headers_hook, (headers),
object_headers * headers)
1991-10-06 19:02:50 +00:00
{
printf ("call to tc_headers_hook \n");
1991-10-06 19:02:50 +00:00
}
1991-10-06 19:02:50 +00:00
void
DEFUN_VOID (md_end)
1991-10-06 19:02:50 +00:00
{
}
/* 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 "";
}
int
md_parse_option (argP, cntP, vecP)
char **argP;
int *cntP;
char ***vecP;
{
return 0;
}
1991-10-06 19:02:50 +00:00
int md_short_jump_size;
void
tc_aout_fix_to_chars ()
{
printf ("call to tc_aout_fix_to_chars \n");
abort ();
}
void
md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
char *ptr;
addressT from_addr;
addressT to_addr;
fragS *frag;
symbolS *to_symbol;
{
as_fatal ("failed sanity check.");
}
void
md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
char *ptr;
addressT from_addr, to_addr;
fragS *frag;
symbolS *to_symbol;
{
as_fatal ("failed sanity check.");
}
void
md_convert_frag (headers, fragP)
object_headers *headers;
fragS *fragP;
{
printf ("call to md_convert_frag \n");
abort ();
}
1991-10-06 19:02:50 +00:00
1993-07-13 19:13:18 +00:00
valueT md_section_align (seg, size)
segT seg;
valueT size;
1991-10-06 19:02:50 +00:00
{
return ((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg]));
1991-10-06 19:02:50 +00:00
}
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 ();
}
}
1991-10-06 19:02:50 +00:00
void
DEFUN (md_operand, (expressionP), expressionS * expressionP)
{
}
1991-10-06 19:02:50 +00:00
int md_long_jump_size;
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 ();
}
1991-10-06 19:02:50 +00:00
/* Put number into target byte order */
void
DEFUN (md_number_to_chars, (ptr, use, nbytes),
char *ptr AND
valueT use AND
int nbytes)
1991-10-06 19:02:50 +00:00
{
switch (nbytes)
{
case 4:
*ptr++ = (use >> 24) & 0xff;
case 3:
*ptr++ = (use >> 16) & 0xff;
case 2:
*ptr++ = (use >> 8) & 0xff;
case 1:
*ptr++ = (use >> 0) & 0xff;
break;
default:
abort ();
}
}
long
md_pcrel_from (fixP)
fixS *fixP;
{
abort ();
1991-10-06 19:02:50 +00:00
}
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;
}
tc_coff_sizemachdep ()
{
abort ();
}
/* end of tc-h8300.c */