handling space characters in file path
[fw/sdcc] / src / ds390 / main.c
1 /** @file main.c
2     ds390 specific general functions.
3
4     Note that mlh prepended _ds390_ on the static functions.  Makes
5     it easier to set a breakpoint using the debugger.
6 */
7 #include "common.h"
8 #include "main.h"
9 #include "ralloc.h"
10 #include "gen.h"
11 #include "BuildCmd.h"
12 #include "MySystem.h"
13 #include "../SDCCutil.h"
14 extern const char *preArgv[128];        /* pre-processor arguments  */
15 static char _defaultRules[] =
16 {
17 #include "peeph.rul"
18 };
19
20 /* list of key words used by msc51 */
21 static char *_ds390_keywords[] =
22 {
23   "at",
24   "bit",
25   "code",
26   "critical",
27   "data",
28   "far",
29   "idata",
30   "interrupt",
31   "near",
32   "pdata",
33   "reentrant",
34   "sfr",
35   "sbit",
36   "using",
37   "xdata",
38   "_data",
39   "_code",
40   "_generic",
41   "_near",
42   "_xdata",
43   "_pdata",
44   "_idata",
45   "_naked",
46   NULL
47 };
48
49 static builtins __ds390_builtins[] = {
50     { "__builtin_memcpy_x2x","v",3,{"cx*","cx*","i"}}, /* void __builtin_memcpy_x2x (xdata char *,xdata char *,int) */
51     { "__builtin_memcpy_c2x","v",3,{"cx*","cp*","i"}}, /* void __builtin_memcpy_c2x (xdata char *,code  char *,int) */
52     { "__builtin_memset_x","v",3,{"cx*","c","i"}},     /* void __builtin_memset     (xdata char *,char,int)         */
53     /* __builtin_inp - used to read from a memory mapped port, increment first pointer */
54     { "__builtin_inp","v",3,{"cx*","cx*","i"}},        /* void __builtin_inp        (xdata char *,xdata char *,int) */
55     /* __builtin_inp - used to write to a memory mapped port, increment first pointer */
56     { "__builtin_outp","v",3,{"cx*","cx*","i"}},       /* void __builtin_outp       (xdata char *,xdata char *,int) */
57     { "__builtin_swapw","us",1,{"us"}},                /* unsigned short __builtin_swapw (unsigned short) */
58     { "__builtin_memcmp_x2x","c",3,{"cx*","cx*","i"}}, /* void __builtin_memcmp_x2x (xdata char *,xdata char *,int) */
59     { "__builtin_memcmp_c2x","c",3,{"cx*","cp*","i"}}, /* void __builtin_memcmp_c2x (xdata char *,code  char *,int) */
60     { NULL , NULL,0, {NULL}}                       /* mark end of table */
61 };    
62 void ds390_assignRegisters (eBBlock ** ebbs, int count);
63
64 static int regParmFlg = 0;      /* determine if we can register a parameter */
65
66 static void
67 _ds390_init (void)
68 {
69   asm_addTree (&asm_asxxxx_mapping);
70 }
71
72 static void
73 _ds390_reset_regparm ()
74 {
75   regParmFlg = 0;
76 }
77
78 static int
79 _ds390_regparm (sym_link * l)
80 {
81
82     if (options.parms_in_bank1 == 0) {
83         /* simple can pass only the first parameter in a register */
84         if (regParmFlg)
85             return 0;
86
87         regParmFlg = 1;
88         return 1;
89     } else {
90         int size = getSize(l);
91         int remain ;
92
93         /* first one goes the usual way to DPTR */
94         if (regParmFlg == 0) {
95             regParmFlg += 4 ;
96             return 1;
97         }
98         /* second one onwards goes to RB1_0 thru RB1_7 */
99         remain = regParmFlg - 4;
100         if (size > (8 - remain)) {
101             regParmFlg = 12 ;
102             return 0;
103         }
104         regParmFlg += size ;
105         return regParmFlg - size + 1;   
106     }
107 }
108
109 static bool
110 _ds390_parseOptions (int *pargc, char **argv, int *i)
111 {
112   /* TODO: allow port-specific command line options to specify
113    * segment names here.
114    */
115   return FALSE;
116 }
117
118 static void
119 _ds390_finaliseOptions (void)
120 {
121   if (options.noXinitOpt) {
122     port->genXINIT=0;
123   }
124
125   /* Hack-o-matic: if we are using the flat24 model,
126    * adjust pointer sizes.
127    */
128   if (options.model != MODEL_FLAT24)  {
129       fprintf (stderr,
130                "*** warning: ds390 port small and large model experimental.\n");
131       if (options.model == MODEL_LARGE)
132       {
133         port->mem.default_local_map = xdata;
134         port->mem.default_globl_map = xdata;
135       }
136       else
137       {
138         port->mem.default_local_map = data;
139         port->mem.default_globl_map = data;
140       }
141   }
142   else {
143     port->s.fptr_size = 3;
144     port->s.gptr_size = 4;
145
146     port->stack.isr_overhead += 2;      /* Will save dpx on ISR entry. */
147
148     port->stack.call_overhead += 2;     /* This acounts for the extra byte 
149                                  * of return addres on the stack.
150                                  * but is ugly. There must be a 
151                                  * better way.
152                                  */
153
154     port->mem.default_local_map = xdata;
155     port->mem.default_globl_map = xdata;
156
157     if (!options.stack10bit)
158     {
159     fprintf (stderr,
160              "*** error: ds390 port only supports the 10 bit stack mode.\n");
161     } else {
162         if (!options.stack_loc) options.stack_loc = 0x400008;
163     }
164     
165     /* generate native code 16*16 mul/div */
166     if (options.useAccelerator) 
167             port->support.muldiv=2;
168     else 
169             port->support.muldiv=1;
170
171      /* Fixup the memory map for the stack; it is now in
172      * far space and requires a FPOINTER to access it.
173      */
174     istack->fmap = 1;
175     istack->ptrType = FPOINTER;
176
177     if (options.parms_in_bank1) {
178         addToList (preArgv, "-DSDCC_PARMS_IN_BANK1");
179     }
180   }  /* MODEL_FLAT24 */
181 }
182
183 static void
184 _ds390_setDefaultOptions (void)
185 {
186   options.model=MODEL_FLAT24;
187   options.stack10bit=1;
188 }
189
190 static const char *
191 _ds390_getRegName (struct regs *reg)
192 {
193   if (reg)
194     return reg->name;
195   return "err";
196 }
197
198 static void
199 _ds390_genAssemblerPreamble (FILE * of)
200 {
201       if (options.model == MODEL_FLAT24)
202         fputs (".flat24 on\t\t; 24 bit flat addressing\n", of);
203
204       fputs ("dpx = 0x93\t\t; dpx register unknown to assembler\n", of);
205       fputs ("dps = 0x86\t\t; dps register unknown to assembler\n", of);
206       fputs ("dpl1 = 0x84\t\t; dpl1 register unknown to assembler\n", of);
207       fputs ("dph1 = 0x85\t\t; dph1 register unknown to assembler\n", of);
208       fputs ("dpx1 = 0x95\t\t; dpx1 register unknown to assembler\n", of);
209       fputs ("ap = 0x9C\t\t; ap register unknown to assembler\n", of);
210       fputs ("_ap = 0x9C\t\t; _ap register unknown to assembler\n", of);
211       fputs ("mcnt0 = 0xD1\t\t; mcnt0 register unknown to assembler\n", of);
212       fputs ("mcnt1 = 0xD2\t\t; mcnt1 register unknown to assembler\n", of);
213       fputs ("ma = 0xD3\t\t; ma register unknown to assembler\n", of);
214       fputs ("mb = 0xD4\t\t; mb register unknown to assembler\n", of);
215       fputs ("mc = 0xD5\t\t; mc register unknown to assembler\n", of);
216       fputs ("F1 = 0xD1\t\t; F1 user flag unknown to assembler\n", of);
217       fputs ("esp = 0x9B\t\t; ESP user flag unknown to assembler\n", of);
218       if (options.parms_in_bank1) {
219           int i ;
220           for (i=0; i < 8 ; i++ )
221               fprintf (of,"b1_%d = 0x%x \n",i,8+i);
222       }
223 }
224
225 /* Generate interrupt vector table. */
226 static int
227 _ds390_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
228 {
229   int i;
230
231   if (options.model != MODEL_FLAT24)
232     {
233       /* Let the default code handle it. */
234       return FALSE;
235     }
236
237   fprintf (of, "\tajmp\t__reset_vect\n");
238
239   /* now for the other interrupts */
240   for (i = 0; i < maxInterrupts; i++)
241     {
242       if (interrupts[i])
243         {
244           fprintf (of, "\tljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
245         }
246       else
247         {
248           fprintf (of, "\treti\n\t.ds\t7\n");
249         }
250     }
251
252   fprintf (of, "__reset_vect:\n\tljmp\t__sdcc_gsinit_startup\n");
253
254   return TRUE;
255 }
256
257 /* Generate code to copy XINIT to XISEG */
258 static void _ds390_genXINIT (FILE * of) {
259   fprintf (of, ";       _ds390_genXINIT() start\n");
260   fprintf (of, "        mov     a,#l_XINIT\n");
261   fprintf (of, "        orl     a,#l_XINIT>>8\n");
262   fprintf (of, "        jz      00003$\n");
263   fprintf (of, "        mov     a,#s_XINIT\n");
264   fprintf (of, "        add     a,#l_XINIT\n");
265   fprintf (of, "        mov     r1,a\n");
266   fprintf (of, "        mov     a,#s_XINIT>>8\n");
267   fprintf (of, "        addc    a,#l_XINIT>>8\n");
268   fprintf (of, "        mov     r2,a\n");
269   fprintf (of, "        mov     dptr,#s_XINIT\n");
270   fprintf (of, "        mov     dps,#0x21\n");
271   fprintf (of, "        mov     dptr,#s_XISEG\n");
272   fprintf (of, "00001$: clr     a\n");
273   fprintf (of, "        movc    a,@a+dptr\n");
274   fprintf (of, "        movx    @dptr,a\n");
275   fprintf (of, "        inc     dptr\n");
276   fprintf (of, "        inc     dptr\n");
277   fprintf (of, "00002$: mov     a,dpl\n");
278   fprintf (of, "        cjne    a,ar1,00001$\n");
279   fprintf (of, "        mov     a,dph\n");
280   fprintf (of, "        cjne    a,ar2,00001$\n");
281   fprintf (of, "        mov     dps,#0\n");
282   fprintf (of, "00003$:\n");
283   fprintf (of, ";       _ds390_genXINIT() end\n");
284 }
285
286 /* Do CSE estimation */
287 static bool cseCostEstimation (iCode *ic, iCode *pdic)
288 {
289     operand *result = IC_RESULT(ic);
290     //operand *right  = IC_RIGHT(ic);
291     //operand *left   = IC_LEFT(ic);
292     sym_link *result_type = operandType(result);
293     //sym_link *right_type  = (right ? operandType(right) : 0);
294     //sym_link *left_type   = (left  ? operandType(left)  : 0);
295     
296     /* if it is a pointer then return ok for now */
297     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
298     
299     /* if bitwise | add & subtract then no since mcs51 is pretty good at it 
300        so we will cse only if they are local (i.e. both ic & pdic belong to
301        the same basic block */
302     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
303         /* then if they are the same Basic block then ok */
304         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
305         else return 0;
306     }
307         
308     /* for others it is cheaper to do the cse */
309     return 1;
310 }
311 /** $1 is always the basename.
312     $2 is always the output file.
313     $3 varies
314     $l is the list of extra options that should be there somewhere...
315     MUST be terminated with a NULL.
316 */
317 static const char *_linkCmd[] =
318 {
319   "aslink", "-nf", "\"$1\"", NULL
320 };
321
322 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */   static const char *_asmCmd[] =
323 {
324   "asx8051", "$l", "$3", "\"$1.asm\"", NULL
325 };
326
327 /* Globals */
328 PORT ds390_port =
329 {
330   TARGET_ID_DS390,
331   "ds390",
332   "DS80C390",                   /* Target name */
333   NULL,
334   {
335     TRUE,                       /* Emit glue around main */
336     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
337     MODEL_SMALL
338   },
339   {
340     _asmCmd,
341     NULL,
342     "-plosgffc",                /* Options with debug */
343     "-plosgff",                 /* Options without debug */
344     0,
345     ".asm",
346     NULL                        /* no do_assemble function */
347   },
348   {
349     _linkCmd,
350     NULL,
351     NULL,
352     ".rel"
353   },
354   {
355     _defaultRules
356   },
357   {
358         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
359     1, 2, 2, 4, 1, 2, 3, 1, 4, 4
360   },
361   {
362     "XSEG    (XDATA)",
363     "STACK   (DATA)",
364     "CSEG    (CODE)",
365     "DSEG    (DATA)",
366     "ISEG    (DATA)",
367     "XSEG    (XDATA)",
368     "BSEG    (BIT)",
369     "RSEG    (DATA)",
370     "GSINIT  (CODE)",
371     "OSEG    (OVR,DATA)",
372     "GSFINAL (CODE)",
373     "HOME    (CODE)",
374     "XISEG   (XDATA)", // initialized xdata
375     "XINIT   (CODE)", // a code copy of xiseg
376     NULL,
377     NULL,
378     1
379   },
380   {
381     +1, 1, 4, 1, 1, 0
382   },
383     /* ds390 has an 16 bit mul & div */
384   {
385     2, -1
386   },
387   "_",
388   _ds390_init,
389   _ds390_parseOptions,
390   NULL,
391   _ds390_finaliseOptions,
392   _ds390_setDefaultOptions,
393   ds390_assignRegisters,
394   _ds390_getRegName,
395   _ds390_keywords,
396   _ds390_genAssemblerPreamble,
397   NULL,                         /* no genAssemblerEnd */
398   _ds390_genIVT,
399   _ds390_genXINIT,
400   _ds390_reset_regparm,
401   _ds390_regparm,
402   NULL,
403   NULL,
404   NULL,
405   FALSE,
406   0,                            /* leave lt */
407   0,                            /* leave gt */
408   1,                            /* transform <= to ! > */
409   1,                            /* transform >= to ! < */
410   1,                            /* transform != to !(a == b) */
411   0,                            /* leave == */
412   TRUE,                         /* we support array initializers. */
413   cseCostEstimation,
414   __ds390_builtins,             /* table of builtin functions */
415   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
416   1,                            /* reset labelKey to 1 */
417   1,                            /* globals & local static allowed */
418   PORT_MAGIC
419 };
420
421 /*---------------------------------------------------------------------------------*/
422 /*                               TININative specific                               */
423 /*---------------------------------------------------------------------------------*/
424 /* Globals */
425 static void _tininative_init (void)
426 {
427     asm_addTree (&asm_a390_mapping);
428 }
429
430 static void _tininative_setDefaultOptions (void)
431 {
432     options.model=MODEL_FLAT24;
433     options.stack10bit=1;
434     options.stackAuto = 1;
435 }
436
437 static void _tininative_finaliseOptions (void)
438 {
439     /* Hack-o-matic: if we are using the flat24 model,
440      * adjust pointer sizes.
441      */
442     if (options.model != MODEL_FLAT24)  {
443         options.model = MODEL_FLAT24 ;
444         fprintf(stderr,"TININative supports only MODEL FLAT24\n");
445     }
446     port->s.fptr_size = 3;
447     port->s.gptr_size = 4;
448     
449     port->stack.isr_overhead += 2;      /* Will save dpx on ISR entry. */
450     
451     port->stack.call_overhead += 2;     /* This acounts for the extra byte 
452                                          * of return addres on the stack.
453                                          * but is ugly. There must be a 
454                                          * better way.
455                                          */
456     
457     port->mem.default_local_map = xdata;
458     port->mem.default_globl_map = xdata;
459     
460     if (!options.stack10bit) {
461         options.stack10bit = 1;
462         fprintf(stderr,"TININative supports only stack10bit \n");
463     }
464     
465     if (!options.stack_loc) options.stack_loc = 0x400008;
466     
467     /* generate native code 16*16 mul/div */
468     if (options.useAccelerator) 
469         port->support.muldiv=2;
470     else 
471         port->support.muldiv=1;
472     
473     /* Fixup the memory map for the stack; it is now in
474      * far space and requires a FPOINTER to access it.
475      */
476     istack->fmap = 1;
477     istack->ptrType = FPOINTER;
478     options.cc_only =1;
479 }
480
481 static int _tininative_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts) 
482 {
483     return 1;
484 }
485 static void _tininative_genAssemblerPreamble (FILE * of)
486 {
487     fputs("$include(tini.inc)\n", of);
488     fputs("$include(ds80c390.inc)\n", of);
489     fputs("$include(tinimacro.inc)\n", of);
490     fputs("$include(apiequ.inc)\n", of);
491     fputs("_bpx EQU 01Eh \t\t; _bpx (frame pointer) mapped to R8_B3:R7_B3\n", of);
492     fputs("_ap  EQU 01Dh \t\t; _ap mapped to R6_B3\n", of);
493     /* Must be first and return 0 */
494     fputs("Lib_Native_Init:\n",of);
495     fputs("\tclr\ta\n",of);
496     fputs("\tret\n",of);
497     fputs("LibraryID:\n",of);
498     fputs("\tdb \"DS\"\n",of);
499     if (options.tini_libid) {
500         fprintf(of,"\tdb 0,0,0%02xh,0%02xh,0%02xh,0%02xh\n",
501                 (options.tini_libid>>24 & 0xff),
502                 (options.tini_libid>>16 & 0xff),
503                 (options.tini_libid>>8 & 0xff),
504                 (options.tini_libid  & 0xff));
505     } else {
506         fprintf(of,"\tdb 0,0,0,0,0,1\n");
507     }
508
509 }
510 static void _tininative_genAssemblerEnd (FILE * of)
511 {
512     fputs("\tend\n",of);
513 }
514 /* tininative assembler , calls "macro", if it succeeds calls "a390" */
515 static void _tininative_do_assemble (set *asmOptions)
516 {
517     static const char *macroCmd[] = {
518         "macro","$1.a51",NULL
519     };
520     static const char *a390Cmd[] = {
521         "a390","$1.mpp",NULL
522     };
523     char buffer[100];
524
525     buildCmdLine(buffer,macroCmd,dstFileName,NULL,NULL,NULL);
526     if (my_system(buffer)) {
527         exit(1);
528     }
529     buildCmdLine(buffer,a390Cmd,dstFileName,NULL,NULL,asmOptions);
530     if (my_system(buffer)) {
531         exit(1);
532     }    
533 }
534
535 /* list of key words used by TININative */
536 static char *_tininative_keywords[] =
537 {
538   "at",
539   "bit",
540   "code",
541   "critical",
542   "data",
543   "far",
544   "idata",
545   "interrupt",
546   "near",
547   "pdata",
548   "reentrant",
549   "sfr",
550   "sbit",
551   "using",
552   "xdata",
553   "_data",
554   "_code",
555   "_generic",
556   "_near",
557   "_xdata",
558   "_pdata",
559   "_idata",
560   "_naked",
561   "_JavaNative",
562   NULL
563 };
564
565 static builtins __tininative_builtins[] = {
566     { "__builtin_memcpy_x2x","v",3,{"cx*","cx*","i"}}, /* void __builtin_memcpy_x2x (xdata char *,xdata char *,int) */
567     { "__builtin_memcpy_c2x","v",3,{"cx*","cp*","i"}}, /* void __builtin_memcpy_c2x (xdata char *,code  char *,int) */
568     { "__builtin_memset_x","v",3,{"cx*","c","i"}},     /* void __builtin_memset     (xdata char *,char,int)         */
569     /* TINI NatLib */
570     { "NatLib_LoadByte","c",1,{"c"}},                  /* char  Natlib_LoadByte  (0 based parameter number)         */
571     { "NatLib_LoadShort","s",1,{"c"}},                 /* short Natlib_LoadShort (0 based parameter number)         */
572     { "NatLib_LoadInt","l",1,{"c"}},                   /* long  Natlib_LoadLong  (0 based parameter number)         */
573     { "NatLib_LoadPointer","cx*",1,{"c"}},             /* long  Natlib_LoadPointer  (0 based parameter number)      */
574     /* TINI StateBlock related */
575     { "NatLib_InstallImmutableStateBlock","c",2,{"vx*","us"}},/* char NatLib_InstallImmutableStateBlock(state block *,int handle) */
576     { "NatLib_InstallEphemeralStateBlock","c",2,{"vx*","us"}},/* char NatLib_InstallEphemeralStateBlock(state block *,int handle) */
577     { "NatLib_RemoveImmutableStateBlock","v",0,{NULL}},/* void NatLib_RemoveImmutableStateBlock() */
578     { "NatLib_RemoveEphemeralStateBlock","v",0,{NULL}},/* void NatLib_RemoveEphemeralStateBlock() */
579     { "NatLib_GetImmutableStateBlock","i",0,{NULL}},   /* int  NatLib_GetImmutableStateBlock () */
580     { "NatLib_GetEphemeralStateBlock","i",0,{NULL}},   /* int  NatLib_GetEphemeralStateBlock () */
581     /* Memory manager */
582     { "MM_XMalloc","i",1,{"l"}},                       /* int  MM_XMalloc (long)                */
583     { "MM_Malloc","i",1,{"i"}},                        /* int  MM_Malloc  (int)                 */
584     { "MM_ApplicationMalloc","i",1,{"i"}},             /* int  MM_ApplicationMalloc  (int)      */
585     { "MM_Free","i",1,{"i"}},                          /* int  MM_Free  (int)                   */
586     { "MM_Deref","cx*",1,{"i"}},                       /* char *MM_Free  (int)                  */
587     { "MM_UnrestrictedPersist","c",1,{"i"}},           /* char  MM_UnrestrictedPersist  (int)   */
588     /* System functions */
589     { "System_ExecJavaProcess","c",2,{"cx*","i"}},     /* char System_ExecJavaProcess (char *,int) */
590     { "System_GetRTCRegisters","v",1,{"cx*"}},         /* void System_GetRTCRegisters (char *) */
591     { "System_SetRTCRegisters","v",1,{"cx*"}},         /* void System_SetRTCRegisters (char *) */
592     { "System_ThreadSleep","v",2,{"l","c"}},           /* void System_ThreadSleep (long,char)  */
593     { "System_ThreadSleep_ExitCriticalSection","v",2,{"l","c"}},/* void System_ThreadSleep_ExitCriticalSection (long,char)  */
594     { "System_ProcessSleep","v",2,{"l","c"}},           /* void System_ProcessSleep (long,char)  */
595     { "System_ProcessSleep_ExitCriticalSection","v",2,{"l","c"}},/* void System_ProcessSleep_ExitCriticalSection (long,char)  */
596     { "System_ThreadResume","c",2,{"c","c"}},          /* char System_ThreadResume(char,char)  */
597     { "System_SaveJavaThreadState","v",0,{NULL}},      /* void System_SaveJavaThreadState()    */
598     { "System_RestoreJavaThreadState","v",0,{NULL}},   /* void System_RestoreJavaThreadState() */
599     { "System_ProcessYield","v",0,{NULL}},             /* void System_ProcessYield() */
600     { "System_ProcessSuspend","v",0,{NULL}},           /* void System_ProcessSuspend() */
601     { "System_ProcessResume","v",1,{"c"}},             /* void System_ProcessResume(char) */
602     { "System_RegisterPoll","c",1,{"vF*"}},            /* char System_RegisterPoll ((void *func pointer)()) */
603     { "System_RemovePoll","c",1,{"vF*"}},              /* char System_RemovePoll ((void *func pointer)()) */
604     { "System_GetCurrentProcessId","c",0,{NULL}},      /* char System_GetCurrentProcessId() */
605     { "System_GetCurrentThreadId","c",0,{NULL}},       /* char System_GetCurrentThreadId() */
606     { NULL , NULL,0, {NULL}}                       /* mark end of table */
607 };    
608
609 static const char *_a390Cmd[] =
610 {
611   "macro", "$l", "$3", "$1.a51", NULL
612 };
613 PORT tininative_port =
614 {
615   TARGET_ID_DS390,
616   "TININative",
617   "DS80C390",                   /* Target name */
618         NULL,                   /* processor */
619   {
620     FALSE,                      /* Emit glue around main */
621     MODEL_FLAT24,
622     MODEL_FLAT24
623   },
624   {
625     _a390Cmd,
626     NULL,
627     "-l",               /* Options with debug */
628     "-l",               /* Options without debug */
629     0,
630     ".a51",
631     _tininative_do_assemble
632   },
633   {
634     NULL,
635     NULL,
636     NULL,
637     ".tlib",
638   },
639   {
640     _defaultRules
641   },
642   {
643         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
644     1, 2, 2, 4, 1, 3, 3, 1, 4, 4
645   },
646   {
647     "XSEG    (XDATA)",
648     "STACK   (DATA)",
649     "CSEG    (CODE)",
650     "DSEG    (DATA)",
651     "ISEG    (DATA)",
652     "XSEG    (XDATA)",
653     "BSEG    (BIT)",
654     "RSEG    (DATA)",
655     "GSINIT  (CODE)",
656     "OSEG    (OVR,DATA)",
657     "GSFINAL (CODE)",
658     "HOME        (CODE)",
659     NULL,
660     NULL,
661     NULL,
662     NULL,
663     1
664   },
665   {
666     +1, 1, 4, 1, 1, 0
667   },
668     /* ds390 has an 16 bit mul & div */
669   {
670     2, -1
671   },
672   "",
673   _tininative_init,
674   _ds390_parseOptions,
675   NULL,
676   _tininative_finaliseOptions,
677   _tininative_setDefaultOptions,
678   ds390_assignRegisters,
679   _ds390_getRegName,
680   _tininative_keywords,
681   _tininative_genAssemblerPreamble,
682   _tininative_genAssemblerEnd,
683   _tininative_genIVT,
684   NULL,
685   _ds390_reset_regparm,
686   _ds390_regparm,
687   NULL,
688   NULL,
689   NULL,
690   FALSE,
691   0,                            /* leave lt */
692   0,                            /* leave gt */
693   1,                            /* transform <= to ! > */
694   1,                            /* transform >= to ! < */
695   1,                            /* transform != to !(a == b) */
696   0,                            /* leave == */
697   TRUE,                         /* we support array initializers. */
698   cseCostEstimation,
699   __tininative_builtins,        /* table of builtin functions */
700   FPOINTER,                     /* treat unqualified pointers as far pointers */
701   0,                            /* DONOT reset labelKey */
702   0,                            /* globals & local static NOT allowed */
703   PORT_MAGIC
704 };