1 /*-------------------------------------------------------------------------
2 main.c - Z80 specific definitions.
4 Michael Hope <michaelh@juju.net.nz> 2001
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
32 static char _z80_defaultRules[] =
35 #include "peeph-z80.rul"
38 static char _gbz80_defaultRules[] =
41 #include "peeph-gbz80.rul"
46 static OPTION _z80_options[] =
48 { 0, "--callee-saves-bc", &z80_opts.calleeSavesBC, "Force a called function to always save BC" },
49 { 80, "--portmode", &z80_opts.port_mode, "Determine PORT I/O mode (z80/z180)" },
66 /* determine if we can register a parameter */
71 static char *_keywords[] =
76 "at", //.p.t.20030714 adding support for 'sfr at ADDR' construct
77 "_naked", //.p.t.20030714 adding support for '_naked' functions
81 extern PORT gbz80_port;
86 static builtins _z80_builtins[] = {
88 { "__builtin_strcpy", "v", 2, {"cg*", "cg*" } },
89 { "__builtin_memcpy", "cg*", 3, {"cg*", "cg*", "ui" } },
91 { NULL , NULL,0, {NULL}}
97 z80_opts.sub = SUB_Z80;
98 asm_addTree (&_asxxxx_z80);
104 z80_opts.sub = SUB_GBZ80;
114 _reg_parm (sym_link * l)
116 if (options.noRegParams)
122 if (_G.regParams == 2)
134 _process_pragma (const char *sz)
136 if( startsWith( sz, "bank=" ) || startsWith( sz, "bank " ))
141 werror(W_DEPRECATED_PRAGMA, "bank=");
143 strncpy (buffer, sz + 5, sizeof (buffer));
144 buffer[sizeof (buffer) - 1 ] = '\0';
146 if (isdigit (buffer[0]))
150 else if (!strcmp (buffer, "BASE"))
152 strcpy (buffer, "HOME");
154 if (isdigit (buffer[0]))
156 /* Arg was a bank number. Handle in an ASM independent
159 strncpy (num, sz + 5, sizeof (num));
160 num[sizeof (num) -1] = '\0';
165 case ASM_TYPE_ASXXXX:
166 sprintf (buffer, "CODE_%s", num);
169 sprintf (buffer, "CODE,BANK[%s]", num);
172 /* PENDING: what to use for ISAS? */
173 sprintf (buffer, "CODE,BANK(%s)", num);
179 gbz80_port.mem.code_name = Safe_strdup (buffer);
180 code->sname = gbz80_port.mem.code_name;
183 else if( startsWith( sz, "portmode=" ) || startsWith( sz, "portmode " ))
184 { /*.p.t.20030716 - adding pragma to manipulate z80 i/o port addressing modes */
188 werror(W_DEPRECATED_PRAGMA, "portmode=");
190 strncpy( bfr, sz + 9, sizeof (bfr));
191 bfr[sizeof (bfr) - 1] = '\0';
194 if ( !strcmp( bfr, "z80" )){ z80_opts.port_mode = 80; }
195 else if( !strcmp( bfr, "z180" )){ z80_opts.port_mode = 180; }
196 else if( !strcmp( bfr, "save" )){ z80_opts.port_back = z80_opts.port_mode; }
197 else if( !strcmp( bfr, "restore" )){ z80_opts.port_mode = z80_opts.port_back; }
206 static const char *_gbz80_rgbasmCmd[] =
208 "rgbasm", "-o\"$1.o\"", "\"$1.asm\"", NULL
211 static const char *_gbz80_rgblinkCmd[] =
213 "xlink", "-tg", "-n\"$1.sym\"", "-m\"$1.map\"", "-zFF", "\"$1.lnk\"", NULL
217 _gbz80_rgblink (void)
221 /* first we need to create the <filename>.lnk file */
222 sprintf (scratchFileName, "%s.lnk", dstFileName);
223 if (!(lnkfile = fopen (scratchFileName, "w")))
225 werror (E_FILE_OPEN_ERR, scratchFileName);
229 fprintf (lnkfile, "[Objects]\n");
231 fprintf (lnkfile, "%s.o\n", dstFileName);
233 fputStrSet(lnkfile, relFilesSet);
235 fprintf (lnkfile, "\n[Libraries]\n");
236 /* additional libraries if any */
237 fputStrSet(lnkfile, libFilesSet);
239 fprintf (lnkfile, "\n[Output]\n" "%s.gb", dstFileName);
243 buildCmdLine (buffer,port->linker.cmd, dstFileName, NULL, NULL, NULL);
244 /* call the linker */
245 if (my_system (buffer))
247 perror ("Cannot exec linker");
253 _parseOptions (int *pargc, char **argv, int *i)
255 if (argv[*i][0] == '-')
257 if (argv[*i][1] == 'b' && IS_GB)
259 int bank = atoi (argv[*i] + 3);
265 sprintf (buffer, "CODE_%u", bank);
266 gbz80_port.mem.code_name = Safe_strdup (buffer);
270 sprintf (buffer, "DATA_%u", bank);
271 gbz80_port.mem.data_name = Safe_strdup (buffer);
275 else if (!strncmp (argv[*i], "--asm=", 6))
277 if (!strcmp (argv[*i], "--asm=rgbds"))
279 asm_addTree (&_rgbds_gb);
280 gbz80_port.assembler.cmd = _gbz80_rgbasmCmd;
281 gbz80_port.linker.cmd = _gbz80_rgblinkCmd;
282 gbz80_port.linker.do_link = _gbz80_rgblink;
283 _G.asmType = ASM_TYPE_RGBDS;
286 else if (!strcmp (argv[*i], "--asm=asxxxx"))
288 _G.asmType = ASM_TYPE_ASXXXX;
291 else if (!strcmp (argv[*i], "--asm=isas"))
293 asm_addTree (&_isas_gb);
294 /* Munge the function prefix */
295 gbz80_port.fun_prefix = "";
296 _G.asmType = ASM_TYPE_ISAS;
299 else if (!strcmp (argv[*i], "--asm=z80asm"))
301 port->assembler.externGlobal = TRUE;
302 asm_addTree (&_z80asm_z80);
303 _G.asmType = ASM_TYPE_ISAS;
316 if (options.nostdlib == FALSE)
322 dbuf_init(&dbuf, PATH_MAX);
324 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
326 buildCmdLine2(path, sizeof path, "-k\"%s" DIR_SEPARATOR_STRING "{port}\" ", s);
327 dbuf_append(&dbuf, path, strlen(path));
329 buildCmdLine2(path, sizeof path, "-l\"{port}.lib\"", s);
330 dbuf_append(&dbuf, path, strlen(path));
332 setMainValue ("z80libspec", dbuf_c_str(&dbuf));
335 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
337 struct stat stat_buf;
339 buildCmdLine2(path, sizeof path, "%s" DIR_SEPARATOR_STRING "{port}" DIR_SEPARATOR_STRING "crt0{objext}", s);
340 if (stat(path, &stat_buf) == 0)
345 setMainValue ("z80crt0", "\"crt0{objext}\"");
349 size_t len = strlen(path) + 3;
351 buf = Safe_alloc(len);
352 SNPRINTF(buf, len, "\"%s\"", path);
353 setMainValue("z80crt0", buf);
359 setMainValue ("z80libspec", "");
360 setMainValue ("z80crt0", "");
363 setMainValue ("z80extralibfiles", (s = joinStrSet(libFilesSet)));
364 Safe_free((void *)s);
365 setMainValue ("z80extralibpaths", (s = joinStrSet(libPathsSet)));
366 Safe_free((void *)s);
370 setMainValue ("z80outputtypeflag", "-z");
371 setMainValue ("z80outext", ".gb");
375 setMainValue ("z80outputtypeflag", "-i");
376 setMainValue ("z80outext", ".ihx");
379 setMainValue ("stdobjdstfilename" , "{dstfilename}{objext}");
380 setMainValue ("stdlinkdstfilename", "{dstfilename}{z80outext}");
382 setMainValue ("z80extraobj", (s = joinStrSet(relFilesSet)));
383 Safe_free((void *)s);
385 sprintf (buffer, "-b_CODE=0x%04X -b_DATA=0x%04X", options.code_loc, options.data_loc);
386 setMainValue ("z80bases", buffer);
390 _finaliseOptions (void)
392 port->mem.default_local_map = data;
393 port->mem.default_globl_map = data;
394 if (_G.asmType == ASM_TYPE_ASXXXX && IS_GB)
395 asm_addTree (&_asxxxx_gb);
401 _setDefaultOptions (void)
404 options.stackAuto = 1;
405 options.mainreturn = 1;
406 /* first the options part */
407 options.intlong_rent = 1;
408 options.float_rent = 1;
409 options.noRegParams = 1;
410 /* Default code and data locations. */
411 options.code_loc = 0x200;
415 options.data_loc = 0xC000;
419 options.data_loc = 0x8000;
422 optimize.global_cse = 1;
427 optimize.loopInvariant = 1;
428 optimize.loopInduction = 1;
434 policy is the function policy
435 params is the parameter format
440 r is 'r' for reentrant, 's' for static functions
441 s is 'c' for callee saves, 'r' for caller saves
442 p is 'p' for profiling on, 'x' for profiling off
444 rr - reentrant, caller saves
446 A combination of register short names and s to signify stack variables.
448 bds - first two args appear in BC and DE, the rest on the stack
449 s - all arguments are on the stack.
452 _mangleSupportFunctionName(char *original)
456 sprintf(buffer, "%s_rr%s_%s", original,
457 options.profile ? "f" : "x",
458 options.noRegParams ? "s" : "bds"
461 return Safe_strdup(buffer);
465 _getRegName (struct regs *reg)
476 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
478 sym_link *test = NULL;
486 if ( IS_LITERAL (left))
489 val = OP_VALUE (IC_LEFT (ic));
491 else if ( IS_LITERAL (right))
494 val = OP_VALUE (IC_RIGHT (ic));
501 if ( getSize (test) <= 2)
509 /* Indicate which extended bit operations this port supports */
511 hasExtBitOp (int op, int size)
519 /* Indicate the expense of an access to an output storage class */
521 oclsExpense (struct memmap *oclass)
523 if (IN_FARSPACE(oclass))
530 #define LINKCMD "link-{port} -nf {dstfilename}"
533 "link-{port} -n -c -- {z80bases} -m -j" \
535 " {z80extralibfiles} {z80extralibpaths}" \
536 " {z80outputtypeflag} \"{linkdstfilename}\"" \
538 " \"{dstfilename}{objext}\"" \
543 "as-{port} -plosgff \"{objdstfilename}\" \"{dstfilename}{asmext}\""
550 "Zilog Z80", /* Target name */
551 NULL, /* Processor name */
555 MODEL_MEDIUM | MODEL_SMALL,
561 "-plosgff", /* Options with debug */
562 "-plosgff", /* Options without debug */
577 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
578 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
603 /* Z80 has no native mul/div commands */
616 0, /* no assembler preamble */
617 NULL, /* no genAssemblerEnd */
618 0, /* no local IVT generation code */
619 0, /* no genXINIT code */
623 _mangleSupportFunctionName,
625 hasExtBitOp, /* hasExtBitOp */
626 oclsExpense, /* oclsExpense */
628 TRUE, /* little endian */
631 1, /* transform <= to ! > */
632 1, /* transform >= to ! < */
633 1, /* transform != to !(a == b) */
635 TRUE, /* Array initializer support. */
636 0, /* no CSE cost estimation yet */
637 _z80_builtins, /* no builtin functions */
638 GPOINTER, /* treat unqualified pointers as "generic" pointers */
639 1, /* reset labelKey to 1 */
640 1, /* globals & local static allowed */
649 "Gameboy Z80-like", /* Target name */
654 MODEL_MEDIUM | MODEL_SMALL,
660 "-plosgff", /* Options with debug */
661 "-plosgff", /* Options without debug */
664 NULL /* no do_assemble function */
677 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
678 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
703 /* gbZ80 has no native mul/div commands */
716 0, /* no assembler preamble */
717 NULL, /* no genAssemblerEnd */
718 0, /* no local IVT generation code */
719 0, /* no genXINIT code */
723 _mangleSupportFunctionName,
725 hasExtBitOp, /* hasExtBitOp */
726 oclsExpense, /* oclsExpense */
728 TRUE, /* little endian */
731 1, /* transform <= to ! > */
732 1, /* transform >= to ! < */
733 1, /* transform != to !(a == b) */
735 TRUE, /* Array initializer support. */
736 0, /* no CSE cost estimation yet */
737 NULL, /* no builtin functions */
738 GPOINTER, /* treat unqualified pointers as "generic" pointers */
739 1, /* reset labelKey to 1 */
740 1, /* globals & local static allowed */