From 3c9b82baee30a1d3cfeb419643c6363dc9267208 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 25 Oct 2005 17:40:19 +0000 Subject: Add support for the Z80 processor family --- gas/ChangeLog | 17 + gas/Makefile.am | 3 + gas/Makefile.in | 3 + gas/app.c | 54 + gas/config/obj-coff.h | 5 + gas/config/tc-z80.c | 2061 +++++++++++++++++++++++++++++++++++ gas/config/tc-z80.h | 103 ++ gas/configure.tgt | 4 +- gas/doc/Makefile.am | 1 + gas/doc/Makefile.in | 7 +- gas/doc/all.texi | 1 + gas/doc/as.texinfo | 64 ++ gas/doc/c-z80.texi | 248 +++++ gas/testsuite/ChangeLog | 13 + gas/testsuite/gas/all/gas.exp | 26 +- gas/testsuite/gas/macros/macros.exp | 2 + gas/testsuite/gas/z80/quotes.d | 9 + gas/testsuite/gas/z80/quotes.s | 11 + gas/testsuite/gas/z80/redef.d | 8 + gas/testsuite/gas/z80/redef.s | 11 + gas/testsuite/gas/z80/z80.exp | 10 + 21 files changed, 2649 insertions(+), 12 deletions(-) create mode 100644 gas/config/tc-z80.c create mode 100644 gas/config/tc-z80.h create mode 100644 gas/doc/c-z80.texi create mode 100644 gas/testsuite/gas/z80/quotes.d create mode 100644 gas/testsuite/gas/z80/quotes.s create mode 100644 gas/testsuite/gas/z80/redef.d create mode 100644 gas/testsuite/gas/z80/redef.s create mode 100644 gas/testsuite/gas/z80/z80.exp (limited to 'gas') diff --git a/gas/ChangeLog b/gas/ChangeLog index 2ff1e50..58816b9 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,20 @@ +2005-10-25 Arnold Metselaar + + * Makefile.am: Add Z80 cpu. + * Makefile.in: Regenerated. + * app.c (do_scrub_chars): Correctly scrub "ex af,af'" + and disallow newlines in quoted strings. + * configure.tgt: Add z80-*-coff. + * config/obj-coff.h: Add format "coff-z80". + * doc/Makefile.am: Add c-z80.texi. + * doc/Makefile.in: Regenerated. + * doc/all.texi: Add Z80. + * doc/c-z80.texi: New file + * doc/as.texinfo: Add z80 options and some z80-related remarks. + * config/tc-z80.c: New file + * config/tc-z80.h: New file + * NEWS: Mention new support. + 2005-10-25 H.J. Lu * write.c (adjust_reloc_syms): Undo the change made on diff --git a/gas/Makefile.am b/gas/Makefile.am index e373978..0867a9a 100644 --- a/gas/Makefile.am +++ b/gas/Makefile.am @@ -88,6 +88,7 @@ CPU_TYPES = \ v850 \ xstormy16 \ xtensa \ + z80 \ z8k # Object format types. This is only used for dependency information. @@ -270,6 +271,7 @@ TARGET_CPU_CFILES = \ config/tc-v850.c \ config/tc-xstormy16.c \ config/tc-xtensa.c \ + config/tc-z80.c \ config/tc-z8k.c TARGET_CPU_HFILES = \ @@ -319,6 +321,7 @@ TARGET_CPU_HFILES = \ config/tc-v850.h \ config/tc-xstormy16.h \ config/tc-xtensa.h \ + config/tc-z80.h \ config/tc-z8k.h # OBJ files in config diff --git a/gas/Makefile.in b/gas/Makefile.in index 4a8c274..c8a3492 100644 --- a/gas/Makefile.in +++ b/gas/Makefile.in @@ -318,6 +318,7 @@ CPU_TYPES = \ v850 \ xstormy16 \ xtensa \ + z80 \ z8k @@ -498,6 +499,7 @@ TARGET_CPU_CFILES = \ config/tc-v850.c \ config/tc-xstormy16.c \ config/tc-xtensa.c \ + config/tc-z80.c \ config/tc-z8k.c TARGET_CPU_HFILES = \ @@ -547,6 +549,7 @@ TARGET_CPU_HFILES = \ config/tc-v850.h \ config/tc-xstormy16.h \ config/tc-xtensa.h \ + config/tc-z80.h \ config/tc-z8k.h diff --git a/gas/app.c b/gas/app.c index 14f2f14..3ff7f61 100644 --- a/gas/app.c +++ b/gas/app.c @@ -376,6 +376,10 @@ do_scrub_chars (int (*get) (char *, int), char *tostart, int tolen) 15: After seeing a `(' at state 1, looking for a `)' as predicate. #endif +#ifdef TC_Z80 + 16: After seeing an 'a' or an 'A' at the start of a symbol + 17: After seeing an 'f' or an 'F' in state 16 +#endif */ /* I added states 9 and 10 because the MIPS ECOFF assembler uses @@ -665,6 +669,32 @@ do_scrub_chars (int (*get) (char *, int), char *tostart, int tolen) PUT ('|'); continue; #endif +#ifdef TC_Z80 + case 16: + /* We have seen an 'a' at the start of a symbol, look for an 'f'. */ + ch = GET (); + if (ch == 'f' || ch == 'F') + { + state = 17; + PUT (ch); + } + else + { + state = 9; + break; + } + case 17: + /* We have seen "af" at the start of a symbol, + a ' here is a part of that symbol. */ + ch = GET (); + state = 9; + if (ch == '\'') + /* Change to avoid warning about unclosed string. */ + PUT ('`'); + else + UNGET (ch); + break; +#endif } /* OK, we are somewhere in states 0 through 4 or 9 through 11. */ @@ -1242,6 +1272,30 @@ do_scrub_chars (int (*get) (char *, int), char *tostart, int tolen) break; } +#ifdef TC_Z80 + /* "af'" is a symbol containing '\''. */ + if (state == 3 && (ch == 'a' || ch == 'A')) + { + state = 16; + PUT (ch); + ch = GET (); + if (ch == 'f' || ch == 'F') + { + state = 17; + PUT (ch); + break; + } + else + { + state = 9; + if (!IS_SYMBOL_COMPONENT (ch)) + { + UNGET (ch); + break; + } + } + } +#endif if (state == 3) state = 9; diff --git a/gas/config/obj-coff.h b/gas/config/obj-coff.h index 81577c8..4c7c68d 100644 --- a/gas/config/obj-coff.h +++ b/gas/config/obj-coff.h @@ -85,6 +85,11 @@ #define TARGET_FORMAT "coff-Intel-little" #endif +#ifdef TC_Z80 +#include "coff/z80.h" +#define TARGET_FORMAT "coff-z80" +#endif + #ifdef TC_Z8K #include "coff/z8k.h" #define TARGET_FORMAT "coff-z8k" diff --git a/gas/config/tc-z80.c b/gas/config/tc-z80.c new file mode 100644 index 0000000..28f69b1 --- /dev/null +++ b/gas/config/tc-z80.c @@ -0,0 +1,2061 @@ +/* tc-z80.c -- Assemble code for the Zilog Z80 and ASCII R800 + Copyright 2005 Free Software Foundation, Inc. + Contributed by Arnold Metselaar + + 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, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include "as.h" +#include "listing.h" +#include "bfd.h" +#include "safe-ctype.h" +#include "subsegs.h" +#include "symbols.h" +#include "libiberty.h" + +/* Exported constants. */ +const char comment_chars[] = ";\0"; +const char line_comment_chars[] = "#;\0"; +const char line_separator_chars[] = "\0"; +const char EXP_CHARS[] = "eE\0"; +const char FLT_CHARS[] = "RrFf\0"; + +/* For machine specific options. */ +const char * md_shortopts = ""; /* None yet. */ + +enum options +{ + OPTION_MACH_Z80 = OPTION_MD_BASE, + OPTION_MACH_R800, + OPTION_MACH_IUD, + OPTION_MACH_WUD, + OPTION_MACH_FUD, + OPTION_MACH_IUP, + OPTION_MACH_WUP, + OPTION_MACH_FUP +}; + +#define INS_Z80 1 +#define INS_UNDOC 2 +#define INS_UNPORT 4 +#define INS_R800 8 + +struct option md_longopts[] = +{ + { "z80", no_argument, NULL, OPTION_MACH_Z80}, + { "r800", no_argument, NULL, OPTION_MACH_R800}, + { "ignore-undocumented-instructions", no_argument, NULL, OPTION_MACH_IUD }, + { "Wnud", no_argument, NULL, OPTION_MACH_IUD }, + { "warn-undocumented-instructions", no_argument, NULL, OPTION_MACH_WUD }, + { "Wud", no_argument, NULL, OPTION_MACH_WUD }, + { "forbid-undocumented-instructions", no_argument, NULL, OPTION_MACH_FUD }, + { "Fud", no_argument, NULL, OPTION_MACH_FUD }, + { "ignore-unportable-instructions", no_argument, NULL, OPTION_MACH_IUP }, + { "Wnup", no_argument, NULL, OPTION_MACH_IUP }, + { "warn-unportable-instructions", no_argument, NULL, OPTION_MACH_WUP }, + { "Wup", no_argument, NULL, OPTION_MACH_WUP }, + { "forbid-unportable-instructions", no_argument, NULL, OPTION_MACH_FUP }, + { "Fup", no_argument, NULL, OPTION_MACH_FUP }, + + { NULL, no_argument, NULL, 0 } +} ; + +size_t md_longopts_size = sizeof (md_longopts); + +extern int coff_flags; +/* Instruction classes that silently assembled. */ +static int ins_ok = INS_Z80 | INS_UNDOC; +/* Instruction classes that generate errors. */ +static int ins_err = INS_R800; +/* Instruction classes actually used, determines machine type. */ +static int ins_used = INS_Z80; + +int +md_parse_option (int c, char* arg ATTRIBUTE_UNUSED) +{ + switch (c) + { + default: + return 0; + case OPTION_MACH_Z80: + ins_ok &= ~INS_R800; + ins_err |= INS_R800; + break; + case OPTION_MACH_R800: + ins_ok = INS_Z80 | INS_UNDOC | INS_R800; + ins_err = INS_UNPORT; + break; + case OPTION_MACH_IUD: + ins_ok |= INS_UNDOC; + ins_err &= ~INS_UNDOC; + break; + case OPTION_MACH_IUP: + ins_ok |= INS_UNDOC | INS_UNPORT; + ins_err &= ~(INS_UNDOC | INS_UNPORT); + break; + case OPTION_MACH_WUD: + if ((ins_ok & INS_R800) == 0) + { + ins_ok &= ~(INS_UNDOC|INS_UNPORT); + ins_err &= ~INS_UNDOC; + } + break; + case OPTION_MACH_WUP: + ins_ok &= ~INS_UNPORT; + ins_err &= ~(INS_UNDOC|INS_UNPORT); + break; + case OPTION_MACH_FUD: + if ((ins_ok & INS_R800) == 0) + { + ins_ok &= (INS_UNDOC | INS_UNPORT); + ins_err |= INS_UNDOC | INS_UNPORT; + } + break; + case OPTION_MACH_FUP: + ins_ok &= ~INS_UNPORT; + ins_err |= INS_UNPORT; + break; + } + + return 1; +} + +void +md_show_usage (FILE * f) +{ + fprintf (f, "\n\ +CPU model/instruction set options:\n\ +\n\ + -z80\t\t assemble for Z80\n\ + -ignore-undocumented-instructions\n\ + -Wnud\n\ +\tsilently assemble undocumented Z80-instructions that work on R800\n\ + -ignore-unportable-instructions\n\ + -Wnup\n\ +\tsilently assemble all undocumented Z80-instructions\n\ + -warn-undocumented-instructions\n\ + -Wud\n\ +\tissue warnings for undocumented Z80-instructions that work on R800\n\ + -warn-unportable-instructions\n\ + -Wup\n\ +\tissue warnings for other undocumented Z80-instructions\n\ + -forbid-undocumented-instructions\n\ + -Fud\n\ +\ttreat all undocumented z80-instructions as errors\n\ + -forbid-unportable-instructions\n\ + -Fup\n\ +\ttreat undocumented z80-instructions that do not work on R800 as errors\n\ + -r800\t assemble for R800\n\n\ +Default: -z80 -ignore-undocument-instructions -warn-unportable-instructions.\n"); +} + +static symbolS * zero; + +void +md_begin (void) +{ + expressionS nul; + char * p; + + p = input_line_pointer; + input_line_pointer = "0"; + nul.X_md=0; + expression (& nul); + input_line_pointer = p; + zero = make_expr_symbol (& nul); + /* We do not use relaxation (yet). */ + linkrelax = 0; +} + +void +z80_md_end (void) +{ + int mach_type; + + if (ins_used & (INS_UNPORT | INS_R800)) + ins_used |= INS_UNDOC; + + switch (ins_used) + { + case INS_Z80: + mach_type = bfd_mach_z80strict; + break; + case INS_Z80|INS_UNDOC: + mach_type = bfd_mach_z80; + break; + case INS_Z80|INS_UNDOC|INS_UNPORT: + mach_type = bfd_mach_z80full; + break; + case INS_Z80|INS_UNDOC|INS_R800: + mach_type = bfd_mach_r800; + break; + default: + mach_type = 0; + } + + 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) +{ + while (*s == ' ' || *s == '\t') + ++s; + return s; +} + +/* A non-zero return-value causes a continue in the + function read_a_source_file () in ../read.c. */ +int +z80_start_line_hook (void) +{ + char *p, quote; + char buf[4]; + + /* Convert one character constants. */ + for (p = input_line_pointer; *p && *p != '\n'; ++p) + { + switch (*p) + { + case '\'': + if (p[1] != 0 && p[1] != '\'' && p[2] == '\'') + { + snprintf (buf, 4, "%3d", (unsigned char)p[1]); + *p++ = buf[0]; + *p++ = buf[1]; + *p++ = buf[2]; + break; + } + case '"': + for (quote = *p++; quote != *p && '\n' != *p; ++p) + /* No escapes. */ ; + if (quote != *p) + { + as_bad (_("-- unterminated string")); + ignore_rest_of_line (); + return 1; + } + break; + } + } + /* Check for