* Makefile.in, configure.in, configure,
[fw/sdcc] / src / ds390 / main.c
index 27e4f5fc6aa1ce35c12a2b74e24aecdb7fb8280c..8b82663f35f62346fab4869f82932e867aa0d1b4 100644 (file)
@@ -10,6 +10,7 @@
 #include "gen.h"
 #include "BuildCmd.h"
 #include "MySystem.h"
+#include "dbuf_string.h"
 #include "../SDCCutil.h"
 #include "../SDCCglobl.h"
 static char _defaultRules[] =
@@ -17,6 +18,25 @@ static char _defaultRules[] =
 #include "peeph.rul"
 };
 
+#define OPTION_STACK_8BIT       "--stack-8bit"
+#define OPTION_FLAT24_MODEL     "--model-flat24"
+#define OPTION_STACK_SIZE       "--stack-size"
+
+static OPTION _ds390_options[] =
+  {
+    { 0, OPTION_FLAT24_MODEL,   NULL, "use the flat24 model for the ds390 (default)" },
+    { 0, OPTION_STACK_8BIT,     NULL, "use the 8bit stack for the ds390 (not supported yet)" },
+    { 0, OPTION_STACK_SIZE,     &options.stack_size, "Tells the linker to allocate this space for stack", CLAT_INTEGER },
+    { 0, "--pack-iram",         NULL, "Tells the linker to pack variables in internal ram (default)"},
+    { 0, "--no-pack-iram",      &options.no_pack_iram, "Tells the linker not to pack variables in internal ram"},
+    { 0, "--stack-10bit",       &options.stack10bit, "use the 10bit stack for ds390 (default)" },
+    { 0, "--use-accelerator",   &options.useAccelerator, "generate code for ds390 arithmetic accelerator"},
+    { 0, "--protect-sp-update", &options.protect_sp_update, "will disable interrupts during ESP:SP updates"},
+    { 0, "--parms-in-bank1",    &options.parms_in_bank1, "use Bank1 for parameter passing"},
+    { 0, NULL }
+  };
+
+
 /* list of key words used by msc51 */
 static char *_ds390_keywords[] =
 {
@@ -32,6 +52,8 @@ static char *_ds390_keywords[] =
   "pdata",
   "reentrant",
   "sfr",
+  "sfr16",
+  "sfr32",
   "sbit",
   "using",
   "xdata",
@@ -49,19 +71,19 @@ static char *_ds390_keywords[] =
 static builtins __ds390_builtins[] = {
     { "__builtin_memcpy_x2x","v",3,{"cx*","cx*","i"}}, /* void __builtin_memcpy_x2x (xdata char *,xdata char *,int) */
     { "__builtin_memcpy_c2x","v",3,{"cx*","cp*","i"}}, /* void __builtin_memcpy_c2x (xdata char *,code  char *,int) */
-    { "__builtin_memset_x","v",3,{"cx*","c","i"}},     /* void __builtin_memset     (xdata char *,char,int)        */
+    { "__builtin_memset_x","v",3,{"cx*","c","i"}},     /* void __builtin_memset     (xdata char *,char,int)         */
     /* __builtin_inp - used to read from a memory mapped port, increment first pointer */
     { "__builtin_inp","v",3,{"cx*","cx*","i"}},        /* void __builtin_inp        (xdata char *,xdata char *,int) */
     /* __builtin_inp - used to write to a memory mapped port, increment first pointer */
     { "__builtin_outp","v",3,{"cx*","cx*","i"}},       /* void __builtin_outp       (xdata char *,xdata char *,int) */
-    { "__builtin_swapw","us",1,{"us"}},                       /* unsigned short __builtin_swapw (unsigned short) */
+    { "__builtin_swapw","us",1,{"us"}},                /* unsigned short __builtin_swapw (unsigned short) */
     { "__builtin_memcmp_x2x","c",3,{"cx*","cx*","i"}}, /* void __builtin_memcmp_x2x (xdata char *,xdata char *,int) */
     { "__builtin_memcmp_c2x","c",3,{"cx*","cp*","i"}}, /* void __builtin_memcmp_c2x (xdata char *,code  char *,int) */
-    { NULL , NULL,0, {NULL}}                      /* mark end of table */
-};    
-void ds390_assignRegisters (eBBlock ** ebbs, int count);
+    { NULL , NULL,0, {NULL}}                       /* mark end of table */
+};
+void ds390_assignRegisters (ebbIndex * ebbi);
 
-static int regParmFlg = 0;     /* determine if we can register a parameter */
+static int regParmFlg = 0;      /* determine if we can register a parameter */
 
 static void
 _ds390_init (void)
@@ -70,39 +92,40 @@ _ds390_init (void)
 }
 
 static void
-_ds390_reset_regparm ()
+_ds390_reset_regparm (void)
 {
   regParmFlg = 0;
 }
 
 static int
-_ds390_regparm (sym_link * l)
+_ds390_regparm (sym_link * l, bool reentrant)
 {
-
+    if (IS_SPEC(l) && (SPEC_NOUN(l) == V_BIT))
+        return 0;
     if (options.parms_in_bank1 == 0) {
-       /* simple can pass only the first parameter in a register */
-       if (regParmFlg)
-           return 0;
+        /* simple can pass only the first parameter in a register */
+        if (regParmFlg)
+            return 0;
 
-       regParmFlg = 1;
-       return 1;
+        regParmFlg = 1;
+        return 1;
     } else {
-       int size = getSize(l);
-       int remain ;
-
-       /* first one goes the usual way to DPTR */
-       if (regParmFlg == 0) {
-           regParmFlg += 4 ;
-           return 1;
-       }
-       /* second one onwards goes to RB1_0 thru RB1_7 */
+        int size = getSize(l);
+        int remain ;
+
+        /* first one goes the usual way to DPTR */
+        if (regParmFlg == 0) {
+            regParmFlg += 4 ;
+            return 1;
+        }
+        /* second one onwards goes to RB1_0 thru RB1_7 */
         remain = regParmFlg - 4;
-       if (size > (8 - remain)) {
-           regParmFlg = 12 ;
-           return 0;
-       }
-       regParmFlg += size ;
-       return regParmFlg - size + 1;   
+        if (size > (8 - remain)) {
+            regParmFlg = 12 ;
+            return 0;
+        }
+        regParmFlg += size ;
+        return regParmFlg - size + 1;
     }
 }
 
@@ -112,6 +135,16 @@ _ds390_parseOptions (int *pargc, char **argv, int *i)
   /* TODO: allow port-specific command line options to specify
    * segment names here.
    */
+  if (!strcmp (argv[*i], OPTION_STACK_8BIT))
+    {
+      options.stack10bit = 0;
+      return TRUE;
+    }
+  else if (!strcmp (argv[*i], OPTION_FLAT24_MODEL))
+    {
+      options.model = MODEL_FLAT24;
+      return TRUE;
+    }
   return FALSE;
 }
 
