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