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