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