* device/lib/z80/mul.s (__mulsuchar_rrx_s, __muluschar_rrx_s),
[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   else
656     {
657       return FALSE;
658     }
659
660   if ( getSize (test) <= 2)
661     {
662       return TRUE;
663     }
664
665   return FALSE;
666 }
667
668 /* Indicate which extended bit operations this port supports */
669 static bool
670 hasExtBitOp (int op, int size)
671 {
672   if (op == GETHBIT)
673     return TRUE;
674   else
675     return FALSE;
676 }
677
678 /* Indicate the expense of an access to an output storage class */
679 static int
680 oclsExpense (struct memmap *oclass)
681 {
682   if (IN_FARSPACE(oclass))
683     return 1;
684     
685   return 0;
686 }
687
688
689 #define LINKCMD "link-{port} -nf {dstfilename}"
690 /*
691 #define LINKCMD \
692     "link-{port} -n -c -- {z80bases} -m -j" \
693     " {z80libspec}" \
694     " {z80extralibfiles} {z80extralibpaths}" \
695     " {z80outputtypeflag} \"{linkdstfilename}\"" \
696     " {z80crt0}" \
697     " \"{dstfilename}{objext}\"" \
698     " {z80extraobj}"
699 */
700
701 #define ASMCMD \
702     "as-{port} -plosgff \"{objdstfilename}\" \"{dstfilename}{asmext}\""
703
704 /* Globals */
705 PORT z80_port =
706 {
707   TARGET_ID_Z80,
708   "z80",
709   "Zilog Z80",                  /* Target name */
710   NULL,                         /* Processor name */
711   {
712     glue,
713     FALSE,
714     MODEL_MEDIUM | MODEL_SMALL,
715     MODEL_SMALL
716   },
717   {                             /* Assembler */
718     NULL,
719     ASMCMD,
720     "-plosgffc",                /* Options with debug */
721     "-plosgff",                 /* Options without debug */
722     0,
723     ".asm"
724   },
725   {                             /* Linker */
726     NULL,
727     LINKCMD,
728     NULL,
729     ".o",
730     1
731   },
732   {                             /* Peephole optimizer */
733     _z80_defaultRules,
734     0,
735     0,
736     0,
737     0,
738     z80notUsed
739   },
740   {
741         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
742     1, 2, 2, 4, 2, 2, 2, 1, 4, 4
743   },
744   /* tags for generic pointers */
745   { 0x00, 0x40, 0x60, 0x80 },           /* far, near, xstack, code */
746   {
747     "XSEG",
748     "STACK",
749     "CODE",
750     "DATA",
751     "ISEG",
752     NULL, /* pdata */
753     "XSEG",
754     "BSEG",
755     "RSEG",
756     "GSINIT",
757     "OVERLAY",
758     "GSFINAL",
759     "HOME",
760     NULL, /* xidata */
761     NULL, /* xinit */
762     NULL, /* const_name */
763     "CABS", /* cabs_name */
764     NULL, /* xabs_name */
765     NULL, /* iabs_name */
766     NULL,
767     NULL,
768     1
769   },
770   { NULL, NULL },
771   {
772     -1, 0, 0, 4, 0, 2
773   },
774     /* Z80 has no native mul/div commands */
775   {
776     0, 2
777   },
778   {
779     z80_emitDebuggerSymbol
780   },
781   {
782     255,        /* maxCount */
783     3,          /* sizeofElement */
784     /* The rest of these costs are bogus. They approximate */
785     /* the behavior of src/SDCCicode.c 1.207 and earlier.  */
786     {4,4,4},    /* sizeofMatchJump[] */
787     {0,0,0},    /* sizeofRangeCompare[] */
788     0,          /* sizeofSubtract */
789     3,          /* sizeofDispatch */
790   },
791   "_",
792   _z80_init,
793   _parseOptions,
794   _z80_options,
795   NULL,
796   _finaliseOptions,
797   _setDefaultOptions,
798   z80_assignRegisters,
799   _getRegName,
800   _keywords,
801   0,                            /* no assembler preamble */
802   NULL,                         /* no genAssemblerEnd */
803   0,                            /* no local IVT generation code */
804   0,                            /* no genXINIT code */
805   NULL,                         /* genInitStartup */
806   _reset_regparm,
807   _reg_parm,
808   _process_pragma,
809   _mangleSupportFunctionName,
810   _hasNativeMulFor,
811   hasExtBitOp,                  /* hasExtBitOp */
812   oclsExpense,                  /* oclsExpense */
813   TRUE,
814   TRUE,                         /* little endian */
815   0,                            /* leave lt */
816   0,                            /* leave gt */
817   1,                            /* transform <= to ! > */
818   1,                            /* transform >= to ! < */
819   1,                            /* transform != to !(a == b) */
820   0,                            /* leave == */
821   TRUE,                         /* Array initializer support. */
822   0,                            /* no CSE cost estimation yet */
823   _z80_builtins,                /* no builtin functions */
824   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
825   1,                            /* reset labelKey to 1 */
826   1,                            /* globals & local static allowed */
827   PORT_MAGIC
828 };
829
830 /* Globals */
831 PORT gbz80_port =
832 {
833   TARGET_ID_GBZ80,
834   "gbz80",
835   "Gameboy Z80-like",           /* Target name */
836   NULL,
837   {
838     glue,
839     FALSE,
840     MODEL_MEDIUM | MODEL_SMALL,
841     MODEL_SMALL
842   },
843   {
844     NULL,
845     ASMCMD,
846     "-plosgffc",                /* Options with debug */
847     "-plosgff",                 /* Options without debug */
848     0,
849     ".asm",
850     NULL                        /* no do_assemble function */
851   },
852   {
853     NULL,
854     LINKCMD,
855     NULL,
856     ".o",
857     1
858   },
859   {
860     _gbz80_defaultRules
861   },
862   {
863     /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
864     1, 2, 2, 4, 2, 2, 2, 1, 4, 4
865   },
866   /* tags for generic pointers */
867   { 0x00, 0x40, 0x60, 0x80 },           /* far, near, xstack, code */
868   {
869     "XSEG",
870     "STACK",
871     "CODE",
872     "DATA",
873     "ISEG",
874     NULL, /* pdata */
875     "XSEG",
876     "BSEG",
877     "RSEG",
878     "GSINIT",
879     "OVERLAY",
880     "GSFINAL",
881     "HOME",
882     NULL, /* xidata */
883     NULL, /* xinit */
884     NULL, /* const_name */
885     "CABS", /* cabs_name */
886     NULL, /* xabs_name */
887     NULL, /* iabs_name */
888     NULL,
889     NULL,
890     1
891   },
892   { NULL, NULL },
893   {
894     -1, 0, 0, 2, 0, 4
895   },
896     /* gbZ80 has no native mul/div commands */
897   {
898     0, 2
899   },
900   {
901     z80_emitDebuggerSymbol
902   },
903   {
904     255,        /* maxCount */
905     3,          /* sizeofElement */
906     /* The rest of these costs are bogus. They approximate */
907     /* the behavior of src/SDCCicode.c 1.207 and earlier.  */
908     {4,4,4},    /* sizeofMatchJump[] */
909     {0,0,0},    /* sizeofRangeCompare[] */
910     0,          /* sizeofSubtract */
911     3,          /* sizeofDispatch */
912   },
913   "_",
914   _gbz80_init,
915   _parseOptions,
916   _gbz80_options,
917   NULL,
918   _finaliseOptions,
919   _setDefaultOptions,
920   z80_assignRegisters,
921   _getRegName,
922   _keywords,
923   0,                            /* no assembler preamble */
924   NULL,                         /* no genAssemblerEnd */
925   0,                            /* no local IVT generation code */
926   0,                            /* no genXINIT code */
927   NULL,                         /* genInitStartup */
928   _reset_regparm,
929   _reg_parm,
930   _process_pragma,
931   _mangleSupportFunctionName,
932   _hasNativeMulFor,
933   hasExtBitOp,                  /* hasExtBitOp */
934   oclsExpense,                  /* oclsExpense */
935   TRUE,
936   TRUE,                         /* little endian */
937   0,                            /* leave lt */
938   0,                            /* leave gt */
939   1,                            /* transform <= to ! > */
940   1,                            /* transform >= to ! < */
941   1,                            /* transform != to !(a == b) */
942   0,                            /* leave == */
943   TRUE,                         /* Array initializer support. */
944   0,                            /* no CSE cost estimation yet */
945   NULL,                         /* no builtin functions */
946   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
947   1,                            /* reset labelKey to 1 */
948   1,                            /* globals & local static allowed */
949   PORT_MAGIC
950 };