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