@@ -127,7 +160,7 @@ _ds390_finaliseOptions (void)
    */
   if (options.model != MODEL_FLAT24)  {
       fprintf (stderr,
-              "*** warning: ds390 port small and large model experimental.\n");
+               "*** warning: ds390 port small and large model experimental.\n");
       if (options.model == MODEL_LARGE)
       {
         port->mem.default_local_map = xdata;
@@ -143,13 +176,13 @@ _ds390_finaliseOptions (void)
     port->s.fptr_size = 3;
     port->s.gptr_size = 4;
 
-    port->stack.isr_overhead += 2;     /* Will save dpx on ISR entry. */
+    port->stack.isr_overhead += 2;      /* Will save dpx on ISR entry. */
 
-    port->stack.call_overhead += 2;    /* This acounts for the extra byte 
-                                * of return addres on the stack.
-                                * but is ugly. There must be a 
-                                * better way.
-                                */
+    port->stack.call_overhead += 2;     /* This acounts for the extra byte
+                                 * of return addres on the stack.
+                                 * but is ugly. There must be a
+                                 * better way.
+                                 */
 
     port->mem.default_local_map = xdata;
     port->mem.default_globl_map = xdata;
@@ -157,16 +190,16 @@ _ds390_finaliseOptions (void)
     if (!options.stack10bit)
     {
     fprintf (stderr,
-            "*** error: ds390 port only supports the 10 bit stack mode.\n");
+             "*** error: ds390 port only supports the 10 bit stack mode.\n");
     } else {
-       if (!options.stack_loc) options.stack_loc = 0x400008;
+        if (!options.stack_loc) options.stack_loc = 0x400008;
     }
-    
+
     /* generate native code 16*16 mul/div */
-    if (options.useAccelerator) 
-           port->support.muldiv=2;
-    else 
-           port->support.muldiv=1;
+    if (options.useAccelerator)
+            port->support.muldiv=2;
+    else
+            port->support.muldiv=1;
 
      /* Fixup the memory map for the stack; it is now in
      * far space and requires a FPOINTER to access it.
@@ -175,7 +208,7 @@ _ds390_finaliseOptions (void)
     istack->ptrType = FPOINTER;
 
     if (options.parms_in_bank1) {
-       addSet(&preArgvSet, Safe_strdup("-DSDCC_PARMS_IN_BANK1"));
+        addSet(&preArgvSet, Safe_strdup("-DSDCC_PARMS_IN_BANK1"));
     }
   }  /* MODEL_FLAT24 */
 }
@@ -222,44 +255,99 @@ _ds390_genAssemblerPreamble (FILE * of)
       fputs ("mc\t=\t0xD5\n", of);
       fputs ("F1\t=\t0xD1\t; user flag\n", of);
       if (options.parms_in_bank1) {
-         int i ;
-         for (i=0; i < 8 ; i++ )
-             fprintf (of,"b1_%d\t=\t0x%02X\n",i,8+i);
+          int i ;
+          for (i=0; i < 8 ; i++ )
+              fprintf (of,"b1_%d\t=\t0x%02X\n",i,8+i);
       }
 }
 
 /* Generate interrupt vector table. */
 static int
