diff options
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/coff-z80.c | 21 | ||||
-rw-r--r-- | gas/ChangeLog | 18 | ||||
-rw-r--r-- | gas/config/tc-z80.c | 173 | ||||
-rw-r--r-- | gas/config/tc-z80.h | 2 | ||||
-rw-r--r-- | gas/doc/c-z80.texi | 14 | ||||
-rw-r--r-- | include/coff/ChangeLog | 4 | ||||
-rw-r--r-- | include/coff/internal.h | 1 |
8 files changed, 167 insertions, 73 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f2ca17d..4dcd1e7 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2006-02-05 Arnold Metselaar <arnold.metselaar@planet.nl> + + * coff-z80.c (r_imm24): New howto. + (rtype2howto): New case R_IMM24. + (coff_z80_reloc_type_lookup): New case BFD_RELOC_24. + (extra_case): Use bfd_get_8 for R_IMM8, new case R_IMM24. + 2006-02-04 Richard Sandiford <richard@codesourcery.com> * elfxx-mips.c (mips_elf_initialize_tls_index): If a TLS symbol diff --git a/bfd/coff-z80.c b/bfd/coff-z80.c index f39413f..512c2b8 100644 --- a/bfd/coff-z80.c +++ b/bfd/coff-z80.c @@ -34,6 +34,11 @@ HOWTO (R_IMM32, 0, 1, 32, FALSE, 0, complain_overflow_dont, 0, "r_imm32", TRUE, 0xffffffff, 0xffffffff, FALSE); +static reloc_howto_type r_imm24 = +HOWTO (R_IMM24, 0, 1, 24, FALSE, 0, + complain_overflow_dont, 0, "r_imm24", TRUE, 0x00ffffff, 0x00ffffff, + FALSE); + static reloc_howto_type r_imm16 = HOWTO (R_IMM16, 0, 1, 16, FALSE, 0, complain_overflow_dont, 0, "r_imm16", TRUE, 0x0000ffff, 0x0000ffff, @@ -84,6 +89,9 @@ rtype2howto (arelent *internal, struct internal_reloc *dst) case R_IMM16: internal->howto = &r_imm16; break; + case R_IMM24: + internal->howto = &r_imm24; + break; case R_IMM32: internal->howto = &r_imm32; break; @@ -106,6 +114,7 @@ coff_z80_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, { case BFD_RELOC_8: return & r_imm8; case BFD_RELOC_16: return & r_imm16; + case BFD_RELOC_24: return & r_imm24; case BFD_RELOC_32: return & r_imm32; case BFD_RELOC_8_PCREL: return & r_jr; case BFD_RELOC_Z80_DISP8: return & r_off8; @@ -173,7 +182,7 @@ extra_case (bfd *in_abfd, break; case R_IMM8: - val = bfd_get_16 ( in_abfd, data+*src_ptr) + val = bfd_get_8 ( in_abfd, data+*src_ptr) + bfd_coff_reloc16_get_value (reloc, link_info, input_section); bfd_put_8 (in_abfd, val, data + *dst_ptr); (*dst_ptr) += 1; @@ -188,6 +197,16 @@ extra_case (bfd *in_abfd, (*src_ptr) += 2; break; + case R_IMM24: + val = bfd_get_16 ( in_abfd, data+*src_ptr) + + (bfd_get_8 ( in_abfd, data+*src_ptr+2) << 16) + + bfd_coff_reloc16_get_value (reloc, link_info, input_section); + bfd_put_16 (in_abfd, val, data + *dst_ptr); + bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr+2); + (*dst_ptr) += 3; + (*src_ptr) += 3; + break; + case R_IMM32: val = bfd_get_32 ( in_abfd, data+*src_ptr) + bfd_coff_reloc16_get_value (reloc, link_info, input_section); diff --git a/gas/ChangeLog b/gas/ChangeLog index ca85d59..0247c82 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,21 @@ +2006-02-05 Arnold Metselaar <arnold.metselaar@planet.nl> + + * config/tc-z80.c (z80_start_line_hook): allow .equ and .defl as + synonyms for equ and defl. + (z80_cons_fix_new): New function. + (emit_byte): Disallow relative jumps to absolute locations. + (emit_data): Only handle defb, prototype changed, because defb is + now handled as pseudo-op rather than an instruction. + (instab): Entries for defb,defw,db,dw moved from here... + (md_pseudo_table): ... to here, use generic cons() for defw,dw. + Add entries for def24,def32,d24,d32. + (md_assemble): Improved error handling. + (md_apply_fix): New case BFD_RELOC_24, set fixP->fx_no_overflow to one. + * config/tc-z80.h (TC_CONS_FIX_NEW): Define. + (z80_cons_fix_new): Declare. + * doc/c-z80.texi (defb, db): Mention warning on overflow. + (def24,d24,def32,d32): New pseudo-ops. + 2006-02-02 Paul Brook <paul@codesourcery.com> * config/tc-arm.c (do_shift): Remove Thumb-1 constraint. diff --git a/gas/config/tc-z80.c b/gas/config/tc-z80.c index 7aabb8e..76d46f5 100644 --- a/gas/config/tc-z80.c +++ b/gas/config/tc-z80.c @@ -210,16 +210,6 @@ z80_md_end (void) bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach_type); } -/* Port specific features. */ -const pseudo_typeS md_pseudo_table[] = -{ - { "defs", s_space, 1}, /* Synonym for ds on some assemblers. */ - { "ds", s_space, 1}, /* Fill with bytes rather than words. */ - { "psect", obj_coff_section, 0}, /* TODO: Translate attributes. */ - { "set", 0, 0}, /* Real instruction on z80. */ - { NULL, 0, 0 } -} ; - static const char * skip_space (const char *s) { @@ -262,7 +252,7 @@ z80_start_line_hook (void) break; } } - /* Check for <label>[:] (EQU|DEFL) <value>. */ + /* Check for <label>[:] [.](EQU|DEFL) <value>. */ if (is_name_beginner (*input_line_pointer)) { char c, *rest, *line_start; @@ -281,6 +271,8 @@ z80_start_line_hook (void) ++rest; if (*rest == ' ' || *rest == '\t') ++rest; + if (*rest == '.') + ++rest; if (strncasecmp (rest, "EQU", 3) == 0) len = 3; else if (strncasecmp (rest, "DEFL", 4) == 0) @@ -300,7 +292,6 @@ z80_start_line_hook (void) if (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP)) as_bad (_("symbol `%s' is already defined"), line_start); } - /* All symbols may be redefined. */ equals (line_start, 1); return 1; } @@ -452,7 +443,7 @@ wrong_mach (int ins_type) p = "instruction only works R800"; break; default: - p = 0; /* Not reachables. */ + p = 0; /* Not reachable. */ } if (ins_type & ins_err) @@ -733,6 +724,26 @@ emit_insn (char prefix, char opcode, const char * args) return args; } +void z80_cons_fix_new (fragS *frag_p, int offset, int nbytes, expressionS *exp) +{ + bfd_reloc_code_real_type r[4] = + { + BFD_RELOC_8, + BFD_RELOC_16, + BFD_RELOC_24, + BFD_RELOC_32 + }; + + if (nbytes < 1 || nbytes > 4) + { + as_bad (_("unsupported BFD relocation size %u"), nbytes); + } + else + { + fix_new_exp (frag_p, offset, nbytes, exp, 0, r[nbytes-1]); + } +} + static void emit_byte (expressionS * val, bfd_reloc_code_real_type r_type) { @@ -742,7 +753,11 @@ emit_byte (expressionS * val, bfd_reloc_code_real_type r_type) p = frag_more (1); *p = val->X_add_number; - if ((r_type != BFD_RELOC_8_PCREL) && (val->X_op == O_constant)) + if ((r_type == BFD_RELOC_8_PCREL) && (val->X_op == O_constant)) + { + as_bad(_("cannot make a relative jump to an absolute location")); + } + else if (val->X_op == O_constant) { lo = -128; hi = (BFD_RELOC_8 == r_type) ? 255 : 127; @@ -1717,38 +1732,33 @@ emit_ld (char prefix_in ATTRIBUTE_UNUSED, char opcode_in ATTRIBUTE_UNUSED, return p; } -static const char * -emit_data (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args) +static void +emit_data (int size ATTRIBUTE_UNUSED) { const char *p, *q; char *u, quote; int cnt; expressionS exp; - p = skip_space (args); - if (!*p) - error (_("missing operand")); + if (is_it_end_of_statement ()) + { + demand_empty_rest_of_line (); + return; + } + p = skip_space (input_line_pointer); - while (*p) + do { if (*p == '\"' || *p == '\'') { - if (opcode == 1) - { - for (quote = *p, q = ++p, cnt = 0; *p && quote != *p; ++p, ++cnt) - ; - u = frag_more (cnt); - memcpy (u, q, cnt); - if (!*p) - as_warn (_("unterminated string")); - else - p = skip_space (p+1); - } - else - { - ill_op (); - break; - } + for (quote = *p, q = ++p, cnt = 0; *p && quote != *p; ++p, ++cnt) + ; + u = frag_more (cnt); + memcpy (u, q, cnt); + if (!*p) + as_warn (_("unterminated string")); + else + p = skip_space (p+1); } else { @@ -1760,21 +1770,12 @@ emit_data (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args) } if (exp.X_md) as_warn (_("parentheses ignored")); - if (opcode == 1) - emit_byte (&exp, BFD_RELOC_8); - else - emit_word (&exp); + emit_byte (&exp, BFD_RELOC_8); p = skip_space (p); } - if (*p) - { - if (*p != ',') - as_warn (_("missing ','")); - else - ++p; - } } - return p; + while (*p++ == ',') ; + input_line_pointer = (char *)(p-1); } static const char * @@ -1843,6 +1844,24 @@ emit_muluw (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args) return p; } +/* Port specific pseudo ops. */ +const pseudo_typeS md_pseudo_table[] = +{ + { "db" , emit_data, 1}, + { "d24", cons, 3}, + { "d32", cons, 4}, + { "def24", cons, 3}, + { "def32", cons, 4}, + { "defb", emit_data, 1}, + { "defs", s_space, 1}, /* Synonym for ds on some assemblers. */ + { "defw", cons, 2}, + { "ds", s_space, 1}, /* Fill with bytes rather than words. */ + { "dw", cons, 2}, + { "psect", obj_coff_section, 0}, /* TODO: Translate attributes. */ + { "set", 0, 0}, /* Real instruction on z80. */ + { NULL, 0, 0 } +} ; + static table_t instab[] = { { "adc", 0x88, 0x4A, emit_adc }, @@ -1858,13 +1877,9 @@ static table_t instab[] = { "cpir", 0xED, 0xB1, emit_insn }, { "cpl", 0x00, 0x2F, emit_insn }, { "daa", 0x00, 0x27, emit_insn }, - { "db", 0x00, 0x01, emit_data }, { "dec", 0x0B, 0x05, emit_incdec }, - { "defb", 0x00, 0x01, emit_data }, - { "defw", 0x00, 0x02, emit_data }, { "di", 0x00, 0xF3, emit_insn }, { "djnz", 0x00, 0x10, emit_jr }, - { "dw", 0x00, 0x02, emit_data }, { "ei", 0x00, 0xFB, emit_insn }, { "ex", 0x00, 0x00, emit_ex}, { "exx", 0x00, 0xD9, emit_insn }, @@ -1936,25 +1951,32 @@ md_assemble (char* str) for (i = 0; (i < BUFLEN) && (ISALPHA (*p));) buf[i++] = TOLOWER (*p++); - if ((i == BUFLEN) - || ((*p) && (!ISSPACE (*p)))) - as_bad (_("illegal instruction '%s'"), buf); - - buf[i] = 0; - p = skip_space (p); - key = buf; - - insp = bsearch (&key, instab, ARRAY_SIZE (instab), - sizeof (instab[0]), key_cmp); - if (!insp) - as_bad (_("illegal instruction '%s'"), buf); - else + if (i == BUFLEN) + { + buf[BUFLEN-3] = buf[BUFLEN-2] = '.'; /* Mark opcode as abbreviated. */ + buf[BUFLEN-1] = 0; + as_bad (_("Unknown instruction '%s'"), buf); + } + else if ((*p) && (!ISSPACE (*p))) + as_bad (_("syntax error")); + else { - p = insp->fp (insp->prefix, insp->opcode, p); + buf[i] = 0; p = skip_space (p); - if ((!err_flag) && *p) - as_bad (_("junk at end of line, first unrecognized character is `%c'"), - *p); + key = buf; + + insp = bsearch (&key, instab, ARRAY_SIZE (instab), + sizeof (instab[0]), key_cmp); + if (!insp) + as_bad (_("Unknown instruction '%s'"), buf); + else + { + p = insp->fp (insp->prefix, insp->opcode, p); + p = skip_space (p); + if ((!err_flag) && *p) + as_bad (_("junk at end of line, first unrecognized character is `%c'"), + *p); + } } input_line_pointer = old_ptr; } @@ -2005,6 +2027,7 @@ md_apply_fix (fixS * fixP, valueT* valP, segT seg ATTRIBUTE_UNUSED) if (val > 255 || val < -128) as_warn_where (fixP->fx_file, fixP->fx_line, _("overflow")); *buf++ = val; + fixP->fx_no_overflow = 1; if (fixP->fx_addsy == NULL) fixP->fx_done = 1; break; @@ -2012,11 +2035,21 @@ md_apply_fix (fixS * fixP, valueT* valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_16: *buf++ = val; *buf++ = (val >> 8); + fixP->fx_no_overflow = 1; + if (fixP->fx_addsy == NULL) + fixP->fx_done = 1; + break; + + case BFD_RELOC_24: /* Def24 may produce this. */ + *buf++ = val; + *buf++ = (val >> 8); + *buf++ = (val >> 16); + fixP->fx_no_overflow = 1; if (fixP->fx_addsy == NULL) fixP->fx_done = 1; break; - case BFD_RELOC_32: /* .Long may produce this. */ + case BFD_RELOC_32: /* Def32 and .long may produce this. */ *buf++ = val; *buf++ = (val >> 8); *buf++ = (val >> 16); diff --git a/gas/config/tc-z80.h b/gas/config/tc-z80.h index ff2c640..0ae318a 100644 --- a/gas/config/tc-z80.h +++ b/gas/config/tc-z80.h @@ -56,10 +56,12 @@ #define md_end z80_md_end #define md_start_line_hook() { if (z80_start_line_hook ()) continue; } #define md_optimize_expr z80_optimize_expr +#define TC_CONS_FIX_NEW z80_cons_fix_new extern void z80_md_end (void); extern int z80_start_line_hook (void); extern int z80_optimize_expr (expressionS *, operatorT, expressionS *); +extern void z80_cons_fix_new (fragS *, int, int, expressionS *); #define WORKING_DOT_WORD diff --git a/gas/doc/c-z80.texi b/gas/doc/c-z80.texi index c3e64bf..76e8410 100644 --- a/gas/doc/c-z80.texi +++ b/gas/doc/c-z80.texi @@ -150,14 +150,24 @@ These are the additional directives in @code{@value{AS}} for the Z80: @item db @var{expression}|@var{string}[,@var{expression}|@var{string}...] @itemx defb @var{expression}|@var{string}[,@var{expression}|@var{string}...] For each @var{string} the characters are copied to the object file, for -each other @var{expression} the value is stored in one byte, ignoring -overflow. +each other @var{expression} the value is stored in one byte. +A warning is issued in case of an overflow. @item dw @var{expression}[,@var{expression}...] @itemx defw @var{expression}[,@var{expression}...] For each @var{expression} the value is stored in two bytes, ignoring overflow. +@item d24 @var{expression}[,@var{expression}...] +@itemx def24 @var{expression}[,@var{expression}...] +For each @var{expression} the value is stored in three bytes, ignoring +overflow. + +@item d32 @var{expression}[,@var{expression}...] +@itemx def32 @var{expression}[,@var{expression}...] +For each @var{expression} the value is stored in four bytes, ignoring +overflow. + @item ds @var{count}[, @var{value}] @itemx defs @var{count}[, @var{value}] @c Synonyms for @code{ds.b}, diff --git a/include/coff/ChangeLog b/include/coff/ChangeLog index a8b66cc..f41c115 100644 --- a/include/coff/ChangeLog +++ b/include/coff/ChangeLog @@ -1,3 +1,7 @@ +2006-02-05 Arnold Metselaar <arnold.metselaar@planet.nl> + + * internal.h: Add relocation number R_IMM24 for Z80. + 2005-10-25 Arnold Metselaar <arnold.metselaar@planet.nl> * internal.h: Add relocation number for Z80 diff --git a/include/coff/internal.h b/include/coff/internal.h index d7a8381..ed0918a 100644 --- a/include/coff/internal.h +++ b/include/coff/internal.h @@ -717,6 +717,7 @@ struct internal_reloc /* Z80 modes */ #define R_OFF8 0x32 /* 8 bit signed abs, for (i[xy]+d) */ +#define R_IMM24 0x33 /* 24 bit abs */ /* R_JR, R_IMM8, R_IMM16, R_IMM32 - as for Z8k */ /* H8500 modes */ |