summaryrefslogtreecommitdiff
path: root/src/z80/main.c
diff options
context:
space:
mode:
authorXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
committerXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
commit268a53de823a6750d6256ee1fb1e7707b4b45740 (patch)
tree42c1799a9a82b2f7d9790ee9fe181d72a7274751 /src/z80/main.c
downloadsdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'src/z80/main.c')
-rw-r--r--src/z80/main.c1758
1 files changed, 1758 insertions, 0 deletions
diff --git a/src/z80/main.c b/src/z80/main.c
new file mode 100644
index 0000000..a96493e
--- /dev/null
+++ b/src/z80/main.c
@@ -0,0 +1,1758 @@
+/*-------------------------------------------------------------------------
+ main.c - Z80 specific definitions.
+
+ Michael Hope <michaelh@juju.net.nz> 2001
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding!
+-------------------------------------------------------------------------*/
+
+#include <sys/stat.h>
+#include "z80.h"
+#include "SDCCsystem.h"
+#include "SDCCutil.h"
+#include "SDCCargs.h"
+#include "dbuf_string.h"
+
+#define OPTION_BO "-bo"
+#define OPTION_BA "-ba"
+#define OPTION_CODE_SEG "--codeseg"
+#define OPTION_CONST_SEG "--constseg"
+#define OPTION_DATA_SEG "--dataseg"
+#define OPTION_CALLEE_SAVES_BC "--callee-saves-bc"
+#define OPTION_PORTMODE "--portmode="
+#define OPTION_ASM "--asm="
+#define OPTION_NO_STD_CRT0 "--no-std-crt0"
+#define OPTION_RESERVE_IY "--reserve-regs-iy"
+#define OPTION_OLDRALLOC "--oldralloc"
+#define OPTION_FRAMEPOINTER "--fno-omit-frame-pointer"
+#define OPTION_EMIT_EXTERNS "--emit-externs"
+
+static char _z80_defaultRules[] = {
+#include "peeph.rul"
+#include "peeph-z80.rul"
+};
+
+static char _r2k_defaultRules[] = {
+#include "peeph.rul"
+#include "peeph-r2k.rul"
+};
+
+static char _tlcs90_defaultRules[] = {
+#include "peeph.rul"
+#include "peeph-tlcs90.rul"
+};
+
+static char _gbz80_defaultRules[] = {
+#include "peeph.rul"
+#include "peeph-gbz80.rul"
+};
+
+
+
+Z80_OPTS z80_opts;
+
+static OPTION _z80_options[] = {
+ {0, OPTION_CALLEE_SAVES_BC, &z80_opts.calleeSavesBC, "Force a called function to always save BC"},
+ {0, OPTION_PORTMODE, NULL, "Determine PORT I/O mode (z80/z180)"},
+ {0, OPTION_ASM, NULL, "Define assembler name (rgbds/asxxxx/isas/z80asm)"},
+ {0, OPTION_CODE_SEG, &options.code_seg, "<name> use this name for the code segment", CLAT_STRING},
+ {0, OPTION_CONST_SEG, &options.const_seg, "<name> use this name for the const segment", CLAT_STRING},
+ {0, OPTION_DATA_SEG, &options.data_seg, "<name> use this name for the data segment", CLAT_STRING},
+ {0, OPTION_NO_STD_CRT0, &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.rel"},
+ {0, OPTION_RESERVE_IY, &z80_opts.reserveIY, "Do not use IY (incompatible with --fomit-frame-pointer)"},
+ {0, OPTION_OLDRALLOC, &options.oldralloc, "Use old register allocator"},
+ {0, OPTION_FRAMEPOINTER, &z80_opts.noOmitFramePtr, "Do not omit frame pointer"},
+ {0, OPTION_EMIT_EXTERNS, NULL, "Emit externs list in generated asm"},
+ {0, NULL}
+};
+
+static OPTION _gbz80_options[] = {
+ {0, OPTION_BO, NULL, "<num> use code bank <num>"},
+ {0, OPTION_BA, NULL, "<num> use data bank <num>"},
+ {0, OPTION_CALLEE_SAVES_BC, &z80_opts.calleeSavesBC, "Force a called function to always save BC"},
+ {0, OPTION_CODE_SEG, &options.code_seg, "<name> use this name for the code segment", CLAT_STRING},
+ {0, OPTION_CONST_SEG, &options.const_seg, "<name> use this name for the const segment", CLAT_STRING},
+ {0, OPTION_DATA_SEG, &options.data_seg, "<name> use this name for the data segment", CLAT_STRING},
+ {0, OPTION_NO_STD_CRT0, &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.rel"},
+ {0, NULL}
+};
+
+typedef enum
+{
+ /* Must be first */
+ ASM_TYPE_ASXXXX,
+ ASM_TYPE_RGBDS,
+ ASM_TYPE_ISAS,
+ ASM_TYPE_Z80ASM
+}
+ASM_TYPE;
+
+static struct
+{
+ ASM_TYPE asmType;
+ /* determine if we can register a parameter */
+ int regParams;
+ bool z88dk_fastcall;
+}
+_G;
+
+static char *_keywords[] = {
+ "sfr",
+ "nonbanked",
+ "banked",
+ "at",
+ "_naked",
+ "critical",
+ "interrupt",
+ "z88dk_fastcall",
+ "z88dk_callee",
+ "smallc",
+ "z88dk_shortcall",
+ "z88dk_params_offset",
+ NULL
+};
+
+static char *_keywordsgb[] = {
+ "sfr",
+ "nonbanked",
+ "banked",
+ "at",
+ "_naked",
+ "critical",
+ "interrupt",
+ "z88dk_callee",
+ "smallc",
+ NULL
+};
+
+static char *_keywordstlcs90[] = {
+ "nonbanked",
+ "banked",
+ "at",
+ "_naked",
+ "critical",
+ "interrupt",
+ "z88dk_fastcall",
+ "z88dk_callee",
+ "smallc",
+ NULL
+};
+
+extern PORT z80_port;
+extern PORT r2k_port;
+extern PORT gbz80_port;
+
+#include "mappings.i"
+
+static builtins _z80_builtins[] = {
+ {"__builtin_memcpy", "vg*", 3, {"vg*", "Cvg*", "Ui"}},
+ {"__builtin_strcpy", "cg*", 2, {"cg*", "Ccg*"}},
+ {"__builtin_strncpy", "cg*", 3, {"cg*", "Ccg*", "Ui"}},
+ {"__builtin_strchr", "cg*", 2, {"Ccg*", "i"}},
+ {"__builtin_memset", "vg*", 3, {"vg*", "i", "Ui"}},
+ {NULL, NULL, 0, {NULL}}
+};
+
+static void
+_z80_init (void)
+{
+ z80_opts.sub = SUB_Z80;
+ asm_addTree (&_asxxxx_z80);
+}
+
+static void
+_z180_init (void)
+{
+ z80_opts.sub = SUB_Z180;
+ asm_addTree (&_asxxxx_z80);
+}
+
+static void
+_r2k_init (void)
+{
+ z80_opts.sub = SUB_R2K;
+ asm_addTree (&_asxxxx_r2k);
+}
+
+static void
+_r3ka_init (void)
+{
+ z80_opts.sub = SUB_R3KA;
+ asm_addTree (&_asxxxx_r2k);
+}
+
+static void
+_gbz80_init (void)
+{
+ z80_opts.sub = SUB_GBZ80;
+}
+
+static void
+_tlcs90_init (void)
+{
+ z80_opts.sub = SUB_TLCS90;
+ asm_addTree (&_asxxxx_z80);
+}
+
+static void
+_ez80_z80_init (void)
+{
+ z80_opts.sub = SUB_EZ80_Z80;
+ asm_addTree (&_asxxxx_z80);
+}
+
+static void
+_reset_regparm (struct sym_link *funcType)
+{
+ _G.regParams = 0;
+ _G.z88dk_fastcall = IFFUNC_ISZ88DK_FASTCALL (funcType);
+ if (_G.z88dk_fastcall && IFFUNC_HASVARARGS (funcType))
+ werror (E_Z88DK_FASTCALL_PARAMETERS);
+}
+
+static int
+_reg_parm (sym_link *l, bool reentrant)
+{
+ if (_G.z88dk_fastcall)
+ {
+ if (_G.regParams)
+ werror (E_Z88DK_FASTCALL_PARAMETERS);
+ if (getSize (l) > 4)
+ werror (E_Z88DK_FASTCALL_PARAMETER);
+ _G.regParams++;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+enum
+{
+ P_BANK = 1,
+ P_PORTMODE,
+ P_CODESEG,
+ P_CONSTSEG,
+};
+
+static int
+do_pragma (int id, const char *name, const char *cp)
+{
+ struct pragma_token_s token;
+ int err = 0;
+ int processed = 1;
+
+ init_pragma_token (&token);
+
+ switch (id)
+ {
+ case P_BANK:
+ {
+ struct dbuf_s buffer;
+
+ dbuf_init (&buffer, 128);
+
+ cp = get_pragma_token (cp, &token);
+
+ switch (token.type)
+ {
+ case TOKEN_EOL:
+ err = 1;
+ break;
+
+ case TOKEN_INT:
+ switch (_G.asmType)
+ {
+ case ASM_TYPE_ASXXXX:
+ dbuf_printf (&buffer, "CODE_%d", token.val.int_val);
+ break;
+
+ case ASM_TYPE_RGBDS:
+ dbuf_printf (&buffer, "CODE,BANK[%d]", token.val.int_val);
+ break;
+
+ case ASM_TYPE_ISAS:
+ /* PENDING: what to use for ISAS? */
+ dbuf_printf (&buffer, "CODE,BANK(%d)", token.val.int_val);
+ break;
+
+ default:
+ wassert (0);
+ }
+ break;
+
+ default:
+ {
+ const char *str = get_pragma_string (&token);
+
+ dbuf_append_str (&buffer, (0 == strcmp ("BASE", str)) ? "HOME" : str);
+ }
+ break;
+ }
+
+ cp = get_pragma_token (cp, &token);
+ if (TOKEN_EOL != token.type)
+ {
+ err = 1;
+ break;
+ }
+
+ dbuf_c_str (&buffer);
+ /* ugly, see comment in src/port.h (borutr) */
+ gbz80_port.mem.code_name = dbuf_detach (&buffer);
+ code->sname = gbz80_port.mem.code_name;
+ options.code_seg = (char *) gbz80_port.mem.code_name;
+ }
+ break;
+
+ case P_PORTMODE:
+ { /*.p.t.20030716 - adding pragma to manipulate z80 i/o port addressing modes */
+ const char *str;
+
+ cp = get_pragma_token (cp, &token);
+
+ if (TOKEN_EOL == token.type)
+ {
+ err = 1;
+ break;
+ }
+
+ str = get_pragma_string (&token);
+
+ cp = get_pragma_token (cp, &token);
+ if (TOKEN_EOL != token.type)
+ {
+ err = 1;
+ break;
+ }
+
+ if (!strcmp (str, "z80"))
+ {
+ z80_opts.port_mode = 80;
+ }
+ else if (!strcmp (str, "z180"))
+ {
+ z80_opts.port_mode = 180;
+ }
+ else if (!strcmp (str, "save"))
+ {
+ z80_opts.port_back = z80_opts.port_mode;
+ }
+ else if (!strcmp (str, "restore"))
+ {
+ z80_opts.port_mode = z80_opts.port_back;
+ }
+ else
+ err = 1;
+ }
+ break;
+
+ case P_CODESEG:
+ case P_CONSTSEG:
+ {
+ char *segname;
+
+ cp = get_pragma_token (cp, &token);
+ if (token.type == TOKEN_EOL)
+ {
+ err = 1;
+ break;
+ }
+
+ segname = Safe_strdup (get_pragma_string (&token));
+
+ cp = get_pragma_token (cp, &token);
+ if (token.type != TOKEN_EOL)
+ {
+ Safe_free (segname);
+ err = 1;
+ break;
+ }
+
+ if (id == P_CODESEG)
+ {
+ if (options.code_seg)
+ Safe_free (options.code_seg);
+ options.code_seg = segname;
+ }
+ else
+ {
+ if (options.const_seg)
+ Safe_free (options.const_seg);
+ options.const_seg = segname;
+ }
+ }
+ break;
+
+ default:
+ processed = 0;
+ break;
+ }
+
+ get_pragma_token (cp, &token);
+
+ if (1 == err)
+ werror (W_BAD_PRAGMA_ARGUMENTS, name);
+
+ free_pragma_token (&token);
+ return processed;
+}
+
+static struct pragma_s pragma_tbl[] = {
+ {"bank", P_BANK, 0, do_pragma},
+ {"portmode", P_PORTMODE, 0, do_pragma},
+ {"codeseg", P_CODESEG, 0, do_pragma},
+ {"constseg", P_CONSTSEG, 0, do_pragma},
+ {NULL, 0, 0, NULL},
+};
+
+static int
+_process_pragma (const char *s)
+{
+ return process_pragma_tbl (pragma_tbl, s);
+}
+
+static const char *_gbz80_rgbasmCmd[] = {
+ "rgbasm", "-o$1.rel", "$1.asm", NULL
+};
+
+static const char *_gbz80_rgblinkCmd[] = {
+ "xlink", "-tg", "-n$1.sym", "-m$1.map", "-zFF", "$1.lnk", NULL
+};
+
+static void
+_gbz80_rgblink (void)
+{
+ FILE *lnkfile;
+ struct dbuf_s lnkFileName;
+ char *buffer;
+
+ dbuf_init (&lnkFileName, PATH_MAX);
+
+ /* first we need to create the <filename>.lnk file */
+ dbuf_append_str (&lnkFileName, dstFileName);
+ dbuf_append_str (&lnkFileName, ".lk");
+ if (!(lnkfile = fopen (dbuf_c_str (&lnkFileName), "w")))
+ {
+ werror (E_FILE_OPEN_ERR, dbuf_c_str (&lnkFileName));
+ dbuf_destroy (&lnkFileName);
+ exit (1);
+ }
+ dbuf_destroy (&lnkFileName);
+
+ fprintf (lnkfile, "[Objects]\n");
+
+ fprintf (lnkfile, "%s.rel\n", dstFileName);
+
+ fputStrSet (lnkfile, relFilesSet);
+
+ fprintf (lnkfile, "\n[Libraries]\n");
+ /* additional libraries if any */
+ fputStrSet (lnkfile, libFilesSet);
+
+ fprintf (lnkfile, "\n[Output]\n" "%s.gb", dstFileName);
+
+ fclose (lnkfile);
+
+ buffer = buildCmdLine (port->linker.cmd, dstFileName, NULL, NULL, NULL);
+ /* call the linker */
+ if (sdcc_system (buffer))
+ {
+ Safe_free (buffer);
+ perror ("Cannot exec linker");
+ exit (1);
+ }
+ Safe_free (buffer);
+}
+
+static bool
+_parseOptions (int *pargc, char **argv, int *i)
+{
+ if (argv[*i][0] == '-')
+ {
+ if (IS_GB)
+ {
+ if (!strncmp (argv[*i], OPTION_BO, sizeof (OPTION_BO) - 1))
+ {
+ /* ROM bank */
+ int bank = getIntArg (OPTION_BO, argv, i, *pargc);
+ struct dbuf_s buffer;
+
+ dbuf_init (&buffer, 16);
+ dbuf_printf (&buffer, "CODE_%u", bank);
+ dbuf_c_str (&buffer);
+ /* ugly, see comment in src/port.h (borutr) */
+ gbz80_port.mem.code_name = dbuf_detach (&buffer);
+ options.code_seg = (char *) gbz80_port.mem.code_name;
+ return TRUE;
+ }
+ else if (!strncmp (argv[*i], OPTION_BA, sizeof (OPTION_BA) - 1))
+ {
+ /* RAM bank */
+ int bank = getIntArg (OPTION_BA, argv, i, *pargc);
+ struct dbuf_s buffer;
+
+ dbuf_init (&buffer, 16);
+ dbuf_printf (&buffer, "DATA_%u", bank);
+ dbuf_c_str (&buffer);
+ /* ugly, see comment in src/port.h (borutr) */
+ gbz80_port.mem.data_name = dbuf_detach (&buffer);
+ return TRUE;
+ }
+ }
+
+ if (!strncmp (argv[*i], OPTION_ASM, sizeof (OPTION_ASM) - 1))
+ {
+ char *asmblr = getStringArg (OPTION_ASM, argv, i, *pargc);
+
+ if (!strcmp (asmblr, "rgbds"))
+ {
+ asm_addTree (&_rgbds_gb);
+ gbz80_port.assembler.cmd = _gbz80_rgbasmCmd;
+ gbz80_port.linker.cmd = _gbz80_rgblinkCmd;
+ gbz80_port.linker.do_link = _gbz80_rgblink;
+ _G.asmType = ASM_TYPE_RGBDS;
+ return TRUE;
+ }
+ else if (!strcmp (asmblr, "asxxxx"))
+ {
+ _G.asmType = ASM_TYPE_ASXXXX;
+ return TRUE;
+ }
+ else if (!strcmp (asmblr, "isas"))
+ {
+ asm_addTree (&_isas_gb);
+ /* Munge the function prefix */
+ gbz80_port.fun_prefix = "";
+ _G.asmType = ASM_TYPE_ISAS;
+ return TRUE;
+ }
+ else if (!strcmp (asmblr, "z80asm"))
+ {
+ port->assembler.externGlobal = TRUE;
+ asm_addTree (&_z80asm_z80);
+ _G.asmType = ASM_TYPE_ISAS;
+ return TRUE;
+ }
+ }
+ else if (!strncmp (argv[*i], OPTION_PORTMODE, sizeof (OPTION_PORTMODE) - 1))
+ {
+ char *portmode = getStringArg (OPTION_ASM, argv, i, *pargc);
+
+ if (!strcmp (portmode, "z80"))
+ {
+ z80_opts.port_mode = 80;
+ return TRUE;
+ }
+ else if (!strcmp (portmode, "z180"))
+ {
+ z80_opts.port_mode = 180;
+ return TRUE;
+ }
+ }
+ else if (!strncmp (argv[*i], OPTION_EMIT_EXTERNS, sizeof (OPTION_EMIT_EXTERNS) - 1))
+ {
+ port->assembler.externGlobal = 1;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void
+_setValues (void)
+{
+ const char *s;
+ struct dbuf_s dbuf;
+
+ if (options.nostdlib == FALSE)
+ {
+ const char *s;
+ char *path;
+ struct dbuf_s dbuf;
+
+ dbuf_init (&dbuf, PATH_MAX);
+
+ for (s = setFirstItem (libDirsSet); s != NULL; s = setNextItem (libDirsSet))
+ {
+ path = buildCmdLine2 ("-k\"%s" DIR_SEPARATOR_STRING "{port}\" ", s);
+ dbuf_append_str (&dbuf, path);
+ Safe_free (path);
+ }
+ path = buildCmdLine2 ("-l\"{port}.lib\"", s);
+ dbuf_append_str (&dbuf, path);
+ Safe_free (path);
+
+ setMainValue ("z80libspec", dbuf_c_str (&dbuf));
+ dbuf_destroy (&dbuf);
+
+ for (s = setFirstItem (libDirsSet); s != NULL; s = setNextItem (libDirsSet))
+ {
+ struct stat stat_buf;
+
+ path = buildCmdLine2 ("%s" DIR_SEPARATOR_STRING "{port}" DIR_SEPARATOR_STRING "crt0{objext}", s);
+ if (stat (path, &stat_buf) == 0)
+ {
+ Safe_free (path);
+ break;
+ }
+ else
+ Safe_free (path);
+ }
+
+ if (s == NULL)
+ setMainValue ("z80crt0", "\"crt0{objext}\"");
+ else
+ {
+ struct dbuf_s dbuf;
+
+ dbuf_init (&dbuf, 128);
+ dbuf_printf (&dbuf, "\"%s\"", path);
+ setMainValue ("z80crt0", dbuf_c_str (&dbuf));
+ dbuf_destroy (&dbuf);
+ }
+ }
+ else
+ {
+ setMainValue ("z80libspec", "");
+ setMainValue ("z80crt0", "");
+ }
+
+ setMainValue ("z80extralibfiles", (s = joinStrSet (libFilesSet)));
+ Safe_free ((void *) s);
+ setMainValue ("z80extralibpaths", (s = joinStrSet (libPathsSet)));
+ Safe_free ((void *) s);
+
+ if (IS_GB)
+ {
+ setMainValue ("z80outputtypeflag", "-Z");
+ setMainValue ("z80outext", ".gb");
+ }
+ else
+ {
+ setMainValue ("z80outputtypeflag", "-i");
+ setMainValue ("z80outext", ".ihx");
+ }
+
+ setMainValue ("stdobjdstfilename", "{dstfilename}{objext}");
+ setMainValue ("stdlinkdstfilename", "{dstfilename}{z80outext}");
+
+ setMainValue ("z80extraobj", (s = joinStrSet (relFilesSet)));
+ Safe_free ((void *) s);
+
+ dbuf_init (&dbuf, 128);
+ dbuf_printf (&dbuf, "-b_CODE=0x%04X -b_DATA=0x%04X", options.code_loc, options.data_loc);
+ setMainValue ("z80bases", dbuf_c_str (&dbuf));
+ dbuf_destroy (&dbuf);
+
+ /* For the old register allocator (with the new one we decide to omit the frame pointer for each function individually) */
+ if (!IS_GB && options.omitFramePtr)
+ port->stack.call_overhead = 2;
+}
+
+static void
+_finaliseOptions (void)
+{
+ port->mem.default_local_map = data;
+ port->mem.default_globl_map = data;
+ if (_G.asmType == ASM_TYPE_ASXXXX && IS_GB)
+ asm_addTree (&_asxxxx_gb);
+
+ if (IY_RESERVED)
+ port->num_regs -= 2;
+
+ _setValues ();
+}
+
+static void
+_setDefaultOptions (void)
+{
+ options.nopeep = 0;
+ options.stackAuto = 1;
+ /* first the options part */
+ options.intlong_rent = 1;
+ options.float_rent = 1;
+ options.noRegParams = 0;
+ /* Default code and data locations. */
+ options.code_loc = 0x200;
+
+ options.data_loc = IS_GB ? 0xC000 : 0x8000;
+ options.out_fmt = 'i'; /* Default output format is ihx */
+}
+
+#if 0
+/* Mangling format:
+ _fun_policy_params
+ where:
+ policy is the function policy
+ params is the parameter format
+
+ policy format:
+ rsp
+ where:
+ r is 'r' for reentrant, 's' for static functions
+ s is 'c' for callee saves, 'r' for caller saves
+ f is 'f' for profiling on, 'x' for profiling off
+ examples:
+ rr - reentrant, caller saves
+ params format:
+ A combination of register short names and s to signify stack variables.
+ examples:
+ bds - first two args appear in BC and DE, the rest on the stack
+ s - all arguments are on the stack.
+*/
+static const char *
+_mangleSupportFunctionName (const char *original)
+{
+ struct dbuf_s dbuf;
+
+ if (strstr (original, "longlong"))
+ return (original);
+
+ dbuf_init (&dbuf, 128);
+ dbuf_printf (&dbuf, "%s_rr%s_%s", original, options.profile ? "f" : "x", options.noRegParams ? "s" : "bds" /* MB: but the library only has hds variants ??? */
+ );
+
+ return dbuf_detach_c_str (&dbuf);
+}
+#endif
+
+static const char *
+_getRegName (const struct reg_info *reg)
+{
+ if (reg)
+ {
+ return reg->name;
+ }
+ /* assert (0); */
+ return "err";
+}
+
+static int
+_getRegByName (const char *name)
+{
+ if (!strcmp (name, "a"))
+ return 0;
+ if (!strcmp (name, "c"))
+ return 1;
+ if (!strcmp (name, "b"))
+ return 2;
+ if (!strcmp (name, "e"))
+ return 3;
+ if (!strcmp (name, "d"))
+ return 4;
+ if (!strcmp (name, "l"))
+ return 5;
+ if (!strcmp (name, "h"))
+ return 6;
+ if (!strcmp (name, "iyl"))
+ return 7;
+ if (!strcmp (name, "iyh"))
+ return 8;
+ return -1;
+}
+
+static bool
+_hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
+{
+ sym_link *test = NULL;
+ int result_size = IS_SYMOP (IC_RESULT(ic)) ? getSize (OP_SYM_TYPE (IC_RESULT(ic))) : 4;
+
+ if (ic->op != '*')
+ {
+ return FALSE;
+ }
+
+ if (IS_LITERAL (left))
+ test = left;
+ else if (IS_LITERAL (right))
+ test = right;
+ /* 8x8 unsigned multiplication code is shorter than
+ call overhead for the multiplication routine. */
+ else if (IS_CHAR (right) && IS_UNSIGNED (right) && IS_CHAR (left) && IS_UNSIGNED (left) && !IS_GB)
+ {
+ return TRUE;
+ }
+ /* Same for any multiplication with 8 bit result. */
+ else if (result_size == 1 && !IS_GB)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ if (getSize (test) <= 2)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+ if (op == GETHBIT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+ if (IN_FARSPACE (oclass))
+ return 1;
+
+ return 0;
+}
+
+
+//#define LINKCMD "sdld{port} -nf {dstfilename}"
+/*
+#define LINKCMD \
+ "sdld{port} -n -c -- {z80bases} -m -j" \
+ " {z80libspec}" \
+ " {z80extralibfiles} {z80extralibpaths}" \
+ " {z80outputtypeflag} \"{linkdstfilename}\"" \
+ " {z80crt0}" \
+ " \"{dstfilename}{objext}\"" \
+ " {z80extraobj}"
+*/
+
+static const char *_z80LinkCmd[] = {
+ "sdldz80", "-nf", "$1", NULL
+};
+
+static const char *_gbLinkCmd[] = {
+ "sdldgb", "-nf", "$1", NULL
+};
+
+/* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
+static const char *_z80AsmCmd[] = {
+ "sdasz80", "$l", "$3", "$2", "$1.asm", NULL
+};
+
+static const char *_r2kAsmCmd[] = {
+ "sdasrab", "$l", "$3", "$2", "$1.asm", NULL
+};
+
+static const char *_gbAsmCmd[] = {
+ "sdasgb", "$l", "$3", "$2", "$1.asm", NULL
+};
+
+static const char *_tlcs90AsmCmd[] = {
+ "sdastlcs90", "$l", "$3", "$2", "$1.asm", NULL
+};
+
+static const char *const _crt[] = { "crt0.rel", NULL, };
+static const char *const _libs_z80[] = { "z80", NULL, };
+static const char *const _libs_z180[] = { "z180", NULL, };
+static const char *const _libs_r2k[] = { "r2k", NULL, };
+static const char *const _libs_r3ka[] = { "r3ka", NULL, };
+static const char *const _libs_tlcs90[] = { "tlcs90", NULL, };
+static const char *const _libs_gb[] = { "gbz80", NULL, };
+static const char *const _libs_ez80_z80[] = { "ez80_z80", NULL, };
+
+/* Globals */
+PORT z80_port =
+{
+ TARGET_ID_Z80,
+ "z80",
+ "Zilog Z80", /* Target name */
+ NULL, /* Processor name */
+ {
+ glue,
+ FALSE,
+ NO_MODEL,
+ NO_MODEL,
+ NULL, /* model == target */
+ },
+ { /* Assembler */
+ _z80AsmCmd,
+ NULL,
+ "-plosgffwy", /* Options with debug */
+ "-plosgffw", /* Options without debug */
+ 0,
+ ".asm"
+ },
+ { /* Linker */
+ _z80LinkCmd, //NULL,
+ NULL, //LINKCMD,
+ NULL,
+ ".rel",
+ 1, /* needLinkerScript */
+ _crt, /* crt */
+ _libs_z80, /* libs */
+ },
+ { /* Peephole optimizer */
+ _z80_defaultRules,
+ z80instructionSize,
+ 0,
+ 0,
+ 0,
+ z80notUsed,
+ z80canAssign,
+ z80notUsedFrom,
+ z80symmParmStack,
+ },
+ /* Sizes: char, short, int, long, long long, near ptr, far ptr, gptr, func ptr, banked func ptr, bit, float */
+ { 1, 2, 2, 4, 8, 2, 2, 2, 2, 2, 1, 4 },
+ /* tags for generic pointers */
+ { 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */
+ {
+ "XSEG",
+ "STACK",
+ "CODE",
+ "DATA",
+ NULL, /* idata */
+ NULL, /* pdata */
+ NULL, /* xdata */
+ NULL, /* bit */
+ "RSEG (ABS)",
+ "GSINIT", /* static initialization */
+ NULL, /* overlay */
+ "GSFINAL",
+ "HOME",
+ NULL, /* xidata */
+ NULL, /* xinit */
+ NULL, /* const_name */
+ "CABS (ABS)", /* cabs_name */
+ "DABS (ABS)", /* xabs_name */
+ NULL, /* iabs_name */
+ "INITIALIZED", /* name of segment for initialized variables */
+ "INITIALIZER", /* name of segment for copies of initialized variables in code space */
+ NULL,
+ NULL,
+ 1, /* CODE is read-only */
+ 1 /* No fancy alignments supported. */
+ },
+ { NULL, NULL },
+ { -1, 0, 0, 4, 0, 2, 0 },
+ { -1, FALSE },
+ { z80_emitDebuggerSymbol },
+ {
+ 256, /* maxCount */
+ 3, /* sizeofElement */
+ {6, 7, 8}, /* sizeofMatchJump[] - Assumes operand allocated to registers */
+ {6, 9, 15}, /* sizeofRangeCompare[] - Assumes operand allocated to registers*/
+ 1, /* sizeofSubtract - Assumes use of a singel inc or dec */
+ 9, /* sizeofDispatch - Assumes operand allocated to register e or c*/
+ },
+ "_",
+ _z80_init,
+ _parseOptions,
+ _z80_options,
+ NULL,
+ _finaliseOptions,
+ _setDefaultOptions,
+ z80_assignRegisters,
+ _getRegName,
+ _getRegByName,
+ NULL,
+ _keywords,
+ 0, /* no assembler preamble */
+ NULL, /* no genAssemblerEnd */
+ 0, /* no local IVT generation code */
+ 0, /* no genXINIT code */
+ NULL, /* genInitStartup */
+ _reset_regparm,
+ _reg_parm,
+ _process_pragma,
+ NULL,
+ _hasNativeMulFor,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
+ TRUE,
+ TRUE, /* little endian */
+ 0, /* leave lt */
+ 0, /* leave gt */
+ 1, /* transform <= to ! > */
+ 1, /* transform >= to ! < */
+ 1, /* transform != to !(a == b) */
+ 0, /* leave == */
+ FALSE, /* Array initializer support. */
+ 0, /* no CSE cost estimation yet */
+ _z80_builtins, /* builtin functions */
+ GPOINTER, /* treat unqualified pointers as "generic" pointers */
+ 1, /* reset labelKey to 1 */
+ 1, /* globals & local statics allowed */
+ 9, /* Number of registers handled in the tree-decomposition-based register allocator in SDCCralloc.hpp */
+ PORT_MAGIC
+};
+
+PORT z180_port =
+{
+ TARGET_ID_Z180,
+ "z180",
+ "Zilog Z180", /* Target name */
+ NULL, /* Processor name */
+ {
+ glue,
+ FALSE,
+ NO_MODEL,
+ NO_MODEL,
+ NULL, /* model == target */
+ },
+ { /* Assembler */
+ _z80AsmCmd,
+ NULL,
+ "-plosgffwy", /* Options with debug */
+ "-plosgffw", /* Options without debug */
+ 0,
+ ".asm"
+ },
+ { /* Linker */
+ _z80LinkCmd, //NULL,
+ NULL, //LINKCMD,
+ NULL,
+ ".rel",
+ 1,
+ _crt, /* crt */
+ _libs_z180, /* libs */
+ },
+ { /* Peephole optimizer */
+ _z80_defaultRules,
+ z80instructionSize,
+ NULL,
+ NULL,
+ NULL,
+ z80notUsed,
+ z80canAssign,
+ z80notUsedFrom,
+ z80symmParmStack,
+ },
+ /* Sizes: char, short, int, long, long long, near ptr, far ptr, gptr, func ptr, banked func ptr, bit, float */
+ { 1, 2, 2, 4, 8, 2, 2, 2, 2, 2, 1, 4 },
+ /* tags for generic pointers */
+ { 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */
+ {
+ "XSEG",
+ "STACK",
+ "CODE",
+ "DATA",
+ NULL, /* idata */
+ NULL, /* pdata */
+ NULL, /* xdata */
+ NULL, /* bit */
+ "RSEG (ABS)",
+ "GSINIT",
+ NULL, /* overlay */
+ "GSFINAL",
+ "HOME",
+ NULL, /* xidata */
+ NULL, /* xinit */
+ NULL, /* const_name */
+ "CABS (ABS)", /* cabs_name */
+ "DABS (ABS)", /* xabs_name */
+ NULL, /* iabs_name */
+ "INITIALIZED", /* name of segment for initialized variables */
+ "INITIALIZER", /* name of segment for copies of initialized variables in code space */
+ NULL,
+ NULL,
+ 1, /* CODE is read-only */
+ 1 /* No fancy alignments supported. */
+ },
+ { NULL, NULL },
+ { -1, 0, 0, 4, 0, 2, 0 },
+ { -1, FALSE },
+ { z80_emitDebuggerSymbol },
+ {
+ 256, /* maxCount */
+ 3, /* sizeofElement */
+ {6, 7, 8}, /* sizeofMatchJump[] - Assumes operand allocated to registers */
+ {6, 9, 15}, /* sizeofRangeCompare[] - Assumes operand allocated to registers*/
+ 1, /* sizeofSubtract - Assumes use of a singel inc or dec */
+ 9, /* sizeofDispatch - Assumes operand allocated to register e or c*/
+ },
+ "_",
+ _z180_init,
+ _parseOptions,
+ _z80_options,
+ NULL,
+ _finaliseOptions,
+ _setDefaultOptions,
+ z80_assignRegisters,
+ _getRegName,
+ _getRegByName,
+ NULL,
+ _keywords,
+ 0, /* no assembler preamble */
+ NULL, /* no genAssemblerEnd */
+ 0, /* no local IVT generation code */
+ 0, /* no genXINIT code */
+ NULL, /* genInitStartup */
+ _reset_regparm,
+ _reg_parm,
+ _process_pragma,
+ NULL,
+ _hasNativeMulFor,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
+ TRUE,
+ TRUE, /* little endian */
+ 0, /* leave lt */
+ 0, /* leave gt */
+ 1, /* transform <= to ! > */
+ 1, /* transform >= to ! < */
+ 1, /* transform != to !(a == b) */
+ 0, /* leave == */
+ FALSE, /* Array initializer support. */
+ 0, /* no CSE cost estimation yet */
+ _z80_builtins, /* builtin functions */
+ GPOINTER, /* treat unqualified pointers as "generic" pointers */
+ 1, /* reset labelKey to 1 */
+ 1, /* globals & local statics allowed */
+ 9, /* Number of registers handled in the tree-decomposition-based register allocator in SDCCralloc.hpp */
+ PORT_MAGIC
+};
+
+PORT r2k_port =
+{
+ TARGET_ID_R2K,
+ "r2k",
+ "Rabbit 2000", /* Target name */
+ NULL, /* Processor name */
+ {
+ glue,
+ FALSE,
+ NO_MODEL,
+ NO_MODEL,
+ NULL, /* model == target */
+ },
+ { /* Assembler */
+ _r2kAsmCmd,
+ NULL,
+ "-plosgffwy", /* Options with debug */
+ "-plosgffw", /* Options without debug */
+ 0,
+ ".asm"},
+ { /* Linker */
+ _z80LinkCmd, //NULL,
+ NULL, //LINKCMD,
+ NULL,
+ ".rel",
+ 1,
+ _crt, /* crt */
+ _libs_r2k, /* libs */
+ },
+ { /* Peephole optimizer */
+ _r2k_defaultRules,
+ z80instructionSize,
+ NULL,
+ NULL,
+ NULL,
+ z80notUsed,
+ z80canAssign,
+ z80notUsedFrom,
+ z80symmParmStack,
+ },
+ /* Sizes: char, short, int, long, long long, near ptr, far ptr, gptr, func ptr, banked func ptr, bit, float */
+ { 1, 2, 2, 4, 8, 2, 2, 2, 2, 2, 1, 4 },
+ /* tags for generic pointers */
+ { 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */
+ {
+ "XSEG",
+ "STACK",
+ "CODE",
+ "DATA",
+ NULL, /* idata */
+ NULL, /* pdata */
+ NULL, /* xdata */
+ NULL, /* bit */
+ "RSEG (ABS)",
+ "GSINIT",
+ NULL, /* overlay */
+ "GSFINAL",
+ "HOME",
+ NULL, /* xidata */
+ NULL, /* xinit */
+ NULL, /* const_name */
+ "CABS (ABS)", /* cabs_name */
+ "DABS (ABS)", /* xabs_name */
+ NULL, /* iabs_name */
+ "INITIALIZED", /* name of segment for initialized variables */
+ "INITIALIZER", /* name of segment for copies of initialized variables in code space */
+ NULL,
+ NULL,
+ 1, /* CODE is read-only */
+ 1 /* No fancy alignments supported. */
+ },
+ { NULL, NULL },
+ { -1, 0, 0, 4, 0, 2, 0 },
+ { -1, FALSE },
+ { z80_emitDebuggerSymbol },
+ {
+ 256, /* maxCount */
+ 3, /* sizeofElement */
+ {6, 7, 8}, /* sizeofMatchJump[] - Assumes operand allocated to registers */
+ {6, 9, 15}, /* sizeofRangeCompare[] - Assumes operand allocated to registers*/
+ 1, /* sizeofSubtract - Assumes use of a singel inc or dec */
+ 9, /* sizeofDispatch - Assumes operand allocated to register e or c*/
+ },
+ "_",
+ _r2k_init,
+ _parseOptions,
+ _z80_options,
+ NULL,
+ _finaliseOptions,
+ _setDefaultOptions,
+ z80_assignRegisters,
+ _getRegName,
+ _getRegByName,
+ NULL,
+ _keywords,
+ 0, /* no assembler preamble */
+ NULL, /* no genAssemblerEnd */
+ 0, /* no local IVT generation code */
+ 0, /* no genXINIT code */
+ NULL, /* genInitStartup */
+ _reset_regparm,
+ _reg_parm,
+ _process_pragma,
+ NULL,
+ _hasNativeMulFor,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
+ TRUE,
+ TRUE, /* little endian */
+ 0, /* leave lt */
+ 0, /* leave gt */
+ 1, /* transform <= to ! > */
+ 1, /* transform >= to ! < */
+ 1, /* transform != to !(a == b) */
+ 0, /* leave == */
+ FALSE, /* Array initializer support. */
+ 0, /* no CSE cost estimation yet */
+ _z80_builtins, /* builtin functions */
+ GPOINTER, /* treat unqualified pointers as "generic" pointers */
+ 1, /* reset labelKey to 1 */
+ 1, /* globals & local statics allowed */
+ 9, /* Number of registers handled in the tree-decomposition-based register allocator in SDCCralloc.hpp */
+ PORT_MAGIC
+};
+
+PORT r3ka_port =
+{
+ TARGET_ID_R3KA,
+ "r3ka",
+ "Rabbit 3000A", /* Target name */
+ NULL, /* Processor name */
+ {
+ glue,
+ FALSE,
+ NO_MODEL,
+ NO_MODEL,
+ NULL, /* model == target */
+ },
+ { /* Assembler */
+ _r2kAsmCmd,
+ NULL,
+ "-plosgffwy", /* Options with debug */
+ "-plosgffw", /* Options without debug */
+ 0,
+ ".asm"
+ },
+ { /* Linker */
+ _z80LinkCmd, //NULL,
+ NULL, //LINKCMD,
+ NULL,
+ ".rel",
+ 1,
+ _crt, /* crt */
+ _libs_r3ka, /* libs */
+ },
+ { /* Peephole optimizer */
+ _r2k_defaultRules,
+ z80instructionSize,
+ 0,
+ 0,
+ 0,
+ z80notUsed,
+ z80canAssign,
+ z80notUsedFrom,
+ z80symmParmStack,
+ },
+ /* Sizes: char, short, int, long, long long, near ptr, far ptr, gptr, func ptr, banked func ptr, bit, float */
+ { 1, 2, 2, 4, 8, 2, 2, 2, 2, 2, 1, 4 },
+ /* tags for generic pointers */
+ { 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */
+ {
+ "XSEG",
+ "STACK",
+ "CODE",
+ "DATA",
+ NULL, /* idata */
+ NULL, /* pdata */
+ NULL, /* xdata */
+ NULL, /* bit */
+ "RSEG (ABS)",
+ "GSINIT",
+ NULL, /* overlay */
+ "GSFINAL",
+ "HOME",
+ NULL, /* xidata */
+ NULL, /* xinit */
+ NULL, /* const_name */
+ "CABS (ABS)", /* cabs_name */
+ "DABS (ABS)", /* xabs_name */
+ NULL, /* iabs_name */
+ "INITIALIZED", /* name of segment for initialized variables */
+ "INITIALIZER", /* name of segment for copies of initialized variables in code space */
+ NULL,
+ NULL,
+ 1, /* CODE is read-only */
+ 1 /* No fancy alignments supported. */
+ },
+ { NULL, NULL },
+ { -1, 0, 0, 4, 0, 2, 0 },
+ { -1, FALSE },
+ { z80_emitDebuggerSymbol },
+ {
+ 256, /* maxCount */
+ 3, /* sizeofElement */
+ {6, 7, 8}, /* sizeofMatchJump[] - Assumes operand allocated to registers */
+ {6, 9, 15}, /* sizeofRangeCompare[] - Assumes operand allocated to registers*/
+ 1, /* sizeofSubtract - Assumes use of a singel inc or dec */
+ 9, /* sizeofDispatch - Assumes operand allocated to register e or c*/
+ },
+ "_",
+ _r3ka_init,
+ _parseOptions,
+ _z80_options,
+ NULL,
+ _finaliseOptions,
+ _setDefaultOptions,
+ z80_assignRegisters,
+ _getRegName,
+ _getRegByName,
+ NULL,
+ _keywords,
+ 0, /* no assembler preamble */
+ NULL, /* no genAssemblerEnd */
+ 0, /* no local IVT generation code */
+ 0, /* no genXINIT code */
+ NULL, /* genInitStartup */
+ _reset_regparm,
+ _reg_parm,
+ _process_pragma,
+ NULL,
+ _hasNativeMulFor,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
+ TRUE,
+ TRUE, /* little endian */
+ 0, /* leave lt */
+ 0, /* leave gt */
+ 1, /* transform <= to ! > */
+ 1, /* transform >= to ! < */
+ 1, /* transform != to !(a == b) */
+ 0, /* leave == */
+ FALSE, /* Array initializer support. */
+ 0, /* no CSE cost estimation yet */
+ _z80_builtins, /* builtin functions */
+ GPOINTER, /* treat unqualified pointers as "generic" pointers */
+ 1, /* reset labelKey to 1 */
+ 1, /* globals & local statics allowed */
+ 9, /* Number of registers handled in the tree-decomposition-based register allocator in SDCCralloc.hpp */
+ PORT_MAGIC
+};
+
+/* Globals */
+PORT gbz80_port =
+{
+ TARGET_ID_GBZ80,
+ "gbz80",
+ "Gameboy Z80-like", /* Target name */
+ NULL,
+ {
+ glue,
+ FALSE,
+ NO_MODEL,
+ NO_MODEL,
+ NULL, /* model == target */
+ },
+ { /* Assembler */
+ _gbAsmCmd,
+ NULL,
+ "-plosgffwy", /* Options with debug */
+ "-plosgffw", /* Options without debug */
+ 0,
+ ".asm",
+ NULL /* no do_assemble function */
+ },
+ { /* Linker */
+ _gbLinkCmd, //NULL,
+ NULL, //LINKCMD,
+ NULL,
+ ".rel",
+ 1,
+ _crt, /* crt */
+ _libs_gb, /* libs */
+ },
+ { /* Peephole optimizer */
+ _gbz80_defaultRules,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ z80symmParmStack,
+ },
+ /* Sizes: char, short, int, long, long long, near ptr, far ptr, gptr, func ptr, banked func ptr, bit, float */
+ { 1, 2, 2, 4, 8, 2, 2, 2, 2, 2, 1, 4 },
+ /* tags for generic pointers */
+ { 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */
+ {
+ "XSEG",
+ "STACK",
+ "CODE",
+ "DATA",
+ NULL, /* idata */
+ NULL, /* pdata */
+ NULL, /* xdata */
+ NULL, /* bit */
+ "RSEG",
+ "GSINIT",
+ NULL, /* overlay */
+ "GSFINAL",
+ "HOME",
+ NULL, /* xidata */
+ NULL, /* xinit */
+ NULL, /* const_name */
+ "CABS (ABS)", /* cabs_name */
+ "DABS (ABS)", /* xabs_name */
+ NULL, /* iabs_name */
+ NULL, /* name of segment for initialized variables */
+ NULL, /* name of segment for copies of initialized variables in code space */
+ NULL,
+ NULL,
+ 1, /* CODE is read-only */
+ 1 /* No fancy alignments supported. */
+ },
+ { NULL, NULL },
+ { -1, 0, 0, 2, 0, 4, 0 },
+ { -1, FALSE },
+ { z80_emitDebuggerSymbol },
+ {
+ 256, /* maxCount */
+ 3, /* sizeofElement */
+ {6, 7, 8}, /* sizeofMatchJump[] - Assumes operand allocated to registers */
+ {6, 9, 15}, /* sizeofRangeCompare[] - Assumes operand allocated to registers*/
+ 1, /* sizeofSubtract - Assumes use of a singel inc or dec */
+ 9, /* sizeofDispatch - Assumes operand allocated to register e or c*/
+ },
+ "_",
+ _gbz80_init,
+ _parseOptions,
+ _gbz80_options,
+ NULL,
+ _finaliseOptions,
+ _setDefaultOptions,
+ z80_assignRegisters,
+ _getRegName,
+ _getRegByName,
+ NULL,
+ _keywordsgb,
+ 0, /* no assembler preamble */
+ NULL, /* no genAssemblerEnd */
+ 0, /* no local IVT generation code */
+ 0, /* no genXINIT code */
+ NULL, /* genInitStartup */
+ _reset_regparm,
+ _reg_parm,
+ _process_pragma,
+ NULL,
+ _hasNativeMulFor,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
+ TRUE,
+ TRUE, /* little endian */
+ 0, /* leave lt */
+ 0, /* leave gt */
+ 1, /* transform <= to ! > */
+ 1, /* transform >= to ! < */
+ 1, /* transform != to !(a == b) */
+ 0, /* leave == */
+ FALSE, /* Array initializer support. */
+ 0, /* no CSE cost estimation yet */
+ NULL, /* no builtin functions */
+ GPOINTER, /* treat unqualified pointers as "generic" pointers */
+ 1, /* reset labelKey to 1 */
+ 1, /* globals & local statics allowed */
+ 5, /* Number of registers handled in the tree-decomposition-based register allocator in SDCCralloc.hpp */
+ PORT_MAGIC
+};
+
+PORT tlcs90_port =
+{
+ TARGET_ID_TLCS90,
+ "tlcs90",
+ "Toshiba TLCS-90", /* Target name */
+ NULL, /* Processor name */
+ {
+ glue,
+ FALSE,
+ NO_MODEL,
+ NO_MODEL,
+ NULL, /* model == target */
+ },
+ { /* Assembler */
+ _tlcs90AsmCmd,
+ NULL,
+ "-plosgffwy", /* Options with debug */
+ "-plosgffw", /* Options without debug */
+ 0,
+ ".asm"
+ },
+ { /* Linker */
+ _z80LinkCmd, //NULL,
+ NULL, //LINKCMD,
+ NULL,
+ ".rel",
+ 1,
+ _crt, /* crt */
+ _libs_tlcs90, /* libs */
+ },
+ { /* Peephole optimizer */
+ _tlcs90_defaultRules,
+ z80instructionSize,
+ NULL,
+ NULL,
+ NULL,
+ z80notUsed,
+ z80canAssign,
+ z80notUsedFrom,
+ z80symmParmStack,
+ },
+ /* Sizes: char, short, int, long, long long, near ptr, far ptr, gptr, func ptr, banked func ptr, bit, float */
+ { 1, 2, 2, 4, 8, 2, 2, 2, 2, 2, 1, 4 },
+ /* tags for generic pointers */
+ { 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */
+ {
+ "XSEG",
+ "STACK",
+ "CODE",
+ "DATA",
+ NULL, /* idata */
+ NULL, /* pdata */
+ NULL, /* xdata */
+ NULL, /* bit */
+ "RSEG (ABS)",
+ "GSINIT", /* static initialization */
+ NULL, /* overlay */
+ "GSFINAL",
+ "HOME",
+ NULL, /* xidata */
+ NULL, /* xinit */
+ NULL, /* const_name */
+ "CABS (ABS)", /* cabs_name */
+ "DABS (ABS)", /* xabs_name */
+ NULL, /* iabs_name */
+ "INITIALIZED", /* name of segment for initialized variables */
+ "INITIALIZER", /* name of segment for copies of initialized variables in code space */
+ NULL,
+ NULL,
+ 1, /* CODE is read-only */
+ 1 /* No fancy alignments supported. */
+ },
+ { NULL, NULL },
+ { -1, 0, 0, 4, 0, 2, 0 },
+ { -1, FALSE },
+ { z80_emitDebuggerSymbol },
+ {
+ 256, /* maxCount */
+ 3, /* sizeofElement */
+ {6, 7, 8}, /* sizeofMatchJump[] - Assumes operand allocated to registers */
+ {6, 9, 15}, /* sizeofRangeCompare[] - Assumes operand allocated to registers*/
+ 1, /* sizeofSubtract - Assumes use of a singel inc or dec */
+ 9, /* sizeofDispatch - Assumes operand allocated to register e or c*/
+ },
+ "_",
+ _tlcs90_init,
+ _parseOptions,
+ _z80_options,
+ NULL,
+ _finaliseOptions,
+ _setDefaultOptions,
+ z80_assignRegisters,
+ _getRegName,
+ _getRegByName,
+ NULL,
+ _keywordstlcs90,
+ 0, /* no assembler preamble */
+ NULL, /* no genAssemblerEnd */
+ 0, /* no local IVT generation code */
+ 0, /* no genXINIT code */
+ NULL, /* genInitStartup */
+ _reset_regparm,
+ _reg_parm,
+ _process_pragma,
+ NULL,
+ _hasNativeMulFor,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
+ TRUE,
+ TRUE, /* little endian */
+ 0, /* leave lt */
+ 0, /* leave gt */
+ 1, /* transform <= to ! > */
+ 1, /* transform >= to ! < */
+ 1, /* transform != to !(a == b) */
+ 0, /* leave == */
+ FALSE, /* Array initializer support. */
+ 0, /* no CSE cost estimation yet */
+ _z80_builtins, /* builtin functions */
+ GPOINTER, /* treat unqualified pointers as "generic" pointers */
+ 1, /* reset labelKey to 1 */
+ 1, /* globals & local statics allowed */
+ 9, /* Number of registers handled in the tree-decomposition-based register allocator in SDCCralloc.hpp */
+ PORT_MAGIC
+};
+
+PORT ez80_z80_port =
+{
+ TARGET_ID_EZ80_Z80,
+ "ez80_z80",
+ "eZ80-Z80", /* Target name */
+ NULL, /* Processor name */
+ {
+ glue,
+ FALSE,
+ NO_MODEL,
+ NO_MODEL,
+ NULL, /* model == target */
+ },
+ { /* Assembler */
+ _z80AsmCmd,
+ NULL,
+ "-plosgffwy", /* Options with debug */
+ "-plosgffw", /* Options without debug */
+ 0,
+ ".asm"
+ },
+ { /* Linker */
+ _z80LinkCmd, //NULL,
+ NULL, //LINKCMD,
+ NULL,
+ ".rel",
+ 1,
+ _crt, /* crt */
+ _libs_ez80_z80, /* libs */
+ },
+ { /* Peephole optimizer */
+ _z80_defaultRules,
+ z80instructionSize,
+ NULL,
+ NULL,
+ NULL,
+ z80notUsed,
+ z80canAssign,
+ z80notUsedFrom,
+ z80symmParmStack,
+ },
+ /* Sizes: char, short, int, long, long long, near ptr, far ptr, gptr, func ptr, banked func ptr, bit, float */
+ { 1, 2, 2, 4, 8, 2, 2, 2, 2, 2, 1, 4 },
+ /* tags for generic pointers */
+ { 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */
+ {
+ "XSEG",
+ "STACK",
+ "CODE",
+ "DATA",
+ NULL, /* idata */
+ NULL, /* pdata */
+ NULL, /* xdata */
+ NULL, /* bit */
+ "RSEG (ABS)",
+ "GSINIT",
+ NULL, /* overlay */
+ "GSFINAL",
+ "HOME",
+ NULL, /* xidata */
+ NULL, /* xinit */
+ NULL, /* const_name */
+ "CABS (ABS)", /* cabs_name */
+ "DABS (ABS)", /* xabs_name */
+ NULL, /* iabs_name */
+ "INITIALIZED", /* name of segment for initialized variables */
+ "INITIALIZER", /* name of segment for copies of initialized variables in code space */
+ NULL,
+ NULL,
+ 1, /* CODE is read-only */
+ 1 /* No fancy alignments supported. */
+ },
+ { NULL, NULL },
+ { -1, 0, 0, 4, 0, 2, 0 },
+ { -1, FALSE },
+ { z80_emitDebuggerSymbol },
+ {
+ 256, /* maxCount */
+ 3, /* sizeofElement */
+ {6, 7, 8}, /* sizeofMatchJump[] - Assumes operand allocated to registers */
+ {6, 9, 15}, /* sizeofRangeCompare[] - Assumes operand allocated to registers*/
+ 1, /* sizeofSubtract - Assumes use of a singel inc or dec */
+ 9, /* sizeofDispatch - Assumes operand allocated to register e or c*/
+ },
+ "_",
+ _ez80_z80_init,
+ _parseOptions,
+ _z80_options,
+ NULL,
+ _finaliseOptions,
+ _setDefaultOptions,
+ z80_assignRegisters,
+ _getRegName,
+ _getRegByName,
+ NULL,
+ _keywords,
+ 0, /* no assembler preamble */
+ NULL, /* no genAssemblerEnd */
+ 0, /* no local IVT generation code */
+ 0, /* no genXINIT code */
+ NULL, /* genInitStartup */
+ _reset_regparm,
+ _reg_parm,
+ _process_pragma,
+ NULL,
+ _hasNativeMulFor,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
+ TRUE,
+ TRUE, /* little endian */
+ 0, /* leave lt */
+ 0, /* leave gt */
+ 1, /* transform <= to ! > */
+ 1, /* transform >= to ! < */
+ 1, /* transform != to !(a == b) */
+ 0, /* leave == */
+ FALSE, /* Array initializer support. */
+ 0, /* no CSE cost estimation yet */
+ _z80_builtins, /* builtin functions */
+ GPOINTER, /* treat unqualified pointers as "generic" pointers */
+ 1, /* reset labelKey to 1 */
+ 1, /* globals & local statics allowed */
+ 9, /* Number of registers handled in the tree-decomposition-based register allocator in SDCCralloc.hpp */
+ PORT_MAGIC
+};
+