-_ds390_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
+_ds390_genIVT (struct dbuf_s * oBuf, symbol ** interrupts, int maxInterrupts)
 {
   int i;
 
   if (options.model != MODEL_FLAT24)
     {
-      /* Let the default code handle it. */
-      return FALSE;
+      dbuf_printf (oBuf, "\tljmp\t__sdcc_gsinit_startup\n");
+
+      /* now for the other interrupts */
+      for (i = 0; i < maxInterrupts; i++)
+        {
+          if (interrupts[i])
+            {
+              dbuf_printf (oBuf, "\tljmp\t%s\n", interrupts[i]->rname);
+              if ( i != maxInterrupts - 1 )
+                dbuf_printf (oBuf, "\t.ds\t5\n");
+            }
+          else
+            {
+              dbuf_printf (oBuf, "\treti\n");
+              if ( i != maxInterrupts - 1 )
+                dbuf_printf (oBuf, "\t.ds\t7\n");
+            }
+        }
+      return TRUE;
     }
 
-  fprintf (of, "\tajmp\t__reset_vect\n");
+  dbuf_printf (oBuf, "\tajmp\t__reset_vect\n");
 
   /* now for the other interrupts */
   for (i = 0; i < maxInterrupts; i++)
     {
       if (interrupts[i])
-       {
-         fprintf (of, "\tljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
-       }
+        {
+          dbuf_printf (oBuf, "\tljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
+        }
       else
-       {
-         fprintf (of, "\treti\n\t.ds\t7\n");
-       }
+        {
+          dbuf_printf (oBuf, "\treti\n\t.ds\t7\n");
+        }
     }
 
-  fprintf (of, "__reset_vect:\n\tljmp\t__sdcc_gsinit_startup\n");
+  dbuf_printf (oBuf, "__reset_vect:\n\tljmp\t__sdcc_gsinit_startup\n");
 
   return TRUE;
 }
 
+static void
+_ds390_genInitStartup (FILE *of)
+{
+  fprintf (of, "__sdcc_gsinit_startup:\n");
+  /* if external stack is specified then the
+     higher order byte of the xdatalocation is
+     going into P2 and the lower order going into
+     spx */
+  if (options.useXstack)
+    {
+      fprintf (of, "\tmov\tP2,#0x%02x\n",
+               (((unsigned int) options.xdata_loc) >> 8) & 0xff);
+      fprintf (of, "\tmov\t_spx,#0x%02x\n",
+               (unsigned int) options.xdata_loc & 0xff);
+    }
+
+  // This should probably be a port option, but I'm being lazy.
+  // on the 400, the firmware boot loader gives us a valid stack
+  // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
+  if (!TARGET_IS_DS400)
+    {
+      /* initialise the stack pointer.  JCF: aslink takes care of the location */
+      fprintf (of, "\tmov\tsp,#__start__stack - 1\n");     /* MOF */
+    }
+
+  fprintf (of, "\tlcall\t__sdcc_external_startup\n");
+  fprintf (of, "\tmov\ta,dpl\n");
+  fprintf (of, "\tjz\t__sdcc_init_data\n");
+  fprintf (of, "\tljmp\t__sdcc_program_startup\n");
+  fprintf (of, "__sdcc_init_data:\n");
+
+  // if the port can copy the XINIT segment to XISEG
+  if (port->genXINIT)
+    {
+      port->genXINIT(of);
+    }
+}
+
 /* Generate code to copy XINIT to XISEG */
 static void _ds390_genXINIT (FILE * of) {
   fprintf (of, ";      _ds390_genXINIT() start\n");
@@ -298,19 +386,19 @@ static bool cseCostEstimation (iCode *ic, iCode *pdic)
     sym_link *result_type = operandType(result);
     //sym_link *right_type  = (right ? operandType(right) : 0);
     //sym_link *left_type   = (left  ? operandType(left)  : 0);
-    
+
     /* if it is a pointer then return ok for now */
     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
-    
-    /* if bitwise | add & subtract then no since mcs51 is pretty good at it 
+
+    /* if bitwise | add & subtract then no since mcs51 is pretty good at it
        so we will cse only if they are local (i.e. both ic & pdic belong to
        the same basic block */
     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
-       /* then if they are the same Basic block then ok */
-       if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
-       else return 0;
+        /* then if they are the same Basic block then ok */
+        if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
+        else return 0;
     }
-       
+
     /* for others it is cheaper to do the cse */
     return 1;
 }
@@ -340,7 +428,7 @@ oclsExpense (struct memmap *oclass)
 {
   if (IN_FARSPACE(oclass))
     return 1;
-    
+
   return 0;
 }
 
@@ -348,7 +436,7 @@ static int
 instructionSize(char *inst, char *op1, char *op2)
 {
   int isflat24 = (options.model == MODEL_FLAT24);
-  
+
   #define ISINST(s) (strncmp(inst, (s), sizeof(s)-1) == 0)
   #define IS_A(s) (*(s) == 'a' && *(s+1) == '\0')
   #define IS_C(s) (*(s) == 'c' && *(s+1) == '\0')
@@ -357,7 +445,7 @@ instructionSize(char *inst, char *op1, char *op2)
 
   /* Based on the current (2003-08-22) code generation for the
      small library, the top instruction probability is:
-   
+
        57% mov/movx/movc
         6% push
         6% pop
@@ -374,20 +462,20 @@ instructionSize(char *inst, char *op1, char *op2)
       if (*(inst+3)=='c') return 1; /* movc */
       if (IS_C (op1) || IS_C (op2)) return 2;
       if (IS_A (op1))
-       {
-         if (IS_Rn (op2) || IS_atRi (op2)) return 1;
-         return 2;
-       }
+        {
+          if (IS_Rn (op2) || IS_atRi (op2)) return 1;
+          return 2;
+        }
       if (IS_Rn(op1) || IS_atRi(op1))
-       {
-         if (IS_A(op2)) return 1;
-         return 2;
-       }
+        {
+          if (IS_A(op2)) return 1;
+          return 2;
+        }
       if (strcmp (op1, "dptr") == 0) return 3+isflat24;
       if (IS_A (op2) || IS_Rn (op2) || IS_atRi (op2)) return 2;
       return 3;
     }
-  
+
   if (ISINST ("push")) return 2;
   if (ISINST ("pop")) return 2;
 
@@ -405,7 +493,7 @@ instructionSize(char *inst, char *op1, char *op2)
   if (ISINST ("jb")) return 3;
   if (ISINST ("jnb")) return 3;
   if (ISINST ("jbc")) return 3;
-  if (ISINST ("jmp")) return 1;        // always jmp @a+dptr
+  if (ISINST ("jmp")) return 1; // always jmp @a+dptr
   if (ISINST ("jz")) return 2;
   if (ISINST ("jnz")) return 2;
   if (ISINST ("cjne")) return 3;
@@ -418,7 +506,7 @@ instructionSize(char *inst, char *op1, char *op2)
   if (ISINST ("acall")) return 2+isflat24;
   if (ISINST ("ajmp")) return 2+isflat24;
 
-    
+
   if (ISINST ("add") || ISINST ("addc") || ISINST ("subb") || ISINST ("xch"))
     {
       if (IS_Rn(op2) || IS_atRi(op2)) return 1;
@@ -434,15 +522,15 @@ instructionSize(char *inst, char *op1, char *op2)
     {
       if (IS_C(op1)) return 2;
       if (IS_A(op1))
-       {
-         if (IS_Rn(op2) || IS_atRi(op2)) return 1;
-         return 2;
-       }
+        {
+          if (IS_Rn(op2) || IS_atRi(op2)) return 1;
+          return 2;
+        }
       else
-       {
-         if (IS_A(op2)) return 2;
-         return 3;
-       }
+        {
+          if (IS_A(op2)) return 2;
+          return 3;
+        }
     }
   if (ISINST ("clr") || ISINST ("setb") || ISINST ("cpl"))
     {
@@ -471,7 +559,7 @@ ds390newAsmLineNode (int currentDPS)
   aln->regsWritten = NULL;
   aln->initialized = 0;
   aln->currentDPS = currentDPS;
-  
+
   return aln;
 }
 
@@ -535,7 +623,7 @@ ds390operandCompare (const void *key, const void *member)
   return strcmp((const char *)key, ((ds390operanddata *)member)->name);
 }
 
-static void      
+static void
 updateOpRW (asmLineNode *aln, char *op, char *optype, int currentDPS)
 {
   ds390operanddata *opdat;
@@ -543,15 +631,15 @@ updateOpRW (asmLineNode *aln, char *op, char *optype, int currentDPS)
   int regIdx1 = -1;
   int regIdx2 = -1;
   int regIdx3 = -1;
-  
+
   dot = strchr(op, '.');
   if (dot)
     *dot = '\0';
 
   opdat = bsearch (op, ds390operandDataTable,
-                  sizeof(ds390operandDataTable)/sizeof(ds390operanddata),
-                  sizeof(ds390operanddata), ds390operandCompare);
-  
+                   sizeof(ds390operandDataTable)/sizeof(ds390operanddata),
+                   sizeof(ds390operanddata), ds390operandCompare);
+
   if (opdat)
     {
       regIdx1 = opdat->regIdx1;
@@ -560,19 +648,19 @@ updateOpRW (asmLineNode *aln, char *op, char *optype, int currentDPS)
   if (!strcmp(op, "dptr"))
     {
       if (!currentDPS)
-       {
-         regIdx1 = DPL_IDX;
-         regIdx2 = DPH_IDX;
-         regIdx3 = DPX_IDX;
-       }
+        {
+          regIdx1 = DPL_IDX;
+          regIdx2 = DPH_IDX;
+          regIdx3 = DPX_IDX;
+        }
       else
-       {
-         regIdx1 = DPL1_IDX;
-         regIdx2 = DPH1_IDX;
-         regIdx3 = DPX1_IDX;
-       }
+        {
+          regIdx1 = DPL1_IDX;
+          regIdx2 = DPH1_IDX;
+          regIdx3 = DPX1_IDX;
+        }
     }
-    
+
   if (strchr(optype,'r'))
     {
       if (regIdx1 >= 0)
@@ -598,22 +686,22 @@ updateOpRW (asmLineNode *aln, char *op, char *optype, int currentDPS)
       if (!strcmp(op, "@r1"))
         aln->regsRead = bitVectSetBit (aln->regsRead, R1_IDX);
       if (strstr(op, "dptr"))
-       {
-         if (!currentDPS)
-           {
-             aln->regsRead = bitVectSetBit (aln->regsRead, DPL_IDX);
-             aln->regsRead = bitVectSetBit (aln->regsRead, DPH_IDX);
-             aln->regsRead = bitVectSetBit (aln->regsRead, DPX_IDX);
-           }
-         else
-           {
-             aln->regsRead = bitVectSetBit (aln->regsRead, DPL1_IDX);
-             aln->regsRead = bitVectSetBit (aln->regsRead, DPH1_IDX);
-             aln->regsRead = bitVectSetBit (aln->regsRead, DPX1_IDX);
-           }
-       }
+        {
+          if (!currentDPS)
+            {
+              aln->regsRead = bitVectSetBit (aln->regsRead, DPL_IDX);
+              aln->regsRead = bitVectSetBit (aln->regsRead, DPH_IDX);
+              aln->regsRead = bitVectSetBit (aln->regsRead, DPX_IDX);
+            }
+          else
+            {
+              aln->regsRead = bitVectSetBit (aln->regsRead, DPL1_IDX);
+              aln->regsRead = bitVectSetBit (aln->regsRead, DPH1_IDX);
+              aln->regsRead = bitVectSetBit (aln->regsRead, DPX1_IDX);
+            }
+        }
       if (strstr(op, "a+"))
-       aln->regsRead = bitVectSetBit (aln->regsRead, A_IDX);
+        aln->regsRead = bitVectSetBit (aln->regsRead, A_IDX);
     }
 }
 
@@ -630,9 +718,9 @@ ds390opcodedata;
 static ds390opcodedata ds390opcodeDataTable[] =
   {
     {"acall","j", "",   "",   ""},
-    {"ajmp", "j", "",   "",   ""},
     {"add",  "",  "w",  "rw", "r"},
     {"addc", "",  "rw", "rw", "r"},
+    {"ajmp", "j", "",   "",   ""},
     {"anl",  "",  "",   "rw", "r"},
     {"cjne", "j", "w",  "r",  "r"},
     {"clr",  "",  "",   "w",  ""},
@@ -674,7 +762,7 @@ static ds390opcodedata ds390opcodeDataTable[] =
     {"xchd", "",  "",   "rw", "rw"},
     {"xrl",  "",  "",   "rw", "r"},
   };
-  
+
 static int
 ds390opcodeCompare (const void *key, const void *member)
 {
@@ -692,9 +780,9 @@ asmLineNodeFromLineNode (lineNode *ln, int currentDPS)
   ds390opcodedata *opdat;
 
   aln->initialized = 1;
-  
+
   p = ln->line;
-  
+
   while (*p && isspace(*p)) p++;
   for (op = inst, opsize=1; *p; p++)
     {
@@ -702,13 +790,13 @@ asmLineNodeFromLineNode (lineNode *ln, int currentDPS)
         break;
       else
         if (opsize < sizeof(inst))
-         *op++ = tolower(*p), opsize++;
+          *op++ = tolower(*p), opsize++;
     }
   *op = '\0';
 
   if (*p == ';' || *p == ':' || *p == '=')
     return aln;
-    
+
   while (*p && isspace(*p)) p++;
   if (*p == '=')
     return aln;
@@ -719,7 +807,7 @@ asmLineNodeFromLineNode (lineNode *ln, int currentDPS)
         *op++ = tolower(*p), opsize++;
     }
   *op = '\0';
-  
+
   if (*p == ',') p++;
   for (op = op2, opsize=1; *p && *p != ','; p++)
     {
@@ -734,8 +822,8 @@ asmLineNodeFromLineNode (lineNode *ln, int currentDPS)
   aln->regsWritten = newBitVect (END_IDX);
 
   opdat = bsearch (inst, ds390opcodeDataTable,
-                  sizeof(ds390opcodeDataTable)/sizeof(ds390opcodedata),
-                  sizeof(ds390opcodedata), ds390opcodeCompare);
+                   sizeof(ds390opcodeDataTable)/sizeof(ds390opcodedata),
+                   sizeof(ds390opcodedata), ds390opcodeCompare);
 
   if (opdat)
     {
@@ -796,7 +884,8 @@ static const char *_linkCmd[] =
   "aslink", "-nf", "\"$1\"", NULL
 };
 
-/* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */   static const char *_asmCmd[] =
+/* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
+static const char *_asmCmd[] =
 {
   "asx8051", "$l", "$3", "\"$1.asm\"", NULL
 };
@@ -806,22 +895,22 @@ PORT ds390_port =
 {
   TARGET_ID_DS390,
   "ds390",
-  "DS80C390",                  /* Target name */
+  "DS80C390",                   /* Target name */
   NULL,
   {
     glue,
-    TRUE,                      /* Emit glue around main */
+    TRUE,                       /* Emit glue around main */
     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
     MODEL_SMALL
   },
   {
     _asmCmd,
     NULL,
-    "-plosgffc",               /* Options with debug */
-    "-plosgff",                        /* Options without debug */
+    "-plosgffc",                /* Options with debug */
+    "-plosgff",                 /* Options without debug */
     0,
     ".asm",
-    NULL                       /* no do_assemble function */
+    NULL                        /* no do_assemble function */
   },
   {
     _linkCmd,
@@ -837,15 +926,20 @@ PORT ds390_port =
     getRegsWritten
   },
   {
-       /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
+        /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
     1, 2, 2, 4, 1, 2, 3, 1, 4, 4
   },
+  
+  /* tags for generic pointers */
+  { 0x00, 0x40, 0x60, 0x80 },           /* far, near, xstack, code */
+
   {
     "XSEG    (XDATA)",
     "STACK   (DATA)",
     "CSEG    (CODE)",
     "DSEG    (DATA)",
     "ISEG    (DATA)",
+    "PSEG    (PAG,XDATA)",
     "XSEG    (XDATA)",
     "BSEG    (BIT)",
     "RSEG    (DATA)",
@@ -853,8 +947,12 @@ PORT ds390_port =
     "OSEG    (OVR,DATA)",
     "GSFINAL (CODE)",
     "HOME    (CODE)",
-    "XISEG   (XDATA)", // initialized xdata
-    "XINIT   (CODE)", // a code copy of xiseg
+    "XISEG   (XDATA)",          // initialized xdata
+    "XINIT   (CODE)",           // a code copy of xiseg
+    "CONST   (CODE)",           // const_name - const data (code or not)
+    "CABS    (ABS,CODE)",       // cabs_name - const absolute data (code or not)
+    "XABS    (ABS,XDATA)",      // xabs_name - absolute xdata/pdata
+    "IABS    (ABS,DATA)",       // iabs_name - absolute idata/data
     NULL,
     NULL,
     1
@@ -870,10 +968,18 @@ PORT ds390_port =
   {
     ds390_emitDebuggerSymbol
   },
+  {
+    255/4,      /* maxCount */
+    4,          /* sizeofElement */
+    {8,12,20},  /* sizeofMatchJump[] */
+    {10,14,22}, /* sizeofRangeCompare[] */
+    4,          /* sizeofSubtract */
+    7,          /* sizeofDispatch */
+  },
   "_",
   _ds390_init,
   _ds390_parseOptions,
-  NULL,
+  _ds390_options,
   NULL,
   _ds390_finaliseOptions,
   _ds390_setDefaultOptions,
@@ -881,42 +987,55 @@ PORT ds390_port =
   _ds390_getRegName,
   _ds390_keywords,
   _ds390_genAssemblerPreamble,
-  NULL,                                /* no genAssemblerEnd */
+  NULL,                         /* no genAssemblerEnd */
   _ds390_genIVT,
   _ds390_genXINIT,
-  NULL,                        /* genInitStartup */
+  _ds390_genInitStartup,
   _ds390_reset_regparm,
   _ds390_regparm,
   NULL,
   NULL,
   _ds390_nativeMulCheck,
-  hasExtBitOp,                 /* hasExtBitOp */
-  oclsExpense,                 /* oclsExpense */
+  hasExtBitOp,                  /* hasExtBitOp */
+  oclsExpense,                  /* oclsExpense */
   FALSE,
-  TRUE,                                /* little endian */
-  0,                           /* leave lt */
-  0,                           /* leave gt */
-  1,                           /* transform <= to ! > */
-  1,                           /* transform >= to ! < */
-  1,                           /* transform != to !(a == b) */
-  0,                           /* leave == */
-#if 0 // obsolete, and buggy for != xdata
-  TRUE,                         /* we support array initializers. */
-#else
+  TRUE,                         /* little endian */
+  0,                            /* leave lt */
+  0,                            /* leave gt */
+  1,                            /* transform <= to ! > */
+  1,                            /* transform >= to ! < */
+  1,                            /* transform != to !(a == b) */
+  0,                            /* leave == */
   FALSE,                        /* No array initializer support. */
-#endif
   cseCostEstimation,
   __ds390_builtins,             /* table of builtin functions */
-  GPOINTER,                    /* treat unqualified pointers as "generic" pointers */
-  1,                           /* reset labelKey to 1 */
-  1,                           /* globals & local static allowed */
+  GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
+  1,                            /* reset labelKey to 1 */
+  1,                            /* globals & local static allowed */
   PORT_MAGIC
 };
 
 /*---------------------------------------------------------------------------------*/
-/*                              TININative specific                               */
+/*                               TININative specific                               */
 /*---------------------------------------------------------------------------------*/
-/* Globals */
+
+#define OPTION_TINI_LIBID "--tini-libid"
+
+static OPTION _tininative_options[] =
+  {
+    { 0, OPTION_FLAT24_MODEL,   NULL, "use the flat24 model for the ds390 (default)" },
+    { 0, OPTION_STACK_8BIT,     NULL, "use the 8bit stack for the ds390 (not supported yet)" },
+    { 0, OPTION_STACK_SIZE,     &options.stack_size, "Tells the linker to allocate this space for stack", CLAT_INTEGER },
+    { 0, "--pack-iram",         NULL, "Tells the linker to pack variables in internal ram (default)"},
+    { 0, "--no-pack-iram",      &options.no_pack_iram, "Tells the linker not to pack variables in internal ram"},
+    { 0, "--stack-10bit",       &options.stack10bit, "use the 10bit stack for ds390 (default)" },
+    { 0, "--use-accelerator",   &options.useAccelerator, "generate code for ds390 arithmetic accelerator"},
+    { 0, "--protect-sp-update", &options.protect_sp_update, "will disable interrupts during ESP:SP updates"},
+    { 0, "--parms-in-bank1",    &options.parms_in_bank1, "use Bank1 for parameter passing"},
+    { 0, OPTION_TINI_LIBID,     &options.tini_libid, "<nnnn> LibraryID used in -mTININative", CLAT_INTEGER },
+    { 0, NULL }
+  };
+
 static void _tininative_init (void)
 {
     asm_addTree (&asm_a390_mapping);
@@ -935,36 +1054,36 @@ static void _tininative_finaliseOptions (void)
      * adjust pointer sizes.
      */
     if (options.model != MODEL_FLAT24)  {
-       options.model = MODEL_FLAT24 ;
-       fprintf(stderr,"TININative supports only MODEL FLAT24\n");
+        options.model = MODEL_FLAT24 ;
+        fprintf(stderr,"TININative supports only MODEL FLAT24\n");
     }
     port->s.fptr_size = 3;
     port->s.gptr_size = 4;
-    
-    port->stack.isr_overhead += 2;     /* Will save dpx on ISR entry. */
-    
-    port->stack.call_overhead += 2;    /* This acounts for the extra byte 
-                                        * of return addres on the stack.
-                                        * but is ugly. There must be a 
-                                        * better way.
-                                        */
-    
+
+    port->stack.isr_overhead += 2;      /* Will save dpx on ISR entry. */
+
+    port->stack.call_overhead += 2;     /* This acounts for the extra byte
+                                         * of return addres on the stack.
+                                         * but is ugly. There must be a
+                                         * better way.
+                                         */
+
     port->mem.default_local_map = xdata;
     port->mem.default_globl_map = xdata;
-    
+
     if (!options.stack10bit) {
-       options.stack10bit = 1;
-       fprintf(stderr,"TININative supports only stack10bit \n");
+        options.stack10bit = 1;
+        fprintf(stderr,"TININative supports only stack10bit \n");
     }
-    
+
     if (!options.stack_loc) options.stack_loc = 0x400008;
-    
+
     /* generate native code 16*16 mul/div */
-    if (options.useAccelerator) 
-       port->support.muldiv=2;
-    else 
-       port->support.muldiv=1;
-    
+    if (options.useAccelerator)
+        port->support.muldiv=2;
+    else
+        port->support.muldiv=1;
+
     /* Fixup the memory map for the stack; it is now in
      * far space and requires a FPOINTER to access it.
      */
@@ -973,10 +1092,11 @@ static void _tininative_finaliseOptions (void)
     options.cc_only =1;
 }
 
-static int _tininative_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts) 
+static int _tininative_genIVT (struct dbuf_s * oBuf, symbol ** interrupts, int maxInterrupts)
 {
-    return 1;
+    return TRUE;
 }
