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