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