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