* src/ds390/ralloc.h,
[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 #include "../SDCCglobl.h"
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         addSet(&preArgvSet, Safe_strdup("-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
312 bool _ds390_nativeMulCheck(iCode *ic, sym_link *left, sym_link *right)
313 {
314     return FALSE; // #STUB
315 }
316
317 /* Indicate which extended bit operations this port supports */
318 static bool
319 hasExtBitOp (int op, int size)
320 {
321   if (op == RRC
322       || op == RLC
323       || op == GETHBIT
324       || (op == SWAP && size <= 2)
325      )
326     return TRUE;
327   else
328     return FALSE;
329 }
330
331 /* Indicate the expense of an access to an output storage class */
332 static int
333 oclsExpense (struct memmap *oclass)
334 {
335   if (IN_FARSPACE(oclass))
336     return 1;
337     
338   return 0;
339 }
340
341 static int
342 instructionSize(char *inst, char *op1, char *op2)
343 {
344   int isflat24 = (options.model == MODEL_FLAT24);
345   
346   #define ISINST(s) (strncmp(inst, (s), sizeof(s)-1) == 0)
347   #define IS_A(s) (*(s) == 'a' && *(s+1) == '\0')
348   #define IS_C(s) (*(s) == 'c' && *(s+1) == '\0')
349   #define IS_Rn(s) (*(s) == 'r' && *(s+1) >= '0' && *(s+1) <= '7')
350   #define IS_atRi(s) (*(s) == '@' && *(s+1) == 'r')
351
352   /* Based on the current (2003-08-22) code generation for the
353      small library, the top instruction probability is:
354    
355        57% mov/movx/movc
356         6% push
357         6% pop
358         4% inc
359         4% lcall
360         4% add
361         3% clr
362         2% subb
363   */
364   /* mov, push, & pop are the 69% of the cases. Check them first! */
365   if (ISINST ("mov"))
366     {
367       if (*(inst+3)=='x') return 1; /* movx */
368       if (*(inst+3)=='c') return 1; /* movc */
369       if (IS_C (op1) || IS_C (op2)) return 2;
370       if (IS_A (op1))
371         {
372           if (IS_Rn (op2) || IS_atRi (op2)) return 1;
373           return 2;
374         }
375       if (IS_Rn(op1) || IS_atRi(op1))
376         {
377           if (IS_A(op2)) return 1;
378           return 2;
379         }
380       if (strcmp (op1, "dptr") == 0) return 3+isflat24;
381       if (IS_A (op2) || IS_Rn (op2) || IS_atRi (op2)) return 2;
382       return 3;
383     }
384   
385   if (ISINST ("push")) return 2;
386   if (ISINST ("pop")) return 2;
387
388   if (ISINST ("lcall")) return 3+isflat24;
389   if (ISINST ("ret")) return 1;
390   if (ISINST ("ljmp")) return 3+isflat24;
391   if (ISINST ("sjmp")) return 2;
392   if (ISINST ("rlc")) return 1;
393   if (ISINST ("rrc")) return 1;
394   if (ISINST ("rl")) return 1;
395   if (ISINST ("rr")) return 1;
396   if (ISINST ("swap")) return 1;
397   if (ISINST ("jc")) return 2;
398   if (ISINST ("jnc")) return 2;
399   if (ISINST ("jb")) return 3;
400   if (ISINST ("jnb")) return 3;
401   if (ISINST ("jbc")) return 3;
402   if (ISINST ("jmp")) return 1; // always jmp @a+dptr
403   if (ISINST ("jz")) return 2;
404   if (ISINST ("jnz")) return 2;
405   if (ISINST ("cjne")) return 3;
406   if (ISINST ("mul")) return 1;
407   if (ISINST ("div")) return 1;
408   if (ISINST ("da")) return 1;
409   if (ISINST ("xchd")) return 1;
410   if (ISINST ("reti")) return 1;
411   if (ISINST ("nop")) return 1;
412   if (ISINST ("acall")) return 2+isflat24;
413   if (ISINST ("ajmp")) return 2+isflat24;
414
415     
416   if (ISINST ("add") || ISINST ("addc") || ISINST ("subb") || ISINST ("xch"))
417     {
418       if (IS_Rn(op2) || IS_atRi(op2)) return 1;
419       return 2;
420     }
421   if (ISINST ("inc") || ISINST ("dec"))
422     {
423       if (IS_A(op1) || IS_Rn(op1) || IS_atRi(op1)) return 1;
424       if (strcmp(op1, "dptr") == 0) return 1;
425       return 2;
426     }
427   if (ISINST ("anl") || ISINST ("orl") || ISINST ("xrl"))
428     {
429       if (IS_C(op1)) return 2;
430       if (IS_A(op1))
431         {
432           if (IS_Rn(op2) || IS_atRi(op2)) return 1;
433           return 2;
434         }
435       else
436         {
437           if (IS_A(op2)) return 2;
438           return 3;
439         }
440     }
441   if (ISINST ("clr") || ISINST ("setb") || ISINST ("cpl"))
442     {
443       if (IS_A(op1) || IS_C(op1)) return 1;
444       return 2;
445     }
446   if (ISINST ("djnz"))
447     {
448       if (IS_Rn(op1)) return 2;
449       return 3;
450     }
451
452   /* If the instruction is unrecognized, we shouldn't try to optimize. */
453   /* Return a large value to discourage optimization.                  */
454   return 999;
455 }
456
457 asmLineNode *
458 ds390newAsmLineNode (int currentDPS)
459 {
460   asmLineNode *aln;
461
462   aln = Safe_alloc ( sizeof (asmLineNode));
463   aln->size = 0;
464   aln->regsRead = NULL;
465   aln->regsWritten = NULL;
466   aln->initialized = 0;
467   aln->currentDPS = currentDPS;
468   
469   return aln;
470 }
471
472
473 typedef struct ds390operanddata
474   {
475     char name[6];
476     int regIdx1;
477     int regIdx2;
478   }
479 ds390operanddata;
480
481 static ds390operanddata ds390operandDataTable[] =
482   {
483     {"_ap", AP_IDX, -1},
484     {"a", A_IDX, -1},
485     {"ab", A_IDX, B_IDX},
486     {"ac", CND_IDX, -1},
487     {"ap", AP_IDX, -1},
488     {"acc", A_IDX, -1},
489     {"ar0", R0_IDX, -1},
490     {"ar1", R1_IDX, -1},
491     {"ar2", R2_IDX, -1},
492     {"ar3", R3_IDX, -1},
493     {"ar4", R4_IDX, -1},
494     {"ar5", R5_IDX, -1},
495     {"ar6", R6_IDX, -1},
496     {"ar7", R7_IDX, -1},
497     {"b", B_IDX, -1},
498     {"c", CND_IDX, -1},
499     {"cy", CND_IDX, -1},
500     {"dph", DPH_IDX, -1},
501     {"dph0", DPH_IDX, -1},
502     {"dph1", DPH1_IDX, -1},
503     {"dpl", DPL_IDX, -1},
504     {"dpl0", DPL_IDX, -1},
505     {"dpl1", DPL1_IDX, -1},
506 /*  {"dptr", DPL_IDX, DPH_IDX}, */ /* dptr is special, based on currentDPS */
507     {"dps", DPS_IDX, -1},
508     {"dpx", DPX_IDX, -1},
509     {"dpx0", DPX_IDX, -1},
510     {"dpx1", DPX1_IDX, -1},
511     {"f0", CND_IDX, -1},
512     {"f1", CND_IDX, -1},
513     {"ov", CND_IDX, -1},
514     {"p", CND_IDX, -1},
515     {"psw", CND_IDX, -1},
516     {"r0", R0_IDX, -1},
517     {"r1", R1_IDX, -1},
518     {"r2", R2_IDX, -1},
519     {"r3", R3_IDX, -1},
520     {"r4", R4_IDX, -1},
521     {"r5", R5_IDX, -1},
522     {"r6", R6_IDX, -1},
523     {"r7", R7_IDX, -1},
524   };
525
526 static int
527 ds390operandCompare (const void *key, const void *member)
528 {
529   return strcmp((const char *)key, ((ds390operanddata *)member)->name);
530 }
531
532 static void      
533 updateOpRW (asmLineNode *aln, char *op, char *optype, int currentDPS)
534 {
535   ds390operanddata *opdat;
536   char *dot;
537   int regIdx1 = -1;
538   int regIdx2 = -1;
539   int regIdx3 = -1;
540   
541   dot = strchr(op, '.');
542   if (dot)
543     *dot = '\0';
544
545   opdat = bsearch (op, ds390operandDataTable,
546                    sizeof(ds390operandDataTable)/sizeof(ds390operanddata),
547                    sizeof(ds390operanddata), ds390operandCompare);
548   
549   if (opdat)
550     {
551       regIdx1 = opdat->regIdx1;
552       regIdx2 = opdat->regIdx2;
553     }
554   if (!strcmp(op, "dptr"))
555     {
556       if (!currentDPS)
557         {
558           regIdx1 = DPL_IDX;
559           regIdx2 = DPH_IDX;
560           regIdx3 = DPX_IDX;
561         }
562       else
563         {
564           regIdx1 = DPL1_IDX;
565           regIdx2 = DPH1_IDX;
566           regIdx3 = DPX1_IDX;
567         }
568     }
569     
570   if (strchr(optype,'r'))
571     {
572       if (regIdx1 >= 0)
573         aln->regsRead = bitVectSetBit (aln->regsRead, regIdx1);
574       if (regIdx2 >= 0)
575         aln->regsRead = bitVectSetBit (aln->regsRead, regIdx2);
576       if (regIdx3 >= 0)
577         aln->regsRead = bitVectSetBit (aln->regsRead, regIdx3);
578     }
579   if (strchr(optype,'w'))
580     {
581       if (regIdx1 >= 0)
582         aln->regsWritten = bitVectSetBit (aln->regsWritten, regIdx1);
583       if (regIdx2 >= 0)
584         aln->regsWritten = bitVectSetBit (aln->regsWritten, regIdx2);
585       if (regIdx3 >= 0)
586         aln->regsWritten = bitVectSetBit (aln->regsWritten, regIdx3);
587     }
588   if (op[0] == '@')
589     {
590       if (!strcmp(op, "@r0"))
591         aln->regsRead = bitVectSetBit (aln->regsRead, R0_IDX);
592       if (!strcmp(op, "@r1"))
593         aln->regsRead = bitVectSetBit (aln->regsRead, R1_IDX);
594       if (strstr(op, "dptr"))
595         {
596           if (!currentDPS)
597             {
598               aln->regsRead = bitVectSetBit (aln->regsRead, DPL_IDX);
599               aln->regsRead = bitVectSetBit (aln->regsRead, DPH_IDX);
600               aln->regsRead = bitVectSetBit (aln->regsRead, DPX_IDX);
601             }
602           else
603             {
604               aln->regsRead = bitVectSetBit (aln->regsRead, DPL1_IDX);
605               aln->regsRead = bitVectSetBit (aln->regsRead, DPH1_IDX);
606               aln->regsRead = bitVectSetBit (aln->regsRead, DPX1_IDX);
607             }
608         }
609       if (strstr(op, "a+"))
610         aln->regsRead = bitVectSetBit (aln->regsRead, A_IDX);
611     }
612 }
613
614 typedef struct ds390opcodedata
615   {
616     char name[6];
617     char class[3];
618     char pswtype[3];
619     char op1type[3];
620     char op2type[3];
621   }
622 ds390opcodedata;
623
624 static ds390opcodedata ds390opcodeDataTable[] =
625   {
626     {"acall","j", "",   "",   ""},
627     {"ajmp", "j", "",   "",   ""},
628     {"add",  "",  "w",  "rw", "r"},
629     {"addc", "",  "rw", "rw", "r"},
630     {"anl",  "",  "",   "rw", "r"},
631     {"cjne", "j", "w",  "r",  "r"},
632     {"clr",  "",  "",   "w",  ""},
633     {"cpl",  "",  "",   "rw", ""},
634     {"da",   "",  "rw", "rw", ""},
635     {"dec",  "",  "",   "rw", ""},
636     {"div",  "",  "w",  "rw", ""},
637     {"djnz", "j", "",  "rw",  ""},
638     {"inc",  "",  "",   "rw", ""},
639     {"jb",   "j", "",   "r",  ""},
640     {"jbc",  "j", "",  "rw",  ""},
641     {"jc",   "j", "",   "",   ""},
642     {"jmp",  "j", "",  "",    ""},
643     {"jnb",  "j", "",   "r",  ""},
644     {"jnc",  "j", "",   "",   ""},
645     {"jnz",  "j", "",  "",    ""},
646     {"jz",   "j", "",  "",    ""},
647     {"lcall","j", "",   "",   ""},
648     {"ljmp", "j", "",   "",   ""},
649     {"mov",  "",  "",   "w",  "r"},
650     {"movc", "",  "",   "w",  "r"},
651     {"movx", "",  "",   "w",  "r"},
652     {"mul",  "",  "w",  "rw", ""},
653     {"nop",  "",  "",   "",   ""},
654     {"orl",  "",  "",   "rw", "r"},
655     {"pop",  "",  "",   "w",  ""},
656     {"push", "",  "",   "r",  ""},
657     {"ret",  "j", "",   "",   ""},
658     {"reti", "j", "",   "",   ""},
659     {"rl",   "",  "",   "rw", ""},
660     {"rlc",  "",  "rw", "rw", ""},
661     {"rr",   "",  "",   "rw", ""},
662     {"rrc",  "",  "rw", "rw", ""},
663     {"setb", "",  "",   "w",  ""},
664     {"sjmp", "j", "",   "",   ""},
665     {"subb", "",  "rw", "rw", "r"},
666     {"swap", "",  "",   "rw", ""},
667     {"xch",  "",  "",   "rw", "rw"},
668     {"xchd", "",  "",   "rw", "rw"},
669     {"xrl",  "",  "",   "rw", "r"},
670   };
671   
672 static int
673 ds390opcodeCompare (const void *key, const void *member)
674 {
675   return strcmp((const char *)key, ((ds390opcodedata *)member)->name);
676 }
677
678 static asmLineNode *
679 asmLineNodeFromLineNode (lineNode *ln, int currentDPS)
680 {
681   asmLineNode *aln = ds390newAsmLineNode(currentDPS);
682   char *op, op1[256], op2[256];
683   int opsize;
684   const char *p;
685   char inst[8];
686   ds390opcodedata *opdat;
687
688   aln->initialized = 1;
689   
690   p = ln->line;
691   
692   while (*p && isspace(*p)) p++;
693   for (op = inst, opsize=1; *p; p++)
694     {
695       if (isspace(*p) || *p == ';' || *p == ':' || *p == '=')
696         break;
697       else
698         if (opsize < sizeof(inst))
699           *op++ = tolower(*p), opsize++;
700     }
701   *op = '\0';
702
703   if (*p == ';' || *p == ':' || *p == '=')
704     return aln;
705     
706   while (*p && isspace(*p)) p++;
707   if (*p == '=')
708     return aln;
709
710   for (op = op1, opsize=1; *p && *p != ','; p++)
711     {
712       if (!isspace(*p) && opsize < sizeof(op1))
713         *op++ = tolower(*p), opsize++;
714     }
715   *op = '\0';
716   
717   if (*p == ',') p++;
718   for (op = op2, opsize=1; *p && *p != ','; p++)
719     {
720       if (!isspace(*p) && opsize < sizeof(op2))
721         *op++ = tolower(*p), opsize++;
722     }
723   *op = '\0';
724
725   aln->size = instructionSize(inst, op1, op2);
726
727   aln->regsRead = newBitVect (END_IDX);
728   aln->regsWritten = newBitVect (END_IDX);
729
730   opdat = bsearch (inst, ds390opcodeDataTable,
731                    sizeof(ds390opcodeDataTable)/sizeof(ds390opcodedata),
732                    sizeof(ds390opcodedata), ds390opcodeCompare);
733
734   if (opdat)
735     {
736       updateOpRW (aln, op1, opdat->op1type, currentDPS);
737       updateOpRW (aln, op2, opdat->op2type, currentDPS);
738       if (strchr(opdat->pswtype,'r'))
739         aln->regsRead = bitVectSetBit (aln->regsRead, CND_IDX);
740       if (strchr(opdat->pswtype,'w'))
741         aln->regsWritten = bitVectSetBit (aln->regsWritten, CND_IDX);
742     }
743
744   return aln;
745 }
746
747 static void
748 initializeAsmLineNode (lineNode *line)
749 {
750   if (!line->aln)
751     line->aln = asmLineNodeFromLineNode (line, 0);
752   else if (line->aln && !line->aln->initialized)
753     {
754       int currentDPS = line->aln->currentDPS;
755       free(line->aln);
756       line->aln = asmLineNodeFromLineNode (line, currentDPS);
757     }
758 }
759
760 static int
761 getInstructionSize (lineNode *line)
762 {
763   initializeAsmLineNode (line);
764   return line->aln->size;
765 }
766
767 static bitVect *
768 getRegsRead (lineNode *line)
769 {
770   initializeAsmLineNode (line);
771   return line->aln->regsRead;
772 }
773
774 static bitVect *
775 getRegsWritten (lineNode *line)
776 {
777   initializeAsmLineNode (line);
778   return line->aln->regsWritten;
779 }
780
781
782 /** $1 is always the basename.
783     $2 is always the output file.
784     $3 varies
785     $l is the list of extra options that should be there somewhere...
786     MUST be terminated with a NULL.
787 */
788 static const char *_linkCmd[] =
789 {
790   "aslink", "-nf", "\"$1\"", NULL
791 };
792
793 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */   static const char *_asmCmd[] =
794 {
795   "asx8051", "$l", "$3", "\"$1.asm\"", NULL
796 };
797
798 /* Globals */
799 PORT ds390_port =
800 {
801   TARGET_ID_DS390,
802   "ds390",
803   "DS80C390",                   /* Target name */
804   NULL,
805   {
806     glue,
807     TRUE,                       /* Emit glue around main */
808     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
809     MODEL_SMALL
810   },
811   {
812     _asmCmd,
813     NULL,
814     "-plosgffc",                /* Options with debug */
815     "-plosgff",                 /* Options without debug */
816     0,
817     ".asm",
818     NULL                        /* no do_assemble function */
819   },
820   {
821     _linkCmd,
822     NULL,
823     NULL,
824     ".rel",
825     1
826   },
827   {
828     _defaultRules,
829     getInstructionSize,
830     getRegsRead,
831     getRegsWritten
832   },
833   {
834         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
835     1, 2, 2, 4, 1, 2, 3, 1, 4, 4
836   },
837   {
838     "XSEG    (XDATA)",
839     "STACK   (DATA)",
840     "CSEG    (CODE)",
841     "DSEG    (DATA)",
842     "ISEG    (DATA)",
843     "XSEG    (XDATA)",
844     "BSEG    (BIT)",
845     "RSEG    (DATA)",
846     "GSINIT  (CODE)",
847     "OSEG    (OVR,DATA)",
848     "GSFINAL (CODE)",
849     "HOME    (CODE)",
850     "XISEG   (XDATA)", // initialized xdata
851     "XINIT   (CODE)", // a code copy of xiseg
852     NULL,
853     NULL,
854     1
855   },
856   { NULL, NULL },
857   {
858     +1, 1, 4, 1, 1, 0
859   },
860     /* ds390 has an 16 bit mul & div */
861   {
862     2, -1
863   },
864   "_",
865   _ds390_init,
866   _ds390_parseOptions,
867   NULL,
868   _ds390_finaliseOptions,
869   _ds390_setDefaultOptions,
870   ds390_assignRegisters,
871   _ds390_getRegName,
872   _ds390_keywords,
873   _ds390_genAssemblerPreamble,
874   NULL,                         /* no genAssemblerEnd */
875   _ds390_genIVT,
876   _ds390_genXINIT,
877   _ds390_reset_regparm,
878   _ds390_regparm,
879   NULL,
880   NULL,
881   _ds390_nativeMulCheck,
882   hasExtBitOp,                  /* hasExtBitOp */
883   oclsExpense,                  /* oclsExpense */
884   FALSE,
885   TRUE,                         /* little endian */
886   0,                            /* leave lt */
887   0,                            /* leave gt */
888   1,                            /* transform <= to ! > */
889   1,                            /* transform >= to ! < */
890   1,                            /* transform != to !(a == b) */
891   0,                            /* leave == */
892 #if 0 // obsolete, and buggy for != xdata
893   TRUE,                         /* we support array initializers. */
894 #else
895   FALSE,                        /* No array initializer support. */
896 #endif
897   cseCostEstimation,
898   __ds390_builtins,             /* table of builtin functions */
899   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
900   1,                            /* reset labelKey to 1 */
901   1,                            /* globals & local static allowed */
902   PORT_MAGIC
903 };
904
905 /*---------------------------------------------------------------------------------*/
906 /*                               TININative specific                               */
907 /*---------------------------------------------------------------------------------*/
908 /* Globals */
909 static void _tininative_init (void)
910 {
911     asm_addTree (&asm_a390_mapping);
912 }
913
914 static void _tininative_setDefaultOptions (void)
915 {
916     options.model=MODEL_FLAT24;
917     options.stack10bit=1;
918     options.stackAuto = 1;
919 }
920
921 static void _tininative_finaliseOptions (void)
922 {
923     /* Hack-o-matic: if we are using the flat24 model,
924      * adjust pointer sizes.
925      */
926     if (options.model != MODEL_FLAT24)  {
927         options.model = MODEL_FLAT24 ;
928         fprintf(stderr,"TININative supports only MODEL FLAT24\n");
929     }
930     port->s.fptr_size = 3;
931     port->s.gptr_size = 4;
932     
933     port->stack.isr_overhead += 2;      /* Will save dpx on ISR entry. */
934     
935     port->stack.call_overhead += 2;     /* This acounts for the extra byte 
936                                          * of return addres on the stack.
937                                          * but is ugly. There must be a 
938                                          * better way.
939                                          */
940     
941     port->mem.default_local_map = xdata;
942     port->mem.default_globl_map = xdata;
943     
944     if (!options.stack10bit) {
945         options.stack10bit = 1;
946         fprintf(stderr,"TININative supports only stack10bit \n");
947     }
948     
949     if (!options.stack_loc) options.stack_loc = 0x400008;
950     
951     /* generate native code 16*16 mul/div */
952     if (options.useAccelerator) 
953         port->support.muldiv=2;
954     else 
955         port->support.muldiv=1;
956     
957     /* Fixup the memory map for the stack; it is now in
958      * far space and requires a FPOINTER to access it.
959      */
960     istack->fmap = 1;
961     istack->ptrType = FPOINTER;
962     options.cc_only =1;
963 }
964
965 static int _tininative_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts) 
966 {
967     return 1;
968 }
969 static void _tininative_genAssemblerPreamble (FILE * of)
970 {
971     fputs("$include(tini.inc)\n", of);
972     fputs("$include(ds80c390.inc)\n", of);
973     fputs("$include(tinimacro.inc)\n", of);
974     fputs("$include(apiequ.inc)\n", of);
975     fputs("_bpx EQU 01Eh \t\t; _bpx (frame pointer) mapped to R8_B3:R7_B3\n", of);
976     fputs("_ap  EQU 01Dh \t\t; _ap mapped to R6_B3\n", of);
977     /* Must be first and return 0 */
978     fputs("Lib_Native_Init:\n",of);
979     fputs("\tclr\ta\n",of);
980     fputs("\tret\n",of);
981     fputs("LibraryID:\n",of);
982     fputs("\tdb \"DS\"\n",of);
983     if (options.tini_libid) {
984         fprintf(of,"\tdb 0,0,0%02xh,0%02xh,0%02xh,0%02xh\n",
985                 (options.tini_libid>>24 & 0xff),
986                 (options.tini_libid>>16 & 0xff),
987                 (options.tini_libid>>8 & 0xff),
988                 (options.tini_libid  & 0xff));
989     } else {
990         fprintf(of,"\tdb 0,0,0,0,0,1\n");
991     }
992
993 }
994 static void _tininative_genAssemblerEnd (FILE * of)
995 {
996     fputs("\tend\n",of);
997 }
998 /* tininative assembler , calls "macro", if it succeeds calls "a390" */
999 static void _tininative_do_assemble (set *asmOptions)
1000 {
1001     static const char *macroCmd[] = {
1002         "macro","$1.a51",NULL
1003     };
1004     static const char *a390Cmd[] = {
1005         "a390","$1.mpp",NULL
1006     };
1007     char buffer[100];
1008
1009     buildCmdLine(buffer,macroCmd,dstFileName,NULL,NULL,NULL);
1010     if (my_system(buffer)) {
1011         exit(1);
1012     }
1013     buildCmdLine(buffer,a390Cmd,dstFileName,NULL,NULL,asmOptions);
1014     if (my_system(buffer)) {
1015         exit(1);
1016     }    
1017 }
1018
1019 /* list of key words used by TININative */
1020 static char *_tininative_keywords[] =
1021 {
1022   "at",
1023   "bit",
1024   "code",
1025   "critical",
1026   "data",
1027   "far",
1028   "idata",
1029   "interrupt",
1030   "near",
1031   "pdata",
1032   "reentrant",
1033   "sfr",
1034   "sbit",
1035   "using",
1036   "xdata",
1037   "_data",
1038   "_code",
1039   "_generic",
1040   "_near",
1041   "_xdata",
1042   "_pdata",
1043   "_idata",
1044   "_naked",
1045   "_JavaNative",
1046   NULL
1047 };
1048
1049 static builtins __tininative_builtins[] = {
1050     { "__builtin_memcpy_x2x","v",3,{"cx*","cx*","i"}}, /* void __builtin_memcpy_x2x (xdata char *,xdata char *,int) */
1051     { "__builtin_memcpy_c2x","v",3,{"cx*","cp*","i"}}, /* void __builtin_memcpy_c2x (xdata char *,code  char *,int) */
1052     { "__builtin_memset_x","v",3,{"cx*","c","i"}},     /* void __builtin_memset     (xdata char *,char,int)         */
1053     /* TINI NatLib */
1054     { "NatLib_LoadByte","c",1,{"c"}},                  /* char  Natlib_LoadByte  (0 based parameter number)         */
1055     { "NatLib_LoadShort","s",1,{"c"}},                 /* short Natlib_LoadShort (0 based parameter number)         */
1056     { "NatLib_LoadInt","l",1,{"c"}},                   /* long  Natlib_LoadLong  (0 based parameter number)         */
1057     { "NatLib_LoadPointer","cx*",1,{"c"}},             /* long  Natlib_LoadPointer  (0 based parameter number)      */
1058     /* TINI StateBlock related */
1059     { "NatLib_InstallImmutableStateBlock","c",2,{"vx*","us"}},/* char NatLib_InstallImmutableStateBlock(state block *,int handle) */
1060     { "NatLib_InstallEphemeralStateBlock","c",2,{"vx*","us"}},/* char NatLib_InstallEphemeralStateBlock(state block *,int handle) */
1061     { "NatLib_RemoveImmutableStateBlock","v",0,{NULL}},/* void NatLib_RemoveImmutableStateBlock() */
1062     { "NatLib_RemoveEphemeralStateBlock","v",0,{NULL}},/* void NatLib_RemoveEphemeralStateBlock() */
1063     { "NatLib_GetImmutableStateBlock","i",0,{NULL}},   /* int  NatLib_GetImmutableStateBlock () */
1064     { "NatLib_GetEphemeralStateBlock","i",0,{NULL}},   /* int  NatLib_GetEphemeralStateBlock () */
1065     /* Memory manager */
1066     { "MM_XMalloc","i",1,{"l"}},                       /* int  MM_XMalloc (long)                */
1067     { "MM_Malloc","i",1,{"i"}},                        /* int  MM_Malloc  (int)                 */
1068     { "MM_ApplicationMalloc","i",1,{"i"}},             /* int  MM_ApplicationMalloc  (int)      */
1069     { "MM_Free","i",1,{"i"}},                          /* int  MM_Free  (int)                   */
1070     { "MM_Deref","cx*",1,{"i"}},                       /* char *MM_Free  (int)                  */
1071     { "MM_UnrestrictedPersist","c",1,{"i"}},           /* char  MM_UnrestrictedPersist  (int)   */
1072     /* System functions */
1073     { "System_ExecJavaProcess","c",2,{"cx*","i"}},     /* char System_ExecJavaProcess (char *,int) */
1074     { "System_GetRTCRegisters","v",1,{"cx*"}},         /* void System_GetRTCRegisters (char *) */
1075     { "System_SetRTCRegisters","v",1,{"cx*"}},         /* void System_SetRTCRegisters (char *) */
1076     { "System_ThreadSleep","v",2,{"l","c"}},           /* void System_ThreadSleep (long,char)  */
1077     { "System_ThreadSleep_ExitCriticalSection","v",2,{"l","c"}},/* void System_ThreadSleep_ExitCriticalSection (long,char)  */
1078     { "System_ProcessSleep","v",2,{"l","c"}},           /* void System_ProcessSleep (long,char)  */
1079     { "System_ProcessSleep_ExitCriticalSection","v",2,{"l","c"}},/* void System_ProcessSleep_ExitCriticalSection (long,char)  */
1080     { "System_ThreadResume","c",2,{"c","c"}},          /* char System_ThreadResume(char,char)  */
1081     { "System_SaveJavaThreadState","v",0,{NULL}},      /* void System_SaveJavaThreadState()    */
1082     { "System_RestoreJavaThreadState","v",0,{NULL}},   /* void System_RestoreJavaThreadState() */
1083     { "System_ProcessYield","v",0,{NULL}},             /* void System_ProcessYield() */
1084     { "System_ProcessSuspend","v",0,{NULL}},           /* void System_ProcessSuspend() */
1085     { "System_ProcessResume","v",1,{"c"}},             /* void System_ProcessResume(char) */
1086     { "System_RegisterPoll","c",1,{"vF*"}},            /* char System_RegisterPoll ((void *func pointer)()) */
1087     { "System_RemovePoll","c",1,{"vF*"}},              /* char System_RemovePoll ((void *func pointer)()) */
1088     { "System_GetCurrentProcessId","c",0,{NULL}},      /* char System_GetCurrentProcessId() */
1089     { "System_GetCurrentThreadId","c",0,{NULL}},       /* char System_GetCurrentThreadId() */
1090     { NULL , NULL,0, {NULL}}                       /* mark end of table */
1091 };    
1092
1093 static const char *_a390Cmd[] =
1094 {
1095   "macro", "$l", "$3", "$1.a51", NULL
1096 };
1097 PORT tininative_port =
1098 {
1099   TARGET_ID_DS390,
1100   "TININative",
1101   "DS80C390",                   /* Target name */
1102         NULL,                   /* processor */
1103   {
1104     glue,
1105     FALSE,                      /* Emit glue around main */
1106     MODEL_FLAT24,
1107     MODEL_FLAT24
1108   },
1109   {
1110     _a390Cmd,
1111     NULL,
1112     "-l",               /* Options with debug */
1113     "-l",               /* Options without debug */
1114     0,
1115     ".a51",
1116     _tininative_do_assemble
1117   },
1118   {
1119     NULL,
1120     NULL,
1121     NULL,
1122     ".tlib",
1123     1
1124   },
1125   {
1126     _defaultRules,
1127     getInstructionSize,
1128     getRegsRead,
1129     getRegsWritten
1130   },
1131   {
1132         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
1133     1, 2, 2, 4, 1, 3, 3, 1, 4, 4
1134   },
1135   {
1136     "XSEG    (XDATA)",
1137     "STACK   (DATA)",
1138     "CSEG    (CODE)",
1139     "DSEG    (DATA)",
1140     "ISEG    (DATA)",
1141     "XSEG    (XDATA)",
1142     "BSEG    (BIT)",
1143     "RSEG    (DATA)",
1144     "GSINIT  (CODE)",
1145     "OSEG    (OVR,DATA)",
1146     "GSFINAL (CODE)",
1147     "HOME        (CODE)",
1148     NULL,
1149     NULL,
1150     NULL,
1151     NULL,
1152     1
1153   },
1154   { NULL, NULL },
1155   {
1156     +1, 1, 4, 1, 1, 0
1157   },
1158     /* ds390 has an 16 bit mul & div */
1159   {
1160     2, -1
1161   },
1162   "",
1163   _tininative_init,
1164   _ds390_parseOptions,
1165   NULL,
1166   _tininative_finaliseOptions,
1167   _tininative_setDefaultOptions,
1168   ds390_assignRegisters,
1169   _ds390_getRegName,
1170   _tininative_keywords,
1171   _tininative_genAssemblerPreamble,
1172   _tininative_genAssemblerEnd,
1173   _tininative_genIVT,
1174   NULL,
1175   _ds390_reset_regparm,
1176   _ds390_regparm,
1177   NULL,
1178   NULL,
1179   NULL,
1180   hasExtBitOp,                  /* hasExtBitOp */
1181   oclsExpense,                  /* oclsExpense */
1182   FALSE,
1183   TRUE,                         /* little endian */
1184   0,                            /* leave lt */
1185   0,                            /* leave gt */
1186   1,                            /* transform <= to ! > */
1187   1,                            /* transform >= to ! < */
1188   1,                            /* transform != to !(a == b) */
1189   0,                            /* leave == */
1190   TRUE,                         /* we support array initializers. */
1191   cseCostEstimation,
1192   __tininative_builtins,        /* table of builtin functions */
1193   FPOINTER,                     /* treat unqualified pointers as far pointers */
1194   0,                            /* DONOT reset labelKey */
1195   0,                            /* globals & local static NOT allowed */
1196   PORT_MAGIC
1197 };
1198
1199 static int
1200 _ds400_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
1201 {
1202     /* We can't generate a static IVT, since the boot rom creates one
1203      * for us in rom_init.
1204      * 
1205      * we must patch it as part of the C startup.
1206      */
1207      fprintf (of, ";\tDS80C400 IVT must be generated at runtime.\n");
1208     fprintf (of, "\tsjmp\t__sdcc_400boot\n");
1209     fprintf (of, "\t.ascii\t'TINI'\t; required signature for 400 boot loader.\n");
1210     fprintf (of, "\t.db\t0\t; selected bank: zero *should* work...\n");
1211     fprintf (of, "\t__sdcc_400boot:\tljmp\t__sdcc_gsinit_startup\n");
1212      return TRUE;
1213 }
1214
1215     
1216
1217 static void
1218 _ds400_finaliseOptions (void)
1219 {
1220   if (options.noXinitOpt) {
1221     port->genXINIT=0;
1222   }
1223
1224   // hackhack: we're a superset of the 390.
1225   addSet(&preArgvSet, Safe_strdup("-DSDCC_ds390"));
1226   addSet(&preArgvSet, Safe_strdup("-D__ds390"));
1227     
1228   /* Hack-o-matic: if we are using the flat24 model,
1229    * adjust pointer sizes.
1230    */
1231   if (options.model != MODEL_FLAT24)  {
1232       fprintf (stderr,
1233                "*** warning: ds400 port small and large model experimental.\n");
1234       if (options.model == MODEL_LARGE)
1235       {
1236         port->mem.default_local_map = xdata;
1237         port->mem.default_globl_map = xdata;
1238       }
1239       else
1240       {
1241         port->mem.default_local_map = data;
1242         port->mem.default_globl_map = data;
1243       }
1244   }
1245   else {
1246     port->s.fptr_size = 3;
1247     port->s.gptr_size = 4;
1248
1249     port->stack.isr_overhead += 2;      /* Will save dpx on ISR entry. */
1250
1251     port->stack.call_overhead += 2;     /* This acounts for the extra byte 
1252                                  * of return addres on the stack.
1253                                  * but is ugly. There must be a 
1254                                  * better way.
1255                                  */
1256
1257     port->mem.default_local_map = xdata;
1258     port->mem.default_globl_map = xdata;
1259
1260     if (!options.stack10bit)
1261     {
1262     fprintf (stderr,
1263              "*** error: ds400 port only supports the 10 bit stack mode.\n");
1264     } else {
1265         if (!options.stack_loc) options.stack_loc = 0xffdc00;
1266         // assumes IDM1:0 = 1:0, CMA = 1.
1267     }
1268     
1269     /* generate native code 16*16 mul/div */
1270     if (options.useAccelerator) 
1271             port->support.muldiv=2;
1272     else 
1273             port->support.muldiv=1;
1274
1275      /* Fixup the memory map for the stack; it is now in
1276      * far space and requires a FPOINTER to access it.
1277      */
1278     istack->fmap = 1;
1279     istack->ptrType = FPOINTER;
1280
1281     if (options.parms_in_bank1) {
1282         addSet(&preArgvSet, Safe_strdup("-DSDCC_PARMS_IN_BANK1"));
1283     }
1284      
1285     // the DS400 rom calling interface uses register bank 3.
1286     RegBankUsed[3] = 1;
1287       
1288   }  /* MODEL_FLAT24 */
1289 }
1290
1291 extern char * iComments2;
1292
1293 static void _ds400_generateRomDataArea(FILE *fp, bool isMain)
1294 {
1295     /* Only do this for the file containing main() */
1296     if (isMain)
1297     {
1298         fprintf(fp, "%s", iComments2);
1299         fprintf(fp, "; the direct data area used by the DS80c400 ROM code.\n");
1300         fprintf(fp, "%s", iComments2);
1301         fprintf(fp, ".area ROMSEG (ABS,CON,DATA)\n\n");
1302         fprintf(fp, ".ds 24 ; 24 bytes of directs used starting at 0x68\n\n");
1303     }
1304 }
1305
1306 static void _ds400_linkRomDataArea(FILE *fp)
1307 {
1308     fprintf(fp, "-b ROMSEG = 0x0068\n");
1309 }
1310
1311
1312 PORT ds400_port =
1313 {
1314   TARGET_ID_DS400,
1315   "ds400",
1316   "DS80C400",                   /* Target name */
1317   NULL,
1318   {
1319     glue,
1320     TRUE,                       /* Emit glue around main */
1321     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
1322     MODEL_SMALL
1323   },
1324   {
1325     _asmCmd,
1326     NULL,
1327     "-plosgffc",                /* Options with debug */
1328     "-plosgff",                 /* Options without debug */
1329     0,
1330     ".asm",
1331     NULL                        /* no do_assemble function */
1332   },
1333   {
1334     _linkCmd,
1335     NULL,
1336     NULL,
1337     ".rel",
1338     1
1339   },
1340   {
1341     _defaultRules,
1342     getInstructionSize,
1343     getRegsRead,
1344     getRegsWritten
1345   },
1346   {
1347         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
1348     1, 2, 2, 4, 1, 2, 3, 1, 4, 4
1349   },
1350   {
1351     "XSEG    (XDATA)",
1352     "STACK   (DATA)",
1353     "CSEG    (CODE)",
1354     "DSEG    (DATA)",
1355     "ISEG    (DATA)",
1356     "XSEG    (XDATA)",
1357     "BSEG    (BIT)",
1358     "RSEG    (DATA)",
1359     "GSINIT  (CODE)",
1360     "OSEG    (OVR,DATA)",
1361     "GSFINAL (CODE)",
1362     "HOME    (CODE)",
1363     "XISEG   (XDATA)", // initialized xdata
1364     "XINIT   (CODE)", // a code copy of xiseg
1365     NULL,
1366     NULL,
1367     1
1368   },
1369   { _ds400_generateRomDataArea, _ds400_linkRomDataArea },
1370   {
1371     +1, 1, 4, 1, 1, 0
1372   },
1373     /* ds390 has an 16 bit mul & div */
1374   {
1375     2, -1
1376   },
1377   "_",
1378   _ds390_init,
1379   _ds390_parseOptions,
1380   NULL,
1381   _ds400_finaliseOptions,
1382   _ds390_setDefaultOptions,
1383   ds390_assignRegisters,
1384   _ds390_getRegName,
1385   _ds390_keywords,
1386   _ds390_genAssemblerPreamble,
1387   NULL,                         /* no genAssemblerEnd */
1388   _ds400_genIVT,
1389   _ds390_genXINIT,
1390   _ds390_reset_regparm,
1391   _ds390_regparm,
1392   NULL,
1393   NULL,
1394   _ds390_nativeMulCheck,
1395   hasExtBitOp,                  /* hasExtBitOp */
1396   oclsExpense,                  /* oclsExpense */
1397   FALSE,
1398   TRUE,                         /* little endian */
1399   0,                            /* leave lt */
1400   0,                            /* leave gt */
1401   1,                            /* transform <= to ! > */
1402   1,                            /* transform >= to ! < */
1403   1,                            /* transform != to !(a == b) */
1404   0,                            /* leave == */
1405   TRUE,                         /* we support array initializers. */
1406   cseCostEstimation,
1407   __ds390_builtins,             /* table of builtin functions */
1408   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
1409   1,                            /* reset labelKey to 1 */
1410   1,                            /* globals & local static allowed */
1411   PORT_MAGIC
1412 };