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" },
65 /* determine if we can register a parameter */
70 static char *_keywords[] =
78 extern PORT gbz80_port;
83 static builtins _z80_builtins[] = {
85 { "__builtin_strcpy", "v", 2, {"cg*", "cg*" } },
86 { "__builtin_memcpy", "cg*", 3, {"cg*", "cg*", "ui" } },
88 { NULL , NULL,0, {NULL}}
94 z80_opts.sub = SUB_Z80;
95 asm_addTree (&_asxxxx_z80);
101 z80_opts.sub = SUB_GBZ80;
111 _reg_parm (sym_link * l)
113 if (options.noRegParams)
119 if (_G.regParams == 2)
132 _process_pragma (const char *sz)
134 if (startsWith (sz, "bank="))
137 strcpy (buffer, sz + 5);
139 if (isdigit (buffer[0]))
143 else if (!strcmp (buffer, "BASE"))
145 strcpy (buffer, "HOME");
147 if (isdigit (buffer[0]))
149 /* Arg was a bank number. Handle in an ASM independent
152 strcpy (num, sz + 5);
157 case ASM_TYPE_ASXXXX:
158 sprintf (buffer, "CODE_%s", num);
161 sprintf (buffer, "CODE,BANK[%s]", num);
164 /* PENDING: what to use for ISAS? */
165 sprintf (buffer, "CODE,BANK(%s)", num);
171 gbz80_port.mem.code_name = Safe_strdup (buffer);
172 code->sname = gbz80_port.mem.code_name;
178 static const char *_gbz80_rgbasmCmd[] =
180 "rgbasm", "-o\"$1.o\"", "\"$1.asm\"", NULL
183 static const char *_gbz80_rgblinkCmd[] =
185 "xlink", "-tg", "-n\"$1.sym\"", "-m\"$1.map\"", "-zFF", "\"$1.lnk\"", NULL
189 _gbz80_rgblink (void)
193 /* first we need to create the <filename>.lnk file */
194 sprintf (scratchFileName, "%s.lnk", dstFileName);
195 if (!(lnkfile = fopen (scratchFileName, "w")))
197 werror (E_FILE_OPEN_ERR, scratchFileName);
201 fprintf (lnkfile, "[Objects]\n");
203 fprintf (lnkfile, "%s.o\n", dstFileName);
205 fputStrSet(lnkfile, relFilesSet);
207 fprintf (lnkfile, "\n[Libraries]\n");
208 /* additional libraries if any */
209 fputStrSet(lnkfile, libFilesSet);
211 fprintf (lnkfile, "\n[Output]\n" "%s.gb", dstFileName);
215 buildCmdLine (buffer,port->linker.cmd, dstFileName, NULL, NULL, NULL);
216 /* call the linker */
217 if (my_system (buffer))
219 perror ("Cannot exec linker");
225 _parseOptions (int *pargc, char **argv, int *i)
227 if (argv[*i][0] == '-')
229 if (argv[*i][1] == 'b' && IS_GB)
231 int bank = atoi (argv[*i] + 3);
237 sprintf (buffer, "CODE_%u", bank);
238 gbz80_port.mem.code_name = Safe_strdup (buffer);
242 sprintf (buffer, "DATA_%u", bank);
243 gbz80_port.mem.data_name = Safe_strdup (buffer);
247 else if (!strncmp (argv[*i], "--asm=", 6))
249 if (!strcmp (argv[*i], "--asm=rgbds"))
251 asm_addTree (&_rgbds_gb);
252 gbz80_port.assembler.cmd = _gbz80_rgbasmCmd;
253 gbz80_port.linker.cmd = _gbz80_rgblinkCmd;
254 gbz80_port.linker.do_link = _gbz80_rgblink;
255 _G.asmType = ASM_TYPE_RGBDS;
258 else if (!strcmp (argv[*i], "--asm=asxxxx"))
260 _G.asmType = ASM_TYPE_ASXXXX;
263 else if (!strcmp (argv[*i], "--asm=isas"))
265 asm_addTree (&_isas_gb);
266 /* Munge the function prefix */
267 gbz80_port.fun_prefix = "";
268 _G.asmType = ASM_TYPE_ISAS;
271 else if (!strcmp (argv[*i], "--asm=z80asm"))
273 port->assembler.externGlobal = TRUE;
274 asm_addTree (&_z80asm_z80);
275 _G.asmType = ASM_TYPE_ISAS;
288 if (options.nostdlib == FALSE)
294 dbuf_init(&dbuf, PATH_MAX);
296 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
298 buildCmdLine2(path, sizeof path, "-k\"%s" DIR_SEPARATOR_STRING "{port}\" ", s);
299 dbuf_append(&dbuf, path, strlen(path));
301 buildCmdLine2(path, sizeof path, "-l\"{port}.lib\"", s);
302 dbuf_append(&dbuf, path, strlen(path));
304 setMainValue ("z80libspec", dbuf_c_str(&dbuf));
307 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
309 struct stat stat_buf;
311 buildCmdLine2(path, sizeof path, "%s" DIR_SEPARATOR_STRING "{port}" DIR_SEPARATOR_STRING "crt0{objext}", s);
312 if (stat(path, &stat_buf) == 0)
317 setMainValue ("z80crt0", "\"crt0{objext}\"");
321 size_t len = strlen(path) + 3;
323 buf = Safe_alloc(len);
324 SNPRINTF(buf, len, "\"%s\"", path);
325 setMainValue("z80crt0", buf);
331 setMainValue ("z80libspec", "");
332 setMainValue ("z80crt0", "");
335 setMainValue ("z80extralibfiles", (s = joinStrSet(libFilesSet)));
336 Safe_free((void *)s);
337 setMainValue ("z80extralibpaths", (s = joinStrSet(libPathsSet)));
338 Safe_free((void *)s);
342 setMainValue ("z80outputtypeflag", "-z");
343 setMainValue ("z80outext", ".gb");
347 setMainValue ("z80outputtypeflag", "-i");
348 setMainValue ("z80outext", ".ihx");
351 setMainValue ("stdobjdstfilename" , "{dstfilename}{objext}");
352 setMainValue ("stdlinkdstfilename", "{dstfilename}{z80outext}");
354 setMainValue ("z80extraobj", (s = joinStrSet(relFilesSet)));
355 Safe_free((void *)s);
357 sprintf (buffer, "-b_CODE=0x%04X -b_DATA=0x%04X", options.code_loc, options.data_loc);
358 setMainValue ("z80bases", buffer);
362 _finaliseOptions (void)
364 port->mem.default_local_map = data;
365 port->mem.default_globl_map = data;
366 if (_G.asmType == ASM_TYPE_ASXXXX && IS_GB)
367 asm_addTree (&_asxxxx_gb);
373 _setDefaultOptions (void)
376 options.stackAuto = 1;
377 options.mainreturn = 1;
378 /* first the options part */
379 options.intlong_rent = 1;
380 options.float_rent = 1;
381 options.noRegParams = 1;
382 /* Default code and data locations. */
383 options.code_loc = 0x200;
387 options.data_loc = 0xC000;
391 options.data_loc = 0x8000;
394 optimize.global_cse = 1;
399 optimize.loopInvariant = 1;
400 optimize.loopInduction = 1;
406 policy is the function policy
407 params is the parameter format
412 r is 'r' for reentrant, 's' for static functions
413 s is 'c' for callee saves, 'r' for caller saves
414 p is 'p' for profiling on, 'x' for profiling off
416 rr - reentrant, caller saves
418 A combination of register short names and s to signify stack variables.
420 bds - first two args appear in BC and DE, the rest on the stack
421 s - all arguments are on the stack.
424 _mangleSupportFunctionName(char *original)
428 sprintf(buffer, "%s_rr%s_%s", original,
429 options.profile ? "f" : "x",
430 options.noRegParams ? "s" : "bds"
433 return Safe_strdup(buffer);
437 _getRegName (struct regs *reg)
448 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
450 sym_link *test = NULL;
458 if ( IS_LITERAL (left))
461 val = OP_VALUE (IC_LEFT (ic));
463 else if ( IS_LITERAL (right))
466 val = OP_VALUE (IC_RIGHT (ic));
473 if ( getSize (test) <= 2)
482 #define LINKCMD "link-{port} -nf {dstfilename}"
485 "link-{port} -n -c -- {z80bases} -m -j" \
487 " {z80extralibfiles} {z80extralibpaths}" \
488 " {z80outputtypeflag} \"{linkdstfilename}\"" \
490 " \"{dstfilename}{objext}\"" \
495 "as-{port} -plosgff \"{objdstfilename}\" \"{dstfilename}{asmext}\""
502 "Zilog Z80", /* Target name */
503 NULL, /* Processor name */
507 MODEL_MEDIUM | MODEL_SMALL,
513 "-plosgff", /* Options with debug */
514 "-plosgff", /* Options without debug */
528 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
529 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
554 /* Z80 has no native mul/div commands */
567 0, /* no assembler preamble */
568 NULL, /* no genAssemblerEnd */
569 0, /* no local IVT generation code */
570 0, /* no genXINIT code */
574 _mangleSupportFunctionName,
579 1, /* transform <= to ! > */
580 1, /* transform >= to ! < */
581 1, /* transform != to !(a == b) */
583 TRUE, /* Array initializer support. */
584 0, /* no CSE cost estimation yet */
585 _z80_builtins, /* no builtin functions */
586 GPOINTER, /* treat unqualified pointers as "generic" pointers */
587 1, /* reset labelKey to 1 */
588 1, /* globals & local static allowed */
597 "Gameboy Z80-like", /* Target name */
602 MODEL_MEDIUM | MODEL_SMALL,
608 "-plosgff", /* Options with debug */
609 "-plosgff", /* Options without debug */
612 NULL /* no do_assemble function */
624 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
625 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
650 /* gbZ80 has no native mul/div commands */
663 0, /* no assembler preamble */
664 NULL, /* no genAssemblerEnd */
665 0, /* no local IVT generation code */
666 0, /* no genXINIT code */
670 _mangleSupportFunctionName,
675 1, /* transform <= to ! > */
676 1, /* transform >= to ! < */
677 1, /* transform != to !(a == b) */
679 TRUE, /* Array initializer support. */
680 0, /* no CSE cost estimation yet */
681 NULL, /* no builtin functions */
682 GPOINTER, /* treat unqualified pointers as "generic" pointers */
683 1, /* reset labelKey to 1 */
684 1, /* globals & local static allowed */