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=" ))
139 strcpy (buffer, sz + 5);
141 if (isdigit (buffer[0]))
145 else if (!strcmp (buffer, "BASE"))
147 strcpy (buffer, "HOME");
149 if (isdigit (buffer[0]))
151 /* Arg was a bank number. Handle in an ASM independent
154 strcpy (num, sz + 5);
159 case ASM_TYPE_ASXXXX:
160 sprintf (buffer, "CODE_%s", num);
163 sprintf (buffer, "CODE,BANK[%s]", num);
166 /* PENDING: what to use for ISAS? */
167 sprintf (buffer, "CODE,BANK(%s)", num);
173 gbz80_port.mem.code_name = Safe_strdup (buffer);
174 code->sname = gbz80_port.mem.code_name;
177 else if( startsWith( sz, "portmode=" ))
178 { /*.p.t.20030716 - adding pragma to manipulate z80 i/o port addressing modes */
181 strcpy( bfr, sz + 9 );
184 if ( !strcmp( bfr, "z80" )){ z80_opts.port_mode = 80; }
185 else if( !strcmp( bfr, "z180" )){ z80_opts.port_mode = 180; }
186 else if( !strcmp( bfr, "save" )){ z80_opts.port_back = z80_opts.port_mode; }
187 else if( !strcmp( bfr, "restore" )){ z80_opts.port_mode = z80_opts.port_back; }
196 static const char *_gbz80_rgbasmCmd[] =
198 "rgbasm", "-o\"$1.o\"", "\"$1.asm\"", NULL
201 static const char *_gbz80_rgblinkCmd[] =
203 "xlink", "-tg", "-n\"$1.sym\"", "-m\"$1.map\"", "-zFF", "\"$1.lnk\"", NULL
207 _gbz80_rgblink (void)
211 /* first we need to create the <filename>.lnk file */
212 sprintf (scratchFileName, "%s.lnk", dstFileName);
213 if (!(lnkfile = fopen (scratchFileName, "w")))
215 werror (E_FILE_OPEN_ERR, scratchFileName);
219 fprintf (lnkfile, "[Objects]\n");
221 fprintf (lnkfile, "%s.o\n", dstFileName);
223 fputStrSet(lnkfile, relFilesSet);
225 fprintf (lnkfile, "\n[Libraries]\n");
226 /* additional libraries if any */
227 fputStrSet(lnkfile, libFilesSet);
229 fprintf (lnkfile, "\n[Output]\n" "%s.gb", dstFileName);
233 buildCmdLine (buffer,port->linker.cmd, dstFileName, NULL, NULL, NULL);
234 /* call the linker */
235 if (my_system (buffer))
237 perror ("Cannot exec linker");
243 _parseOptions (int *pargc, char **argv, int *i)
245 if (argv[*i][0] == '-')
247 if (argv[*i][1] == 'b' && IS_GB)
249 int bank = atoi (argv[*i] + 3);
255 sprintf (buffer, "CODE_%u", bank);
256 gbz80_port.mem.code_name = Safe_strdup (buffer);
260 sprintf (buffer, "DATA_%u", bank);
261 gbz80_port.mem.data_name = Safe_strdup (buffer);
265 else if (!strncmp (argv[*i], "--asm=", 6))
267 if (!strcmp (argv[*i], "--asm=rgbds"))
269 asm_addTree (&_rgbds_gb);
270 gbz80_port.assembler.cmd = _gbz80_rgbasmCmd;
271 gbz80_port.linker.cmd = _gbz80_rgblinkCmd;
272 gbz80_port.linker.do_link = _gbz80_rgblink;
273 _G.asmType = ASM_TYPE_RGBDS;
276 else if (!strcmp (argv[*i], "--asm=asxxxx"))
278 _G.asmType = ASM_TYPE_ASXXXX;
281 else if (!strcmp (argv[*i], "--asm=isas"))
283 asm_addTree (&_isas_gb);
284 /* Munge the function prefix */
285 gbz80_port.fun_prefix = "";
286 _G.asmType = ASM_TYPE_ISAS;
289 else if (!strcmp (argv[*i], "--asm=z80asm"))
291 port->assembler.externGlobal = TRUE;
292 asm_addTree (&_z80asm_z80);
293 _G.asmType = ASM_TYPE_ISAS;
306 if (options.nostdlib == FALSE)
312 dbuf_init(&dbuf, PATH_MAX);
314 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
316 buildCmdLine2(path, sizeof path, "-k\"%s" DIR_SEPARATOR_STRING "{port}\" ", s);
317 dbuf_append(&dbuf, path, strlen(path));
319 buildCmdLine2(path, sizeof path, "-l\"{port}.lib\"", s);
320 dbuf_append(&dbuf, path, strlen(path));
322 setMainValue ("z80libspec", dbuf_c_str(&dbuf));
325 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
327 struct stat stat_buf;
329 buildCmdLine2(path, sizeof path, "%s" DIR_SEPARATOR_STRING "{port}" DIR_SEPARATOR_STRING "crt0{objext}", s);
330 if (stat(path, &stat_buf) == 0)
335 setMainValue ("z80crt0", "\"crt0{objext}\"");
339 size_t len = strlen(path) + 3;
341 buf = Safe_alloc(len);
342 SNPRINTF(buf, len, "\"%s\"", path);
343 setMainValue("z80crt0", buf);
349 setMainValue ("z80libspec", "");
350 setMainValue ("z80crt0", "");
353 setMainValue ("z80extralibfiles", (s = joinStrSet(libFilesSet)));
354 Safe_free((void *)s);
355 setMainValue ("z80extralibpaths", (s = joinStrSet(libPathsSet)));
356 Safe_free((void *)s);
360 setMainValue ("z80outputtypeflag", "-z");
361 setMainValue ("z80outext", ".gb");
365 setMainValue ("z80outputtypeflag", "-i");
366 setMainValue ("z80outext", ".ihx");
369 setMainValue ("stdobjdstfilename" , "{dstfilename}{objext}");
370 setMainValue ("stdlinkdstfilename", "{dstfilename}{z80outext}");
372 setMainValue ("z80extraobj", (s = joinStrSet(relFilesSet)));
373 Safe_free((void *)s);
375 sprintf (buffer, "-b_CODE=0x%04X -b_DATA=0x%04X", options.code_loc, options.data_loc);
376 setMainValue ("z80bases", buffer);
380 _finaliseOptions (void)
382 port->mem.default_local_map = data;
383 port->mem.default_globl_map = data;
384 if (_G.asmType == ASM_TYPE_ASXXXX && IS_GB)
385 asm_addTree (&_asxxxx_gb);
391 _setDefaultOptions (void)
394 options.stackAuto = 1;
395 options.mainreturn = 1;
396 /* first the options part */
397 options.intlong_rent = 1;
398 options.float_rent = 1;
399 options.noRegParams = 1;
400 /* Default code and data locations. */
401 options.code_loc = 0x200;
405 options.data_loc = 0xC000;
409 options.data_loc = 0x8000;
412 optimize.global_cse = 1;
417 optimize.loopInvariant = 1;
418 optimize.loopInduction = 1;
424 policy is the function policy
425 params is the parameter format
430 r is 'r' for reentrant, 's' for static functions
431 s is 'c' for callee saves, 'r' for caller saves
432 p is 'p' for profiling on, 'x' for profiling off
434 rr - reentrant, caller saves
436 A combination of register short names and s to signify stack variables.
438 bds - first two args appear in BC and DE, the rest on the stack
439 s - all arguments are on the stack.
442 _mangleSupportFunctionName(char *original)
446 sprintf(buffer, "%s_rr%s_%s", original,
447 options.profile ? "f" : "x",
448 options.noRegParams ? "s" : "bds"
451 return Safe_strdup(buffer);
455 _getRegName (struct regs *reg)
466 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
468 sym_link *test = NULL;
476 if ( IS_LITERAL (left))
479 val = OP_VALUE (IC_LEFT (ic));
481 else if ( IS_LITERAL (right))
484 val = OP_VALUE (IC_RIGHT (ic));
491 if ( getSize (test) <= 2)
499 /* Indicate which extended bit operations this port supports */
501 hasExtBitOp (int op, int size)
509 /* Indicate the expense of an access to an output storage class */
511 oclsExpense (struct memmap *oclass)
513 if (IN_FARSPACE(oclass))
520 #define LINKCMD "link-{port} -nf {dstfilename}"
523 "link-{port} -n -c -- {z80bases} -m -j" \
525 " {z80extralibfiles} {z80extralibpaths}" \
526 " {z80outputtypeflag} \"{linkdstfilename}\"" \
528 " \"{dstfilename}{objext}\"" \
533 "as-{port} -plosgff \"{objdstfilename}\" \"{dstfilename}{asmext}\""
540 "Zilog Z80", /* Target name */
541 NULL, /* Processor name */
545 MODEL_MEDIUM | MODEL_SMALL,
551 "-plosgff", /* Options with debug */
552 "-plosgff", /* Options without debug */
567 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
568 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
593 /* Z80 has no native mul/div commands */
606 0, /* no assembler preamble */
607 NULL, /* no genAssemblerEnd */
608 0, /* no local IVT generation code */
609 0, /* no genXINIT code */
613 _mangleSupportFunctionName,
615 hasExtBitOp, /* hasExtBitOp */
616 oclsExpense, /* oclsExpense */
618 TRUE, /* little endian */
621 1, /* transform <= to ! > */
622 1, /* transform >= to ! < */
623 1, /* transform != to !(a == b) */
625 TRUE, /* Array initializer support. */
626 0, /* no CSE cost estimation yet */
627 _z80_builtins, /* no builtin functions */
628 GPOINTER, /* treat unqualified pointers as "generic" pointers */
629 1, /* reset labelKey to 1 */
630 1, /* globals & local static allowed */
639 "Gameboy Z80-like", /* Target name */
644 MODEL_MEDIUM | MODEL_SMALL,
650 "-plosgff", /* Options with debug */
651 "-plosgff", /* Options without debug */
654 NULL /* no do_assemble function */
667 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
668 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
693 /* gbZ80 has no native mul/div commands */
706 0, /* no assembler preamble */
707 NULL, /* no genAssemblerEnd */
708 0, /* no local IVT generation code */
709 0, /* no genXINIT code */
713 _mangleSupportFunctionName,
715 hasExtBitOp, /* hasExtBitOp */
716 oclsExpense, /* oclsExpense */
718 TRUE, /* little endian */
721 1, /* transform <= to ! > */
722 1, /* transform >= to ! < */
723 1, /* transform != to !(a == b) */
725 TRUE, /* Array initializer support. */
726 0, /* no CSE cost estimation yet */
727 NULL, /* no builtin functions */
728 GPOINTER, /* treat unqualified pointers as "generic" pointers */
729 1, /* reset labelKey to 1 */
730 1, /* globals & local static allowed */