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