Implemented RFE #1899189
[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", "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   }
467   return FALSE;
468 }
469
470 static void
471 _setValues(void)
472 {
473   const char *s;
474
475   if (options.nostdlib == FALSE)
476     {
477       const char *s;
478       char path[PATH_MAX];
479       struct dbuf_s dbuf;
480
481       dbuf_init(&dbuf, PATH_MAX);
482
483       for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
484         {
485           buildCmdLine2(path, sizeof path, "-k\"%s" DIR_SEPARATOR_STRING "{port}\" ", s);
486           dbuf_append_str(&dbuf, path);
487         }
488       buildCmdLine2(path, sizeof path, "-l\"{port}.lib\"", s);
489       dbuf_append_str(&dbuf, path);
490
491       setMainValue ("z80libspec", dbuf_c_str(&dbuf));
492       dbuf_destroy(&dbuf);
493
494       for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
495         {
496           struct stat stat_buf;
497
498           buildCmdLine2(path, sizeof path, "%s" DIR_SEPARATOR_STRING "{port}" DIR_SEPARATOR_STRING "crt0{objext}", s);
499           if (stat(path, &stat_buf) == 0)
500             break;
501         }
502
503       if (s == NULL)
504         setMainValue ("z80crt0", "\"crt0{objext}\"");
505       else
506         {
507           char *buf;
508           size_t len = strlen(path) + 3;
509
510           buf = Safe_alloc(len);
511           SNPRINTF(buf, len, "\"%s\"", path);
512           setMainValue("z80crt0", buf);
513           Safe_free(buf);
514         }
515     }
516   else
517     {
518       setMainValue ("z80libspec", "");
519       setMainValue ("z80crt0", "");
520     }
521
522   setMainValue ("z80extralibfiles", (s = joinStrSet(libFilesSet)));
523   Safe_free((void *)s);
524   setMainValue ("z80extralibpaths", (s = joinStrSet(libPathsSet)));
525   Safe_free((void *)s);
526
527   if (IS_GB)
528     {
529       setMainValue ("z80outputtypeflag", "-Z");
530       setMainValue ("z80outext", ".gb");
531     }
532   else
533     {
534       setMainValue ("z80outputtypeflag", "-i");
535       setMainValue ("z80outext", ".ihx");
536     }
537
538   setMainValue ("stdobjdstfilename" , "{dstfilename}{objext}");
539   setMainValue ("stdlinkdstfilename", "{dstfilename}{z80outext}");
540
541   setMainValue ("z80extraobj", (s = joinStrSet(relFilesSet)));
542   Safe_free((void *)s);
543
544   sprintf (buffer, "-b_CODE=0x%04X -b_DATA=0x%04X", options.code_loc, options.data_loc);
545   setMainValue ("z80bases", buffer);
546 }
547
548 static void
549 _finaliseOptions (void)
550 {
551   port->mem.default_local_map = data;
552   port->mem.default_globl_map = data;
553   if (_G.asmType == ASM_TYPE_ASXXXX && IS_GB)
554     asm_addTree (&_asxxxx_gb);
555
556   _setValues();
557 }
558
559 static void
560 _setDefaultOptions (void)
561 {
562   options.nopeep = 0;
563   options.stackAuto = 1;
564   options.mainreturn = 1;
565   /* first the options part */
566   options.intlong_rent = 1;
567   options.float_rent = 1;
568   options.noRegParams = 1;
569   /* Default code and data locations. */
570   options.code_loc = 0x200;
571
572   if (IS_GB) 
573     {
574       options.data_loc = 0xC000;
575     }
576   else
577     {
578       options.data_loc = 0x8000;
579     }
580
581   optimize.global_cse = 1;
582   optimize.label1 = 1;
583   optimize.label2 = 1;
584   optimize.label3 = 1;
585   optimize.label4 = 1;
586   optimize.loopInvariant = 1;
587   optimize.loopInduction = 1;
588 }
589
590 /* Mangling format:
591     _fun_policy_params
592     where:
593       policy is the function policy
594       params is the parameter format
595
596    policy format:
597     rsp
598     where:
599       r is 'r' for reentrant, 's' for static functions
600       s is 'c' for callee saves, 'r' for caller saves
601       f is 'f' for profiling on, 'x' for profiling off
602     examples:
603       rr - reentrant, caller saves
604    params format:
605     A combination of register short names and s to signify stack variables.
606     examples:
607       bds - first two args appear in BC and DE, the rest on the stack
608       s - all arguments are on the stack.
609 */
610 static char *
611 _mangleSupportFunctionName(char *original)
612 {
613   char buffer[128];
614
615   sprintf(buffer, "%s_rr%s_%s", original,
616           options.profile ? "f" : "x",
617           options.noRegParams ? "s" : "bds" /* MB: but the library only has hds variants ??? */
618           );
619
620   return Safe_strdup(buffer);
621 }
622
623 static const char *
624 _getRegName (struct regs *reg)
625 {
626   if (reg)
627     {
628       return reg->name;
629     }
630   /*  assert (0); */
631   return "err";
632 }
633
634 static bool
635 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
636 {
637   sym_link *test = NULL;
638   value *val;
639
640   if ( ic->op != '*')
641     {
642       return FALSE;
643     }
644
645   if ( IS_LITERAL (left))
646     {
647       test = left;
648       val = OP_VALUE (IC_LEFT (ic));
649     }
650   else if ( IS_LITERAL (right))
651     {
652       test = right;
653       val = OP_VALUE (IC_RIGHT (ic));
654     }
655   /* 8x8 unsigned multiplication code is shorter than
656      call overhead for the multiplication routine. */
657   else if ( IS_CHAR (right) && IS_UNSIGNED (right) &&
658     IS_CHAR (left) && IS_UNSIGNED(left) && !IS_GB)
659     {
660       return TRUE;
661     }
662   else
663     {
664       return FALSE;
665     }
666
667   if ( getSize (test) <= 2)
668     {
669       return TRUE;
670     }
671
672   return FALSE;
673 }
674
675 /* Indicate which extended bit operations this port supports */
676 static bool
677 hasExtBitOp (int op, int size)
678 {
679   if (op == GETHBIT)
680     return TRUE;
681   else
682     return FALSE;
683 }
684
685 /* Indicate the expense of an access to an output storage class */
686 static int
687 oclsExpense (struct memmap *oclass)
688 {
689   if (IN_FARSPACE(oclass))
690     return 1;
691     
692   return 0;
693 }
694
695
696 #define LINKCMD "link-{port} -nf {dstfilename}"
697 /*
698 #define LINKCMD \
699     "link-{port} -n -c -- {z80bases} -m -j" \
700     " {z80libspec}" \
701     " {z80extralibfiles} {z80extralibpaths}" \
702     " {z80outputtypeflag} \"{linkdstfilename}\"" \
703     " {z80crt0}" \
704     " \"{dstfilename}{objext}\"" \
705     " {z80extraobj}"
706 */
707
708 #define ASMCMD \
709     "as-{port} -plosgff \"{objdstfilename}\" \"{dstfilename}{asmext}\""
710
711 /* Globals */
712 PORT z80_port =
713 {
714   TARGET_ID_Z80,
715   "z80",
716   "Zilog Z80",                  /* Target name */
717   NULL,                         /* Processor name */
718   {
719     glue,
720     FALSE,
721     MODEL_MEDIUM | MODEL_SMALL,
722     MODEL_SMALL
723   },
724   {                             /* Assembler */
725     NULL,
726     ASMCMD,
727     "-plosgffc",                /* Options with debug */
728     "-plosgff",                 /* Options without debug */
729     0,
730     ".asm"
731   },
732   {                             /* Linker */
733     NULL,
734     LINKCMD,
735     NULL,
736     ".o",
737     1
738   },
739   {                             /* Peephole optimizer */
740     _z80_defaultRules,
741     0,
742     0,
743     0,
744     0,
745     z80notUsed
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     "-plosgffc",                /* 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 };