+
 static void _tininative_genAssemblerPreamble (FILE * of)
 {
     fputs("$include(tini.inc)\n", of);
@@ -992,13 +1112,13 @@ static void _tininative_genAssemblerPreamble (FILE * of)
     fputs("LibraryID:\n",of);
     fputs("\tdb \"DS\"\n",of);
     if (options.tini_libid) {
-       fprintf(of,"\tdb 0,0,0%02xh,0%02xh,0%02xh,0%02xh\n",
-               (options.tini_libid>>24 & 0xff),
-               (options.tini_libid>>16 & 0xff),
-               (options.tini_libid>>8 & 0xff),
-               (options.tini_libid  & 0xff));
+        fprintf(of,"\tdb 0,0,0%02xh,0%02xh,0%02xh,0%02xh\n",
+                (options.tini_libid>>24 & 0xff),
+                (options.tini_libid>>16 & 0xff),
+                (options.tini_libid>>8 & 0xff),
+                (options.tini_libid  & 0xff));
     } else {
-       fprintf(of,"\tdb 0,0,0,0,0,1\n");
+        fprintf(of,"\tdb 0,0,0,0,0,1\n");
     }
 
 }
@@ -1010,21 +1130,21 @@ static void _tininative_genAssemblerEnd (FILE * of)
 static void _tininative_do_assemble (set *asmOptions)
 {
     static const char *macroCmd[] = {
-       "macro","$1.a51",NULL
+        "macro","$1.a51",NULL
     };
     static const char *a390Cmd[] = {
-       "a390","$1.mpp",NULL
+        "a390","$1.mpp",NULL
     };
     char buffer[100];
 
     buildCmdLine(buffer,macroCmd,dstFileName,NULL,NULL,NULL);
     if (my_system(buffer)) {
-       exit(1);
+        exit(1);
     }
     buildCmdLine(buffer,a390Cmd,dstFileName,NULL,NULL,asmOptions);
     if (my_system(buffer)) {
-       exit(1);
-    }    
+        exit(1);
+    }
 }
 
 /* list of key words used by TININative */
