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