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 -------------------------------------------------------------------------*/
31 static char _z80_defaultRules[] =
34 #include "peeph-z80.rul"
37 static char _gbz80_defaultRules[] =
40 #include "peeph-gbz80.rul"
45 static OPTION _z80_options[] =
47 { 0, "--callee-saves-bc", &z80_opts.calleeSavesBC, "Force a called function to always save BC" },
64 /* determine if we can register a parameter */
69 static char *_keywords[] =
77 extern PORT gbz80_port;
82 static builtins _z80_builtins[] = {
84 { "__builtin_strcpy", "v", 2, {"cg*", "cg*" } },
85 { "__builtin_memcpy", "cg*", 3, {"cg*", "cg*", "ui" } },
87 { NULL , NULL,0, {NULL}}
93 z80_opts.sub = SUB_Z80;
94 asm_addTree (&_asxxxx_z80);
100 z80_opts.sub = SUB_GBZ80;
110 _reg_parm (sym_link * l)
112 if (options.noRegParams)
118 if (_G.regParams == 2)
131 _process_pragma (const char *sz)
133 if (startsWith (sz, "bank="))
136 strcpy (buffer, sz + 5);
138 if (isdigit (buffer[0]))
142 else if (!strcmp (buffer, "BASE"))
144 strcpy (buffer, "HOME");
146 if (isdigit (buffer[0]))
148 /* Arg was a bank number. Handle in an ASM independent
151 strcpy (num, sz + 5);
156 case ASM_TYPE_ASXXXX:
157 sprintf (buffer, "CODE_%s", num);
160 sprintf (buffer, "CODE,BANK[%s]", num);
163 /* PENDING: what to use for ISAS? */
164 sprintf (buffer, "CODE,BANK(%s)", num);
170 gbz80_port.mem.code_name = Safe_strdup (buffer);
171 code->sname = gbz80_port.mem.code_name;
177 static const char *_gbz80_rgbasmCmd[] =
179 "rgbasm", "-o\"$1.o\"", "\"$1.asm\"", NULL
182 static const char *_gbz80_rgblinkCmd[] =
184 "xlink", "-tg", "-n\"$1.sym\"", "-m\"$1.map\"", "-zFF", "\"$1.lnk\"", NULL
188 _gbz80_rgblink (void)
192 /* first we need to create the <filename>.lnk file */
193 sprintf (scratchFileName, "%s.lnk", dstFileName);
194 if (!(lnkfile = fopen (scratchFileName, "w")))
196 werror (E_FILE_OPEN_ERR, scratchFileName);
200 fprintf (lnkfile, "[Objects]\n");
202 fprintf (lnkfile, "%s.o\n", dstFileName);
204 fputStrSet(lnkfile, relFilesSet);
206 fprintf (lnkfile, "\n[Libraries]\n");
207 /* additional libraries if any */
208 fputStrSet(lnkfile, libFilesSet);
210 fprintf (lnkfile, "\n[Output]\n" "%s.gb", dstFileName);
214 buildCmdLine (buffer,port->linker.cmd, dstFileName, NULL, NULL, NULL);
215 /* call the linker */
216 if (my_system (buffer))
218 perror ("Cannot exec linker");
224 _parseOptions (int *pargc, char **argv, int *i)
226 if (argv[*i][0] == '-')
228 if (argv[*i][1] == 'b' && IS_GB)
230 int bank = atoi (argv[*i] + 3);
236 sprintf (buffer, "CODE_%u", bank);
237 gbz80_port.mem.code_name = Safe_strdup (buffer);
241 sprintf (buffer, "DATA_%u", bank);
242 gbz80_port.mem.data_name = Safe_strdup (buffer);
246 else if (!strncmp (argv[*i], "--asm=", 6))
248 if (!strcmp (argv[*i], "--asm=rgbds"))
250 asm_addTree (&_rgbds_gb);
251 gbz80_port.assembler.cmd = _gbz80_rgbasmCmd;
252 gbz80_port.linker.cmd = _gbz80_rgblinkCmd;
253 gbz80_port.linker.do_link = _gbz80_rgblink;
254 _G.asmType = ASM_TYPE_RGBDS;
257 else if (!strcmp (argv[*i], "--asm=asxxxx"))
259 _G.asmType = ASM_TYPE_ASXXXX;
262 else if (!strcmp (argv[*i], "--asm=isas"))
264 asm_addTree (&_isas_gb);
265 /* Munge the function prefix */
266 gbz80_port.fun_prefix = "";
267 _G.asmType = ASM_TYPE_ISAS;
270 else if (!strcmp (argv[*i], "--asm=z80asm"))
272 port->assembler.externGlobal = TRUE;
273 asm_addTree (&_z80asm_z80);
274 _G.asmType = ASM_TYPE_ISAS;
287 if (options.nostdlib == FALSE)
292 setMainValue ("z80libspec", "-l\"{port}.lib\"");
294 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
296 struct stat stat_buf;
298 buildCmdLine2(path, sizeof path, "%s" DIR_SEPARATOR_STRING "{port}" DIR_SEPARATOR_STRING "crt0{objext}", s);
299 if (stat(path, &stat_buf) == 0)
304 setMainValue ("z80crt0", "\"crt0{objext}\"");
308 size_t len = strlen(path) + 3;
310 buf = Safe_alloc(len);
311 SNPRINTF(buf, len, "\"%s\"", path);
312 setMainValue("z80crt0", buf);
318 setMainValue ("z80libspec", "");
319 setMainValue ("z80crt0", "");
322 setMainValue ("z80extralibfiles", (s = joinStrSet(libFilesSet)));
323 Safe_free((void *)s);
324 setMainValue ("z80extralibpaths", (s = joinStrSet(libPathsSet)));
325 Safe_free((void *)s);
329 setMainValue ("z80outputtypeflag", "-z");
330 setMainValue ("z80outext", ".gb");
334 setMainValue ("z80outputtypeflag", "-i");
335 setMainValue ("z80outext", ".ihx");
338 setMainValue ("stdobjdstfilename" , "{dstfilename}{objext}");
339 setMainValue ("stdlinkdstfilename", "{dstfilename}{z80outext}");
341 setMainValue ("z80extraobj", (s = joinStrSet(relFilesSet)));
342 Safe_free((void *)s);
344 sprintf (buffer, "-b_CODE=0x%04X -b_DATA=0x%04X", options.code_loc, options.data_loc);
345 setMainValue ("z80bases", buffer);
349 _finaliseOptions (void)
351 port->mem.default_local_map = data;
352 port->mem.default_globl_map = data;
353 if (_G.asmType == ASM_TYPE_ASXXXX && IS_GB)
354 asm_addTree (&_asxxxx_gb);
360 _setDefaultOptions (void)
363 options.stackAuto = 1;
364 options.mainreturn = 1;
365 /* first the options part */
366 options.intlong_rent = 1;
367 options.float_rent = 1;
368 options.noRegParams = 1;
369 /* Default code and data locations. */
370 options.code_loc = 0x200;
374 options.data_loc = 0xC000;
378 options.data_loc = 0x8000;
381 optimize.global_cse = 1;
386 optimize.loopInvariant = 1;
387 optimize.loopInduction = 1;
393 policy is the function policy
394 params is the parameter format
399 r is 'r' for reentrant, 's' for static functions
400 s is 'c' for callee saves, 'r' for caller saves
401 p is 'p' for profiling on, 'x' for profiling off
403 rr - reentrant, caller saves
405 A combination of register short names and s to signify stack variables.
407 bds - first two args appear in BC and DE, the rest on the stack
408 s - all arguments are on the stack.
411 _mangleSupportFunctionName(char *original)
415 sprintf(buffer, "%s_rr%s_%s", original,
416 options.profile ? "f" : "x",
417 options.noRegParams ? "s" : "bds"
420 return Safe_strdup(buffer);
424 _getRegName (struct regs *reg)
435 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
437 sym_link *test = NULL;
445 if ( IS_LITERAL (left))
448 val = OP_VALUE (IC_LEFT (ic));
450 else if ( IS_LITERAL (right))
453 val = OP_VALUE (IC_RIGHT (ic));
460 if ( getSize (test) <= 2)
469 "link-{port} -n -c -- {z80bases} -m -j" \
471 " {z80extralibfiles} {z80extralibpaths}" \
472 " {z80outputtypeflag} \"{linkdstfilename}\"" \
474 " \"{dstfilename}{objext}\"" \
478 "as-{port} -plosgff \"{objdstfilename}\" \"{dstfilename}{asmext}\""
485 "Zilog Z80", /* Target name */
486 NULL, /* Processor name */
489 MODEL_MEDIUM | MODEL_SMALL,
495 "-plosgff", /* Options with debug */
496 "-plosgff", /* Options without debug */
510 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
511 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
535 /* Z80 has no native mul/div commands */
548 0, /* no assembler preamble */
549 NULL, /* no genAssemblerEnd */
550 0, /* no local IVT generation code */
551 0, /* no genXINIT code */
555 _mangleSupportFunctionName,
560 1, /* transform <= to ! > */
561 1, /* transform >= to ! < */
562 1, /* transform != to !(a == b) */
564 TRUE, /* Array initializer support. */
565 0, /* no CSE cost estimation yet */
566 _z80_builtins, /* no builtin functions */
567 GPOINTER, /* treat unqualified pointers as "generic" pointers */
568 1, /* reset labelKey to 1 */
569 1, /* globals & local static allowed */
578 "Gameboy Z80-like", /* Target name */
582 MODEL_MEDIUM | MODEL_SMALL,
588 "-plosgff", /* Options with debug */
589 "-plosgff", /* Options without debug */
592 NULL /* no do_assemble function */
604 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
605 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
629 /* gbZ80 has no native mul/div commands */
642 0, /* no assembler preamble */
643 NULL, /* no genAssemblerEnd */
644 0, /* no local IVT generation code */
645 0, /* no genXINIT code */
649 _mangleSupportFunctionName,
654 1, /* transform <= to ! > */
655 1, /* transform >= to ! < */
656 1, /* transform != to !(a == b) */
658 TRUE, /* Array initializer support. */
659 0, /* no CSE cost estimation yet */
660 NULL, /* no builtin functions */
661 GPOINTER, /* treat unqualified pointers as "generic" pointers */
662 1, /* reset labelKey to 1 */
663 1, /* globals & local static allowed */