@@ -1060,7 +1180,7 @@ static char *_tininative_keywords[] =
 static builtins __tininative_builtins[] = {
     { "__builtin_memcpy_x2x","v",3,{"cx*","cx*","i"}}, /* void __builtin_memcpy_x2x (xdata char *,xdata char *,int) */
     { "__builtin_memcpy_c2x","v",3,{"cx*","cp*","i"}}, /* void __builtin_memcpy_c2x (xdata char *,code  char *,int) */
-    { "__builtin_memset_x","v",3,{"cx*","c","i"}},     /* void __builtin_memset     (xdata char *,char,int)        */
+    { "__builtin_memset_x","v",3,{"cx*","c","i"}},     /* void __builtin_memset     (xdata char *,char,int)         */
     /* TINI NatLib */
     { "NatLib_LoadByte","c",1,{"c"}},                  /* char  Natlib_LoadByte  (0 based parameter number)         */
     { "NatLib_LoadShort","s",1,{"c"}},                 /* short Natlib_LoadShort (0 based parameter number)         */
@@ -1077,13 +1197,13 @@ static builtins __tininative_builtins[] = {
     { "MM_XMalloc","i",1,{"l"}},                       /* int  MM_XMalloc (long)                */
     { "MM_Malloc","i",1,{"i"}},                        /* int  MM_Malloc  (int)                 */
     { "MM_ApplicationMalloc","i",1,{"i"}},             /* int  MM_ApplicationMalloc  (int)      */
-    { "MM_Free","i",1,{"i"}},                          /* int  MM_Free  (int)                  */
-    { "MM_Deref","cx*",1,{"i"}},                       /* char *MM_Free  (int)                 */
+    { "MM_Free","i",1,{"i"}},                          /* int  MM_Free  (int)                   */
+    { "MM_Deref","cx*",1,{"i"}},                       /* char *MM_Free  (int)                  */
     { "MM_UnrestrictedPersist","c",1,{"i"}},           /* char  MM_UnrestrictedPersist  (int)   */
     /* System functions */
     { "System_ExecJavaProcess","c",2,{"cx*","i"}},     /* char System_ExecJavaProcess (char *,int) */
-    { "System_GetRTCRegisters","v",1,{"cx*"}},        /* void System_GetRTCRegisters (char *) */
-    { "System_SetRTCRegisters","v",1,{"cx*"}},        /* void System_SetRTCRegisters (char *) */
+    { "System_GetRTCRegisters","v",1,{"cx*"}},         /* void System_GetRTCRegisters (char *) */
+    { "System_SetRTCRegisters","v",1,{"cx*"}},         /* void System_SetRTCRegisters (char *) */
     { "System_ThreadSleep","v",2,{"l","c"}},           /* void System_ThreadSleep (long,char)  */
     { "System_ThreadSleep_ExitCriticalSection","v",2,{"l","c"}},/* void System_ThreadSleep_ExitCriticalSection (long,char)  */
     { "System_ProcessSleep","v",2,{"l","c"}},           /* void System_ProcessSleep (long,char)  */
@@ -1098,30 +1218,31 @@ static builtins __tininative_builtins[] = {
     { "System_RemovePoll","c",1,{"vF*"}},              /* char System_RemovePoll ((void *func pointer)()) */
     { "System_GetCurrentProcessId","c",0,{NULL}},      /* char System_GetCurrentProcessId() */
     { "System_GetCurrentThreadId","c",0,{NULL}},       /* char System_GetCurrentThreadId() */
-    { NULL , NULL,0, {NULL}}                      /* mark end of table */
-};    
+    { NULL , NULL,0, {NULL}}                       /* mark end of table */
+};
 
 static const char *_a390Cmd[] =
 {
   "macro", "$l", "$3", "$1.a51", NULL
 };
+
 PORT tininative_port =
 {
   TARGET_ID_DS390,
   "TININative",
-  "DS80C390",                  /* Target name */
-       NULL,                   /* processor */
+  "DS80C390",                   /* Target name */
+        NULL,                   /* processor */
   {
     glue,
-    FALSE,                     /* Emit glue around main */
+    FALSE,                      /* Emit glue around main */
     MODEL_FLAT24,
     MODEL_FLAT24
   },
   {
     _a390Cmd,
     NULL,
-    "-l",              /* Options with debug */
-    "-l",              /* Options without debug */
+    "-l",               /* Options with debug */
+    "-l",               /* Options without debug */
     0,
     ".a51",
     _tininative_do_assemble
@@ -1140,24 +1261,32 @@ PORT tininative_port =
     getRegsWritten
   },
   {
-       /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
+        /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
     1, 2, 2, 4, 1, 3, 3, 1, 4, 4
   },
+  /* tags for generic pointers */
+  { 0x00, 0x40, 0x60, 0x80 },           /* far, near, xstack, code */
+
   {
     "XSEG    (XDATA)",
     "STACK   (DATA)",
     "CSEG    (CODE)",
     "DSEG    (DATA)",
     "ISEG    (DATA)",
+    "PSEG    (PAG,XDATA)",
     "XSEG    (XDATA)",
     "BSEG    (BIT)",
     "RSEG    (DATA)",
     "GSINIT  (CODE)",
     "OSEG    (OVR,DATA)",
     "GSFINAL (CODE)",
-    "HOME       (CODE)",
+    "HOME    (CODE)",
     NULL,
     NULL,
+    "CONST   (CODE)",           // const_name - const data (code or not)
+    "CABS    (ABS,CODE)",       // cabs_name - const absolute data (code or not)
+    "XABS    (ABS,XDATA)",      // xabs_name - absolute xdata/pdata
+    "IABS    (ABS,DATA)",       // iabs_name - absolute idata/data
     NULL,
     NULL,
     1
@@ -1173,10 +1302,18 @@ PORT tininative_port =
   {
     ds390_emitDebuggerSymbol
   },
+  {
+    255/4,      /* maxCount */
+    4,          /* sizeofElement */
+    {8,12,20},  /* sizeofMatchJump[] */
+    {10,14,22}, /* sizeofRangeCompare[] */
+    4,          /* sizeofSubtract */
+    7,          /* sizeofDispatch */
+  },
   "",
   _tininative_init,
   _ds390_parseOptions,
-  NULL,
+  _tininative_options,
   NULL,
   _tininative_finaliseOptions,
   _tininative_setDefaultOptions,
@@ -1187,48 +1324,66 @@ PORT tininative_port =
   _tininative_genAssemblerEnd,
   _tininative_genIVT,
   NULL,
-  NULL,                        /* genInitStartup */
+  _ds390_genInitStartup,
   _ds390_reset_regparm,
   _ds390_regparm,
   NULL,
   NULL,
   NULL,
-  hasExtBitOp,                 /* hasExtBitOp */
-  oclsExpense,                 /* oclsExpense */
+  hasExtBitOp,                  /* hasExtBitOp */
+  oclsExpense,                  /* oclsExpense */
   FALSE,
-  TRUE,                                /* little endian */
-  0,                           /* leave lt */
-  0,                           /* leave gt */
-  1,                           /* transform <= to ! > */
-  1,                           /* transform >= to ! < */
-  1,                           /* transform != to !(a == b) */
-  0,                           /* leave == */
-  TRUE,                         /* we support array initializers. */
+  TRUE,                         /* little endian */
+  0,                            /* leave lt */
+  0,                            /* leave gt */
+  1,                            /* transform <= to ! > */
+  1,                            /* transform >= to ! < */
+  1,                            /* transform != to !(a == b) */
+  0,                            /* leave == */
+  FALSE,                        /* No array initializer support. */
   cseCostEstimation,
   __tininative_builtins,        /* table of builtin functions */
-  FPOINTER,                    /* treat unqualified pointers as far pointers */
-  0,                           /* DONOT reset labelKey */
-  0,                           /* globals & local static NOT allowed */
+  FPOINTER,                     /* treat unqualified pointers as far pointers */
+  0,                            /* DONOT reset labelKey */
+  0,                            /* globals & local static NOT allowed */
   PORT_MAGIC
 };
 
 static int
-_ds400_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
+_ds400_genIVT (struct dbuf_s * oBuf, symbol ** interrupts, int maxInterrupts)
 {
-    /* We can't generate a static IVT, since the boot rom creates one
-     * for us in rom_init.
-     * 
-     * we must patch it as part of the C startup.
-     */
-     fprintf (of, ";\tDS80C400 IVT must be generated at runtime.\n");
-    fprintf (of, "\tsjmp\t__sdcc_400boot\n");
-    fprintf (of, "\t.ascii\t'TINI'\t; required signature for 400 boot loader.\n");
-    fprintf (of, "\t.db\t0\t; selected bank: zero *should* work...\n");
-    fprintf (of, "\t__sdcc_400boot:\tljmp\t__sdcc_gsinit_startup\n");
-     return TRUE;
+  /* We can't generate a static IVT, since the boot rom creates one
+   * for us in rom_init.
+   *
+   * we must patch it as part of the C startup.
+   */
+  dbuf_printf (oBuf, ";\tDS80C400 IVT must be generated at runtime.\n");
+  dbuf_printf (oBuf, "\tsjmp\t__sdcc_400boot\n");
+  dbuf_printf (oBuf, "\t.ascii\t'TINI'\t; required signature for 400 boot loader.\n");
+  dbuf_printf (oBuf, "\t.db\t0\t; selected bank: zero *should* work...\n");
+  dbuf_printf (oBuf, "\t__sdcc_400boot:\tljmp\t__sdcc_gsinit_startup\n");
+
+  return TRUE;
 }
 
-    
+
+/*---------------------------------------------------------------------------------*/
+/*                               _ds400 specific                                   */
+/*---------------------------------------------------------------------------------*/
+
+static OPTION _ds400_options[] =
+  {
+    { 0, OPTION_FLAT24_MODEL,   NULL, "use the flat24 model for the ds400 (default)" },
+    { 0, OPTION_STACK_8BIT,     NULL, "use the 8bit stack for the ds400 (not supported yet)" },
+    { 0, OPTION_STACK_SIZE,     &options.stack_size, "Tells the linker to allocate this space for stack", CLAT_INTEGER },
+    { 0, "--pack-iram",         NULL, "Tells the linker to pack variables in internal ram (default)"},
+    { 0, "--no-pack-iram",      &options.no_pack_iram, "Tells the linker not to pack variables in internal ram"},
+    { 0, "--stack-10bit",       &options.stack10bit, "use the 10bit stack for ds400 (default)" },
+    { 0, "--use-accelerator",   &options.useAccelerator, "generate code for ds400 arithmetic accelerator"},
+    { 0, "--protect-sp-update", &options.protect_sp_update, "will disable interrupts during ESP:SP updates"},
+    { 0, "--parms-in-bank1",    &options.parms_in_bank1, "use Bank1 for parameter passing"},
+    { 0, NULL }
+  };
 
 static void
 _ds400_finaliseOptions (void)
@@ -1240,13 +1395,13 @@ _ds400_finaliseOptions (void)
   // hackhack: we're a superset of the 390.
   addSet(&preArgvSet, Safe_strdup("-DSDCC_ds390"));
   addSet(&preArgvSet, Safe_strdup("-D__ds390"));
-    
+
   /* Hack-o-matic: if we are using the flat24 model,
    * adjust pointer sizes.
    */
   if (options.model != MODEL_FLAT24)  {
       fprintf (stderr,
-              "*** warning: ds400 port small and large model experimental.\n");
+               "*** warning: ds400 port small and large model experimental.\n");
       if (options.model == MODEL_LARGE)
       {
         port->mem.default_local_map = xdata;
@@ -1262,13 +1417,13 @@ _ds400_finaliseOptions (void)
     port->s.fptr_size = 3;
     port->s.gptr_size = 4;
 
-    port->stack.isr_overhead += 2;     /* Will save dpx on ISR entry. */
+    port->stack.isr_overhead += 2;      /* Will save dpx on ISR entry. */
 
-    port->stack.call_overhead += 2;    /* This acounts for the extra byte 
-                                * of return addres on the stack.
-                                * but is ugly. There must be a 
-                                * better way.
-                                */
+    port->stack.call_overhead += 2;     /* This acounts for the extra byte
+                                 * of return addres on the stack.
+                                 * but is ugly. There must be a
+                                 * better way.
+                                 */
 
     port->mem.default_local_map = xdata;
     port->mem.default_globl_map = xdata;
@@ -1276,17 +1431,17 @@ _ds400_finaliseOptions (void)
     if (!options.stack10bit)
     {
     fprintf (stderr,
-            "*** error: ds400 port only supports the 10 bit stack mode.\n");
+             "*** error: ds400 port only supports the 10 bit stack mode.\n");
     } else {
-       if (!options.stack_loc) options.stack_loc = 0xffdc00;
-       // assumes IDM1:0 = 1:0, CMA = 1.
+        if (!options.stack_loc) options.stack_loc = 0xffdc00;
+        // assumes IDM1:0 = 1:0, CMA = 1.
     }
-    
+
     /* generate native code 16*16 mul/div */
-    if (options.useAccelerator) 
-           port->support.muldiv=2;
-    else 
-           port->support.muldiv=1;
+    if (options.useAccelerator)
+            port->support.muldiv=2;
+    else
+            port->support.muldiv=1;
 
      /* Fixup the memory map for the stack; it is now in
      * far space and requires a FPOINTER to access it.
@@ -1295,12 +1450,12 @@ _ds400_finaliseOptions (void)
     istack->ptrType = FPOINTER;
 
     if (options.parms_in_bank1) {
-       addSet(&preArgvSet, Safe_strdup("-DSDCC_PARMS_IN_BANK1"));
+        addSet(&preArgvSet, Safe_strdup("-DSDCC_PARMS_IN_BANK1"));
     }
-     
+
     // the DS400 rom calling interface uses register bank 3.
     RegBankUsed[3] = 1;
-      
+
   }  /* MODEL_FLAT24 */
 }
 
@@ -1309,11 +1464,11 @@ static void _ds400_generateRomDataArea(FILE *fp, bool isMain)
     /* Only do this for the file containing main() */
     if (isMain)
     {
-       fprintf(fp, "%s", iComments2);
-       fprintf(fp, "; the direct data area used by the DS80c400 ROM code.\n");
-       fprintf(fp, "%s", iComments2);
-       fprintf(fp, ".area ROMSEG (ABS,CON,DATA)\n\n");
-       fprintf(fp, ".ds 24 ; 24 bytes of directs used starting at 0x68\n\n");
+        fprintf(fp, "%s", iComments2);
+        fprintf(fp, "; the direct data area used by the DS80c400 ROM code.\n");
+        fprintf(fp, "%s", iComments2);
+        fprintf(fp, ".area ROMSEG (ABS,CON,DATA)\n\n");
+        fprintf(fp, ".ds 24 ; 24 bytes of directs used starting at 0x68\n\n");
     }
 }
 
