dbb465df01925332b4b3a373c1056ad9f39b71e5
[fw/sdcc] / src / z80 / main.c
1 /*-------------------------------------------------------------------------
2   main.c - Z80 specific definitions.
3
4   Michael Hope <michaelh@juju.net.nz> 2001
5
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
9    later version.
10
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.
15
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.
19
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 -------------------------------------------------------------------------*/
24
25 #include <sys/stat.h>
26 #include "z80.h"
27 #include "MySystem.h"
28 #include "BuildCmd.h"
29 #include "SDCCutil.h"
30 #include "SDCCargs.h"
31 #include "dbuf_string.h"
32
33 #define OPTION_BO              "-bo"
34 #define OPTION_BA              "-ba"
35 #define OPTION_CODE_SEG        "--codeseg"
36 #define OPTION_CONST_SEG       "--constseg"
37 #define OPTION_CALLEE_SAVES_BC "--callee-saves-bc"
38 #define OPTION_PORTMODE        "--portmode="
39 #define OPTION_ASM             "--asm="
40 #define OPTION_NO_STD_CRT0     "--no-std-crt0"
41
42
43 static char _z80_defaultRules[] =
44 {
45 #include "peeph.rul"
46 #include "peeph-z80.rul"
47 };
48
49 static char _gbz80_defaultRules[] =
50 {
51 #include "peeph.rul"
52 #include "peeph-gbz80.rul"
53 };
54
55 Z80_OPTS z80_opts;
56
57 static OPTION _z80_options[] =
58   {
59     { 0, OPTION_CALLEE_SAVES_BC, &z80_opts.calleeSavesBC, "Force a called function to always save BC" },
60     { 0, OPTION_PORTMODE,        NULL, "Determine PORT I/O mode (z80/z180)" },
61     { 0, OPTION_ASM,             NULL, "Define assembler name (rgbds/asxxxx/isas/z80asm)" },
62     { 0, OPTION_CODE_SEG,        &options.code_seg, "<name> use this name for the code segment", CLAT_STRING },
63     { 0, OPTION_CONST_SEG,       &options.const_seg, "<name> use this name for the const segment", CLAT_STRING },
64     { 0, OPTION_NO_STD_CRT0,     &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.o"},
65     { 0, NULL }
66   };
67
68 static OPTION _gbz80_options[] = 
69   {
70     { 0, OPTION_BO,              NULL, "<num> use code bank <num>" },
71     { 0, OPTION_BA,              NULL, "<num> use data bank <num>" },
72     { 0, OPTION_CALLEE_SAVES_BC, &z80_opts.calleeSavesBC, "Force a called function to always save BC" },
73     { 0, OPTION_CODE_SEG,        &options.code_seg, "<name> use this name for the code segment", CLAT_STRING },
74     { 0, OPTION_CONST_SEG,       &options.const_seg, "<name> use this name for the const segment", CLAT_STRING },
75     { 0, OPTION_NO_STD_CRT0,     &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.o"},
76     { 0, NULL }
77   };
78
79 typedef enum
80   {
81     /* Must be first */
82     ASM_TYPE_ASXXXX,
83     ASM_TYPE_RGBDS,
84     ASM_TYPE_ISAS,
85     ASM_TYPE_Z80ASM
86   }
87 ASM_TYPE;
88
89 static struct
90   {
91     ASM_TYPE asmType;
92     /* determine if we can register a parameter */    
93     int regParams;
94   }
95 _G;
96
97 static char *_keywords[] =
98 {
99   "sfr",
100   "nonbanked",
101   "banked",
102   "at",       //.p.t.20030714 adding support for 'sfr at ADDR' construct
103   "_naked",   //.p.t.20030714 adding support for '_naked' functions
104   "critical",
105   "interrupt",
106   NULL
107 };
108
109 extern PORT gbz80_port;
110 extern PORT z80_port;
111
112 #include "mappings.i"
113
114 static builtins _z80_builtins[] = {
115   /* Disabled for now.
116     { "__builtin_strcpy", "v", 2, {"cg*", "cg*" } },*/
117     { "__builtin_memcpy", "vg*", 3, {"vg*", "vg*", "ui" } },
118     { NULL , NULL,0, {NULL}}
119 };
120
121 static void
122 _z80_init (void)
123 {
124   z80_opts.sub = SUB_Z80;
125   asm_addTree (&_asxxxx_z80);
126 }
127
128 static void
129 _gbz80_init (void)
130 {
131   z80_opts.sub = SUB_GBZ80;
132 }
133
134 static void
135 _reset_regparm (void)
136 {
137   _G.regParams = 0;
138 }
139
140 static int
141 _reg_parm (sym_link * l, bool reentrant)
142 {
143   if (options.noRegParams)
144     {
145       return FALSE;
146     }
147   else 
148     {
149       if (_G.regParams == 2)
150         {
151           return FALSE;
152         }
153       else
154         {
155           _G.regParams++;
156           return TRUE;
157         }
158     }
159 }
160
161 enum {
162   P_BANK = 1,
163   P_PORTMODE,
164   P_CODESEG,
165   P_CONSTSEG,
166 };
167
168 static int
169 do_pragma(int id, const char *name, const char *cp)
170 {
171   struct pragma_token_s token;
172   int err = 0;
173   int processed = 1;
174
175   init_pragma_token(&token);
176
177   switch (id)
178     {
179     case P_BANK:
180       {
181         struct dbuf_s buffer;
182
183         dbuf_init(&buffer, 128);
184
185         cp = get_pragma_token(cp, &token);
186
187         switch (token.type)
188           {
189           case TOKEN_EOL:
190             err = 1;
191             break;
192
193           case TOKEN_INT:
194             switch (_G.asmType)
195               {
196               case ASM_TYPE_ASXXXX:
197                 dbuf_printf (&buffer, "CODE_%d", token.val.int_val);
198                 break;
199
200               case ASM_TYPE_RGBDS:
201                 dbuf_printf (&buffer, "CODE,BANK[%d]", token.val.int_val);
202                 break;
203
204               case ASM_TYPE_ISAS:
205                 /* PENDING: what to use for ISAS? */
206                 dbuf_printf (&buffer, "CODE,BANK(%d)", token.val.int_val);
207                 break;
208
209               default:
210                 wassert (0);
211               }
212             break;
213
214           default:
215             {
216               const char *str = get_pragma_string (&token);
217
218               dbuf_append_str (&buffer, (0 == strcmp("BASE", str)) ? "HOME" : str);
219             }
220             break;
221           }
222
223         cp = get_pragma_token (cp, &token);
224         if (TOKEN_EOL != token.type)
225           {
226             err = 1;
227             break;
228           }
229
230         dbuf_c_str (&buffer);
231         /* ugly, see comment in src/port.h (borutr) */
232         gbz80_port.mem.code_name = dbuf_detach (&buffer);
233         code->sname = gbz80_port.mem.code_name;
234         options.code_seg = (char *)gbz80_port.mem.code_name;
235       }
236       break;
237
238     case P_PORTMODE:
239       { /*.p.t.20030716 - adding pragma to manipulate z80 i/o port addressing modes */
240         const char *str;
241
242         cp = get_pragma_token (cp, &token);
243
244         if (TOKEN_EOL == token.type)
245           {
246             err = 1;
247             break;
248           }
249
250         str = get_pragma_string (&token);
251
252         cp = get_pragma_token (cp, &token);
253         if (TOKEN_EOL != token.type)
254           {
255             err = 1;
256             break;
257           }
258
259         if (!strcmp(str, "z80"))
260           { z80_opts.port_mode = 80; }
261         else if(!strcmp(str, "z180"))
262           { z80_opts.port_mode = 180; }
263         else if(!strcmp(str, "save"))
264           { z80_opts.port_back = z80_opts.port_mode; }
265         else if(!strcmp(str, "restore" ))
266           { z80_opts.port_mode = z80_opts.port_back; }
267         else
268           err = 1;
269       }
270       break;
271
272     case P_CODESEG:
273     case P_CONSTSEG:
274       {
275         char *segname;
276
277         cp = get_pragma_token (cp, &token);
278         if (token.type == TOKEN_EOL)
279           {
280             err = 1;
281             break;
282           }
283
284         segname = Safe_strdup (get_pragma_string(&token));
285
286         cp = get_pragma_token (cp, &token);
287         if (token.type != TOKEN_EOL)
288           {
289             Safe_free (segname);
290             err = 1;
291             break;
292           }
293
294         if (id == P_CODESEG)
295           {
296             if (options.code_seg) Safe_free(options.code_seg);
297             options.code_seg = segname;
298           }
299         else
300           {
301             if (options.const_seg) Safe_free(options.const_seg);
302             options.const_seg = segname;
303           }
304       }
305       break;
306
307     default:
308       processed = 0;
309       break;
310   }
311
312   get_pragma_token(cp, &token);
313
314   if (1 == err)
315     werror(W_BAD_PRAGMA_ARGUMENTS, name);
316
317   free_pragma_token(&token);
318   return processed;
319 }
320
321 static struct pragma_s pragma_tbl[] = {
322   { "bank",     P_BANK,     0, do_pragma },
323   { "portmode", P_PORTMODE, 0, do_pragma },
324   { "codeseg",  P_CODESEG,  0, do_pragma },
325   { "constseg", P_CONSTSEG, 0, do_pragma },
326   { NULL,       0,          0, NULL },
327   };
328
329 static int
330 _process_pragma(const char *s)
331 {
332   return process_pragma_tbl(pragma_tbl, s);
333 }
334
335 static const char *_gbz80_rgbasmCmd[] =
336 {
337   "rgbasm", "-o\"$1.o\"", "\"$1.asm\"", NULL
338 };
339
340 static const char *_gbz80_rgblinkCmd[] =
341 {
342   "xlink", "-tg", "-n\"$1.sym\"", "-m\"$1.map\"", "-zFF", "\"$1.lnk\"", NULL
343 };
344
345 static void
346 _gbz80_rgblink (void)
347 {
348   FILE *lnkfile;
349
350   /* first we need to create the <filename>.lnk file */
351   sprintf (scratchFileName, "%s.lnk", dstFileName);
352   if (!(lnkfile = fopen (scratchFileName, "w")))
353     {
354       werror (E_FILE_OPEN_ERR, scratchFileName);
355       exit (1);
356     }
357
358   fprintf (lnkfile, "[Objects]\n");
359
360   fprintf (lnkfile, "%s.o\n", dstFileName);
361
362   fputStrSet(lnkfile, relFilesSet);
363
364   fprintf (lnkfile, "\n[Libraries]\n");
365   /* additional libraries if any */
366   fputStrSet(lnkfile, libFilesSet);
367
368   fprintf (lnkfile, "\n[Output]\n" "%s.gb", dstFileName);
369
370   fclose (lnkfile);
371
372   buildCmdLine (buffer,port->linker.cmd, dstFileName, NULL, NULL, NULL);
373   /* call the linker */
374   if (my_system (buffer))
375     {
376       perror ("Cannot exec linker");
377       exit (1);
378     }
379 }
380
381 static bool
382 _parseOptions (int *pargc, char **argv, int *i)
383 {
384   if (argv[*i][0] == '-')
385     {
386       if (IS_GB)
387         {
388           if (!strncmp (argv[*i], OPTION_BO, sizeof (OPTION_BO) - 1))
389             {
390               /* ROM bank */
391               int bank = getIntArg (OPTION_BO, argv, i, *pargc);
392               struct dbuf_s buffer;
393
394               dbuf_init (&buffer, 16);
395               dbuf_printf (&buffer, "CODE_%u", bank);
396               dbuf_c_str (&buffer);
397               /* ugly, see comment in src/port.h (borutr) */
398               gbz80_port.mem.code_name = dbuf_detach (&buffer);
399               options.code_seg = (char *)gbz80_port.mem.code_name;
400               return TRUE;
401             }
402           else if (!strncmp (argv[*i], OPTION_BA, sizeof (OPTION_BA) - 1))
403             {
404               /* RAM bank */
405               int bank = getIntArg (OPTION_BA, argv, i, *pargc);
406               struct dbuf_s buffer;
407
408               dbuf_init (&buffer, 16);
409               dbuf_printf (&buffer, "DATA_%u", bank);
410               dbuf_c_str (&buffer);
411               /* ugly, see comment in src/port.h (borutr) */
412               gbz80_port.mem.data_name = dbuf_detach (&buffer);
413               return TRUE;
414             }
415         }
416       else if (!strncmp (argv[*i], OPTION_ASM, sizeof (OPTION_ASM) - 1))
417         {
418           char *asmblr = getStringArg (OPTION_ASM, argv, i, *pargc);
419
420           if (!strcmp (asmblr, "rgbds"))
421             {
422               asm_addTree (&_rgbds_gb);
423               gbz80_port.assembler.cmd = _gbz80_rgbasmCmd;
424               gbz80_port.linker.cmd = _gbz80_rgblinkCmd;
425               gbz80_port.linker.do_link = _gbz80_rgblink;
426               _G.asmType = ASM_TYPE_RGBDS;
427               return TRUE;
428             }
429           else if (!strcmp (asmblr, "asxxxx"))
430             {
431               _G.asmType = ASM_TYPE_ASXXXX;
432               return TRUE;
433             }
434           else if (!strcmp (asmblr, "isas"))
435             {
436               asm_addTree (&_isas_gb);
437               /* Munge the function prefix */
438               gbz80_port.fun_prefix = "";
439               _G.asmType = ASM_TYPE_ISAS;
440               return TRUE;
441             }
442           else if (!strcmp (asmblr, "z80asm"))
443             {
444               port->assembler.externGlobal = TRUE;
445               asm_addTree (&_z80asm_z80);
446               _G.asmType = ASM_TYPE_ISAS;
447               return TRUE;
448             }
449         }
450       else if (!strncmp (argv[*i], OPTION_PORTMODE, sizeof (OPTION_PORTMODE) - 1))
451         {
452            char *portmode = getStringArg (OPTION_ASM, argv, i, *pargc);
453
454           if (!strcmp (portmode, "z80"))
455             {
456               z80_opts.port_mode = 80;
457               return TRUE;
458             }
459           else if (!strcmp (portmode, "z180"))
460             {
461               z80_opts.port_mode = 180;
462               return TRUE;
463             }
464         }
465   }
466   return FALSE;
467 }
468
469 static void
470 _setValues(void)
471 {
472   const char *s;
473
474   if (options.nostdlib == FALSE)
475     {
476       const char *s;
477       char path[PATH_MAX];
478       struct dbuf_s dbuf;
479
480       dbuf_init(&dbuf, PATH_MAX);
481
482       for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
483         {
484           buildCmdLine2(path, sizeof path, "-k\"%s" DIR_SEPARATOR_STRING "{port}\" ", s);
485           dbuf_append_str(&dbuf, path);
486         }
487       buildCmdLine2(path, sizeof path, "-l\"{port}.lib\"", s);
488       dbuf_append_str(&dbuf, path);
489
490       setMainValue ("z80libspec", dbuf_c_str(&dbuf));
491       dbuf_destroy(&dbuf);
492
493       for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
494         {
495           struct stat stat_buf;
496
497           buildCmdLine2(path, sizeof path, "%s" DIR_SEPARATOR_STRING "{port}" DIR_SEPARATOR_STRING "crt0{objext}", s);
498           if (stat(path, &stat_buf) == 0)
499             break;
500         }
501
502       if (s == NULL)
503         setMainValue ("z80crt0", "\"crt0{objext}\"");
504       else
505         {
506           char *buf;
507           size_t len = strlen(path) + 3;
508
509           buf = Safe_alloc(len);
510           SNPRINTF(buf, len, "\"%s\"", path);
511           setMainValue("z80crt0", buf);
512           Safe_free(buf);
513         }
514     }
515   else
516     {
517       setMainValue ("z80libspec", "");
518       setMainValue ("z80crt0", "");
519     }
520
521   setMainValue ("z80extralibfiles", (s = joinStrSet(libFilesSet)));
522   Safe_free((void *)s);
523   setMainValue ("z80extralibpaths", (s = joinStrSet(libPathsSet)));
524   Safe_free((void *)s);
525
526   if (IS_GB)
527     {
528       setMainValue ("z80outputtypeflag", "-Z");
529       setMainValue ("z80outext", ".gb");
530     }
531   else
532     {
533       setMainValue ("z80outputtypeflag", "-i");
534       setMainValue ("z80outext", ".ihx");
535     }
536
537   setMainValue ("stdobjdstfilename" , "{dstfilename}{objext}");
538   setMainValue ("stdlinkdstfilename", "{dstfilename}{z80outext}");
539
540   setMainValue ("z80extraobj", (s = joinStrSet(relFilesSet)));
541   Safe_free((void *)s);
542
543   sprintf (buffer, "-b_CODE=0x%04X -b_DATA=0x%04X", options.code_loc, options.data_loc);
544   setMainValue ("z80bases", buffer);
545 }
546
547 static void
548 _finaliseOptions (void)
549 {
550   port->mem.default_local_map = data;
551   port->mem.default_globl_map = data;
552   if (_G.asmType == ASM_TYPE_ASXXXX && IS_GB)
553     asm_addTree (&_asxxxx_gb);
554
555   _setValues();
556 }
557
558 static void
559 _setDefaultOptions (void)
560 {
561   options.nopeep = 0;
562   options.stackAuto = 1;
563   options.mainreturn = 1;
564   /* first the options part */
565   options.intlong_rent = 1;
566   options.float_rent = 1;
567   options.noRegParams = 1;
568   /* Default code and data locations. */
569   options.code_loc = 0x200;
570
571   if (IS_GB) 
572     {
573       options.data_loc = 0xC000;
574     }
575   else
576     {
577       options.data_loc = 0x8000;
578     }
579
580   optimize.global_cse = 1;
581   optimize.label1 = 1;
582   optimize.label2 = 1;
583   optimize.label3 = 1;
584   optimize.label4 = 1;
585   optimize.loopInvariant = 1;
586   optimize.loopInduction = 1;
587 }
588
589 /* Mangling format:
590     _fun_policy_params
591     where:
592       policy is the function policy
593       params is the parameter format
594
595    policy format:
596     rsp
597     where:
598       r is 'r' for reentrant, 's' for static functions
599       s is 'c' for callee saves, 'r' for caller saves
600       f is 'f' for profiling on, 'x' for profiling off
601     examples:
602       rr - reentrant, caller saves
603    params format:
604     A combination of register short names and s to signify stack variables.
605     examples:
606       bds - first two args appear in BC and DE, the rest on the stack
607       s - all arguments are on the stack.
608 */
609 static char *
610 _mangleSupportFunctionName(char *original)
611 {
612   char buffer[128];
613
614   sprintf(buffer, "%s_rr%s_%s", original,
615           options.profile ? "f" : "x",
616           options.noRegParams ? "s" : "bds" /* MB: but the library only has hds variants ??? */
617           );
618
619   return Safe_strdup(buffer);
620 }
621
622 static const char *
623 _getRegName (struct regs *reg)
624 {
625   if (reg)
626     {
627       return reg->name;
628     }
629   /*  assert (0); */
630   return "err";
631 }
632
633 static bool
634 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
635 {
636   sym_link *test = NULL;
637   value *val;
638
639   if ( ic->op != '*')
640     {
641       return FALSE;
642     }
643
644   if ( IS_LITERAL (left))
645     {
646       test = left;
647       val = OP_VALUE (IC_LEFT (ic));
648     }
649   else if ( IS_LITERAL (right))
650     {
651       test = right;
652       val = OP_VALUE (IC_RIGHT (ic));
653     }
654   /* 8x8 unsigned multiplication code is shorter than
655      call overhead for the multiplication routine. */
656   else if ( IS_CHAR (right) && IS_UNSIGNED (right) &&
657     IS_CHAR (left) && IS_UNSIGNED(left) && !IS_GB)
658     {
659       return TRUE;
660     }
661   else
662     {
663       return FALSE;
664     }
665
666   if ( getSize (test) <= 2)
667     {
668       return TRUE;
669     }
670
671   return FALSE;
672 }
673
674 /* Indicate which extended bit operations this port supports */
675 static bool
676 hasExtBitOp (int op, int size)
677 {
678   if (op == GETHBIT)
679     return TRUE;
680   else
681     return FALSE;
682 }
683
684 /* Indicate the expense of an access to an output storage class */
685 static int
686 oclsExpense (struct memmap *oclass)
687 {
688   if (IN_FARSPACE(oclass))
689     return 1;
690     
691   return 0;
692 }
693
694
695 #define LINKCMD "link-{port} -nf {dstfilename}"
696 /*
697 #define LINKCMD \
698     "link-{port} -n -c -- {z80bases} -m -j" \
699     " {z80libspec}" \
700     " {z80extralibfiles} {z80extralibpaths}" \
701     " {z80outputtypeflag} \"{linkdstfilename}\"" \
702     " {z80crt0}" \
703     " \"{dstfilename}{objext}\"" \
704     " {z80extraobj}"
705 */
706
707 #define ASMCMD \
708     "as-{port} -plosgff \"{objdstfilename}\" \"{dstfilename}{asmext}\""
709
710 /* Globals */
711 PORT z80_port =
712 {
713   TARGET_ID_Z80,
714   "z80",
715   "Zilog Z80",                  /* Target name */
716   NULL,                         /* Processor name */
717   {
718     glue,
719     FALSE,
720     MODEL_MEDIUM | MODEL_SMALL,
721     MODEL_SMALL
722   },
723   {                             /* Assembler */
724     NULL,
725     ASMCMD,
726     "-plosgffc",                /* Options with debug */
727     "-plosgff",                 /* Options without debug */
728     0,
729     ".asm"
730   },
731   {                             /* Linker */
732     NULL,
733     LINKCMD,
734     NULL,
735     ".o",
736     1
737   },
738   {                             /* Peephole optimizer */
739     _z80_defaultRules,
740     0,
741     0,
742     0,
743     0,
744     z80notUsed
745   },
746   {
747         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
748     1, 2, 2, 4, 2, 2, 2, 1, 4, 4
749   },
750   /* tags for generic pointers */
751   { 0x00, 0x40, 0x60, 0x80 },           /* far, near, xstack, code */
752   {
753     "XSEG",
754     "STACK",
755     "CODE",
756     "DATA",
757     "ISEG",
758     NULL, /* pdata */
759     "XSEG",
760     "BSEG",
761     "RSEG",
762     "GSINIT",
763     "OVERLAY",
764     "GSFINAL",
765     "HOME",
766     NULL, /* xidata */
767     NULL, /* xinit */
768     NULL, /* const_name */
769     "CABS", /* cabs_name */
770     NULL, /* xabs_name */
771     NULL, /* iabs_name */
772     NULL,
773     NULL,
774     1
775   },
776   { NULL, NULL },
777   {
778     -1, 0, 0, 4, 0, 2
779   },
780     /* Z80 has no native mul/div commands */
781   {
782     0, 2
783   },
784   {
785     z80_emitDebuggerSymbol
786   },
787   {
788     255,        /* maxCount */
789     3,          /* sizeofElement */
790     /* The rest of these costs are bogus. They approximate */
791     /* the behavior of src/SDCCicode.c 1.207 and earlier.  */
792     {4,4,4},    /* sizeofMatchJump[] */
793     {0,0,0},    /* sizeofRangeCompare[] */
794     0,          /* sizeofSubtract */
795     3,          /* sizeofDispatch */
796   },
797   "_",
798   _z80_init,
799   _parseOptions,
800   _z80_options,
801   NULL,
802   _finaliseOptions,
803   _setDefaultOptions,
804   z80_assignRegisters,
805   _getRegName,
806   _keywords,
807   0,                            /* no assembler preamble */
808   NULL,                         /* no genAssemblerEnd */
809   0,                            /* no local IVT generation code */
810   0,                            /* no genXINIT code */
811   NULL,                         /* genInitStartup */
812   _reset_regparm,
813   _reg_parm,
814   _process_pragma,
815   _mangleSupportFunctionName,
816   _hasNativeMulFor,
817   hasExtBitOp,                  /* hasExtBitOp */
818   oclsExpense,                  /* oclsExpense */
819   TRUE,
820   TRUE,                         /* little endian */
821   0,                            /* leave lt */
822   0,                            /* leave gt */
823   1,                            /* transform <= to ! > */
824   1,                            /* transform >= to ! < */
825   1,                            /* transform != to !(a == b) */
826   0,                            /* leave == */
827   TRUE,                         /* Array initializer support. */
828   0,                            /* no CSE cost estimation yet */
829   _z80_builtins,                /* builtin functions */
830   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
831   1,                            /* reset labelKey to 1 */
832   1,                            /* globals & local static allowed */
833   PORT_MAGIC
834 };
835
836 /* Globals */
837 PORT gbz80_port =
838 {
839   TARGET_ID_GBZ80,
840   "gbz80",
841   "Gameboy Z80-like",           /* Target name */
842   NULL,
843   {
844     glue,
845     FALSE,
846     MODEL_MEDIUM | MODEL_SMALL,
847     MODEL_SMALL
848   },
849   {
850     NULL,
851     ASMCMD,
852     "-plosgffc",                /* Options with debug */
853     "-plosgff",                 /* Options without debug */
854     0,
855     ".asm",
856     NULL                        /* no do_assemble function */
857   },
858   {
859     NULL,
860     LINKCMD,
861     NULL,
862     ".o",
863     1
864   },
865   {
866     _gbz80_defaultRules
867   },
868   {
869     /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
870     1, 2, 2, 4, 2, 2, 2, 1, 4, 4
871   },
872   /* tags for generic pointers */
873   { 0x00, 0x40, 0x60, 0x80 },           /* far, near, xstack, code */
874   {
875     "XSEG",
876     "STACK",
877     "CODE",
878     "DATA",
879     "ISEG",
880     NULL, /* pdata */
881     "XSEG",
882     "BSEG",
883     "RSEG",
884     "GSINIT",
885     "OVERLAY",
886     "GSFINAL",
887     "HOME",
888     NULL, /* xidata */
889     NULL, /* xinit */
890     NULL, /* const_name */
891     "CABS", /* cabs_name */
892     NULL, /* xabs_name */
893     NULL, /* iabs_name */
894     NULL,
895     NULL,
896     1
897   },
898   { NULL, NULL },
899   {
900     -1, 0, 0, 2, 0, 4
901   },
902     /* gbZ80 has no native mul/div commands */
903   {
904     0, 2
905   },
906   {
907     z80_emitDebuggerSymbol
908   },
909   {
910     255,        /* maxCount */
911     3,          /* sizeofElement */
912     /* The rest of these costs are bogus. They approximate */
913     /* the behavior of src/SDCCicode.c 1.207 and earlier.  */
914     {4,4,4},    /* sizeofMatchJump[] */
915     {0,0,0},    /* sizeofRangeCompare[] */
916     0,          /* sizeofSubtract */
917     3,          /* sizeofDispatch */
918   },
919   "_",
920   _gbz80_init,
921   _parseOptions,
922   _gbz80_options,
923   NULL,
924   _finaliseOptions,
925   _setDefaultOptions,
926   z80_assignRegisters,
927   _getRegName,
928   _keywords,
929   0,                            /* no assembler preamble */
930   NULL,                         /* no genAssemblerEnd */
931   0,                            /* no local IVT generation code */
932   0,                            /* no genXINIT code */
933   NULL,                         /* genInitStartup */
934   _reset_regparm,
935   _reg_parm,
936   _process_pragma,
937   _mangleSupportFunctionName,
938   _hasNativeMulFor,
939   hasExtBitOp,                  /* hasExtBitOp */
940   oclsExpense,                  /* oclsExpense */
941   TRUE,
942   TRUE,                         /* little endian */
943   0,                            /* leave lt */
944   0,                            /* leave gt */
945   1,                            /* transform <= to ! > */
946   1,                            /* transform >= to ! < */
947   1,                            /* transform != to !(a == b) */
948   0,                            /* leave == */
949   TRUE,                         /* Array initializer support. */
950   0,                            /* no CSE cost estimation yet */
951   NULL,                         /* no builtin functions */
952   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
953   1,                            /* reset labelKey to 1 */
954   1,                            /* globals & local static allowed */
955   PORT_MAGIC
956 };