@@ -1327,22 +1482,22 @@ PORT ds400_port =
 {
   TARGET_ID_DS400,
   "ds400",
-  "DS80C400",                  /* Target name */
+  "DS80C400",                   /* Target name */
   NULL,
   {
     glue,
-    TRUE,                      /* Emit glue around main */
+    TRUE,                       /* Emit glue around main */
     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
     MODEL_SMALL
   },
   {
     _asmCmd,
     NULL,
-    "-plosgffc",               /* Options with debug */
-    "-plosgff",                        /* Options without debug */
+    "-plosgffc",                /* Options with debug */
+    "-plosgff",                 /* Options without debug */
     0,
     ".asm",
-    NULL                       /* no do_assemble function */
+    NULL                        /* no do_assemble function */
   },
   {
     _linkCmd,
@@ -1358,15 +1513,20 @@ PORT ds400_port =
     getRegsWritten
   },
   {
-       /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
+        /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
     1, 2, 2, 4, 1, 2, 3, 1, 4, 4
   },
+
+  /* tags for generic pointers */
+  { 0x00, 0x40, 0x60, 0x80 },           /* far, near, xstack, code */
+
   {
     "XSEG    (XDATA)",
     "STACK   (DATA)",
     "CSEG    (CODE)",
     "DSEG    (DATA)",
     "ISEG    (DATA)",
+    "PSEG    (PAG,XDATA)",
     "XSEG    (XDATA)",
     "BSEG    (BIT)",
     "RSEG    (DATA)",
@@ -1376,6 +1536,10 @@ PORT ds400_port =
     "HOME    (CODE)",
     "XISEG   (XDATA)", // initialized xdata
     "XINIT   (CODE)", // a code copy of xiseg
+    "CONST   (CODE)",           // const_name - const data (code or not)
+    "CABS    (ABS,CODE)",       // cabs_name - const absolute data (code or not)
+    "XABS    (ABS,XDATA)",      // xabs_name - absolute xdata/pdata
+    "IABS    (ABS,DATA)",       // iabs_name - absolute idata/data
     NULL,
     NULL,
     1
@@ -1391,10 +1555,18 @@ PORT ds400_port =
   {
     ds390_emitDebuggerSymbol
   },
+  {
+    255/4,      /* maxCount */
+    4,          /* sizeofElement */
+    {8,12,20},  /* sizeofMatchJump[] */
+    {10,14,22}, /* sizeofRangeCompare[] */
+    4,          /* sizeofSubtract */
+    7,          /* sizeofDispatch */
+  },
   "_",
   _ds390_init,
   _ds390_parseOptions,
-  NULL,
+  _ds400_options,
   NULL,
   _ds400_finaliseOptions,
   _ds390_setDefaultOptions,
@@ -1402,30 +1574,30 @@ PORT ds400_port =
   _ds390_getRegName,
   _ds390_keywords,
   _ds390_genAssemblerPreamble,
-  NULL,                                /* no genAssemblerEnd */
+  NULL,                         /* no genAssemblerEnd */
   _ds400_genIVT,
   _ds390_genXINIT,
-  NULL,                        /* genInitStartup */
+  _ds390_genInitStartup,
   _ds390_reset_regparm,
   _ds390_regparm,
   NULL,
   NULL,
   _ds390_nativeMulCheck,
-  hasExtBitOp,                 /* hasExtBitOp */
-  oclsExpense,                 /* oclsExpense */
+  hasExtBitOp,                  /* hasExtBitOp */
+  oclsExpense,                  /* oclsExpense */
   FALSE,
-  TRUE,                                /* little endian */
-  0,                           /* leave lt */
-  0,                           /* leave gt */
-  1,                           /* transform <= to ! > */
-  1,                           /* transform >= to ! < */
-  1,                           /* transform != to !(a == b) */
-  0,                           /* leave == */
-  TRUE,                         /* we support array initializers. */
+  TRUE,                         /* little endian */
+  0,                            /* leave lt */
+  0,                            /* leave gt */
+  1,                            /* transform <= to ! > */
+  1,                            /* transform >= to ! < */
+  1,                            /* transform != to !(a == b) */
+  0,                            /* leave == */
+  FALSE,                        /* No array initializer support. */
   cseCostEstimation,
   __ds390_builtins,             /* table of builtin functions */
-  GPOINTER,                    /* treat unqualified pointers as "generic" pointers */
-  1,                           /* reset labelKey to 1 */
-  1,                           /* globals & local static allowed */
+  GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
+  1,                            /* reset labelKey to 1 */
+  1,                            /* globals & local static allowed */
   PORT_MAGIC
 };