PIC16 - Applied patch from Vangelis Rokas. Many fixes for the PIC16 port.
[fw/sdcc] / src / pic / main.c
index 0dc512cadc76eb554f4ac978f822f23cfa659634..78cfda609d6d8e883a273c412219b05ee3d41b15 100644 (file)
@@ -7,7 +7,10 @@
 #include "common.h"
 #include "main.h"
 #include "ralloc.h"
-#include "gen.h"
+#include "device.h"
+#include "SDCCutil.h"
+//#include "gen.h"
+
 
 static char _defaultRules[] =
 {
@@ -15,165 +18,305 @@ static char _defaultRules[] =
 };
 
 /* list of key words used by msc51 */
-static char *_pic14_keywords[] =     {
-    "at",
-    "bit",
-    "code",
-    "critical",
-    "data",
-    "far",
-    "idata",
-    "interrupt",
-    "near",
-    "pdata",
-    "reentrant",
-    "sfr",
-    "sbit",
-    "using",
-    "xdata",
-    "_data",
-    "_code",
-    "_generic",
-    "_near",
-    "_xdata",
-    "_pdata",
-    "_idata",
-    NULL
+static char *_pic14_keywords[] =
+{
+  "at",
+  "bit",
+  "code",
+  "critical",
+  "data",
+  "far",
+  "idata",
+  "interrupt",
+  "near",
+  "pdata",
+  "reentrant",
+  "sfr",
+  "sbit",
+  "using",
+  "xdata",
+  "_data",
+  "_code",
+  "_generic",
+  "_near",
+  "_xdata",
+  "_pdata",
+  "_idata",
+  NULL
 };
 
+void  pCodeInitRegisters(void);
 
-void pic14_assignRegisters (eBBlock **ebbs, int count);
+void pic14_assignRegisters (eBBlock ** ebbs, int count);
 
-static int regParmFlg = 0; /* determine if we can register a parameter */
+static int regParmFlg = 0;     /* determine if we can register a parameter */
 
-static void _pic14_init(void)
+static void
+_pic14_init (void)
 {
-    asm_addTree(&asm_asxxxx_mapping);
+  asm_addTree (&asm_asxxxx_mapping);
+  pCodeInitRegisters();
 }
 
-static void _pic14_reset_regparm()
+static void
+_pic14_reset_regparm ()
 {
-    regParmFlg = 0;
+  regParmFlg = 0;
 }
 
-static int _pic14_regparm( sym_link *l)
+static int
+_pic14_regparm (sym_link * l)
 {
-    /* for this processor it is simple
-       can pass only the first parameter in a register */
-    if (regParmFlg)
-       return 0;
+  /* for this processor it is simple
+     can pass only the first parameter in a register */
+  //if (regParmFlg)
+  //  return 0;
 
-    regParmFlg = 1;
-    return 1;
+  regParmFlg++;// = 1;
+  return 1;
 }
 
-static bool _pic14_parseOptions(int *pargc, char **argv, int *i)
+static int
+_process_pragma(const char *sz)
 {
-    /* TODO: allow port-specific command line options to specify
-     * segment names here.
-     */
-    return FALSE;
+  static const char *WHITE = " \t";
+  char *ptr = strtok((char *)sz, WHITE);
+
+  if (startsWith (ptr, "memmap"))
+    {
+      char     *start;
+      char     *end;
+      char     *type;
+      char     *alias;
+
+      start = strtok((char *)NULL, WHITE);
+      end = strtok((char *)NULL, WHITE);
+      type = strtok((char *)NULL, WHITE);
+      alias = strtok((char *)NULL, WHITE);
+
+      if (start != (char *)NULL
+         && end != (char *)NULL
+         && type != (char *)NULL) {
+       value           *startVal = constVal(start);
+       value           *endVal = constVal(end);
+       value           *aliasVal;
+       memRange        r;
+
+       if (alias == (char *)NULL) {
+         aliasVal = constVal(0);
+       } else {
+         aliasVal = constVal(alias);
+       }
+
+       r.start_address = (int)floatFromVal(startVal);
+       r.end_address = (int)floatFromVal(endVal);
+       r.alias = (int)floatFromVal(aliasVal);
+       r.bank = (r.start_address >> 7) & 3;
+
+       if (strcmp(type, "RAM") == 0) {
+         addMemRange(&r, 0);
+       } else if (strcmp(type, "SFR") == 0) {
+         addMemRange(&r, 1);
+       } else {
+         return 1;
+       }
+      }
+
+      return 0;
+    } else if (startsWith (ptr, "maxram")) {
+      char *maxRAM = strtok((char *)NULL, WHITE);
+
+      if (maxRAM != (char *)NULL) {
+       int     maxRAMaddress;
+       value   *maxRAMVal;
+
+       maxRAMVal = constVal(maxRAM);
+       maxRAMaddress = (int)floatFromVal(maxRAMVal);
+       setMaxRAM(maxRAMaddress);
+      }
+       
+      return 0;
+    }
+  return 1;
 }
 
-static void _pic14_finaliseOptions(void)
+static bool
+_pic14_parseOptions (int *pargc, char **argv, int *i)
 {
-    /* Hack-o-matic: if we are using the flat24 model,
-     * adjust pointer sizes.
-     */
-    if (options.model == MODEL_FLAT24)
+  /* TODO: allow port-specific command line options to specify
+   * segment names here.
+   */
+  return FALSE;
+}
+
+static void
+_pic14_finaliseOptions (void)
+{
+
+      port->mem.default_local_map = data;
+      port->mem.default_globl_map = data;
+#if 0
+  /* Hack-o-matic: if we are using the flat24 model,
+   * adjust pointer sizes.
+   */
+  if (options.model == MODEL_FLAT24)
     {
-       
-       fprintf(stderr, "*** WARNING: you should use the '-mds390' option "
-                       "for DS80C390 support. This code generator is "
-                       "badly out of date and probably broken.\n");
-       
-        port->s.fptr_size = 3;
-        port->s.gptr_size = 4;
-        port->stack.isr_overhead++;   /* Will save dpx on ISR entry. */
-        #if 1
-        port->stack.call_overhead++;      /* This acounts for the extra byte 
-                                           * of return addres on the stack.
-                                           * but is ugly. There must be a 
-                                           * better way.
-                                           */
-       #endif
-        fReturn = fReturn390;
-        fReturnSize = 5;
-    } 
-
-    if (options.model == MODEL_LARGE) {
-       port->mem.default_local_map = xdata;
-       port->mem.default_globl_map = xdata;
-    } else {
-       port->mem.default_local_map = data;
-       port->mem.default_globl_map = data;
+
+      fprintf (stderr, "*** WARNING: you should use the '-mds390' option "
+              "for DS80C390 support. This code generator is "
+              "badly out of date and probably broken.\n");
+
+      port->s.fptr_size = 3;
+      port->s.gptr_size = 4;
+      port->stack.isr_overhead++;      /* Will save dpx on ISR entry. */
+#if 1
+      port->stack.call_overhead++;     /* This acounts for the extra byte 
+                                        * of return addres on the stack.
+                                        * but is ugly. There must be a 
+                                        * better way.
+                                        */
+#endif
+      fReturn = fReturn390;
+      fReturnSize = 5;
+    }
+
+  if (options.model == MODEL_LARGE)
+    {
+      port->mem.default_local_map = xdata;
+      port->mem.default_globl_map = xdata;
     }
-    
-    if (options.stack10bit)
+  else
+    {
+      port->mem.default_local_map = data;
+      port->mem.default_globl_map = data;
+    }
+
+  if (options.stack10bit)
     {
-       if (options.model != MODEL_FLAT24)
-       {
-            fprintf(stderr, 
-                   "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
-            fprintf(stderr, "\t10 bit stack mode disabled.\n");
-            options.stack10bit = 0;
-        }
-        else
-        {
-            /* Fixup the memory map for the stack; it is now in
-             * far space and requires a FPOINTER to access it.
-             */
-            istack->fmap = 1;
-            istack->ptrType = FPOINTER; 
-        }
+      if (options.model != MODEL_FLAT24)
+       {
+         fprintf (stderr,
+                  "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
+         fprintf (stderr, "\t10 bit stack mode disabled.\n");
+         options.stack10bit = 0;
+       }
+      else
+       {
+         /* Fixup the memory map for the stack; it is now in
+          * far space and requires a FPOINTER to access it.
+          */
+         istack->fmap = 1;
+         istack->ptrType = FPOINTER;
+       }
     }
+#endif
 }
 
-static void _pic14_setDefaultOptions(void)
+static void
+_pic14_setDefaultOptions (void)
 {
 }
 
-static const char *_pic14_getRegName(struct regs *reg)
+static const char *
+_pic14_getRegName (struct regs *reg)
 {
-    if (reg)
-       return reg->name;
-    return "err";
+  if (reg)
+    return reg->name;
+  return "err";
 }
 
-static void _pic14_genAssemblerPreamble(FILE *of)
+extern char *processor_base_name(void);
+
+static void
+_pic14_genAssemblerPreamble (FILE * of)
 {
-  fprintf(of,"\tlist\tp=16c84\n");
-  fprintf(of,"\t__config _wdt_off\n");
-  fprintf(of,"\ninclude \"p16c84.inc\"\n");
+  char * name = processor_base_name();
+
+  if(!name) {
+
+    name = "p16f877";
+    fprintf(stderr,"WARNING: No Pic has been selected, defaulting to %s\n",name);
+  }
+
+  fprintf (of, "\tlist\tp=%s\n",&name[1]);
+  fprintf (of, "\tradix dec");
+  fprintf (of, "\ninclude \"%s.inc\"\n",name);
 }
 
 /* Generate interrupt vector table. */
-static int _pic14_genIVT(FILE *of, symbol **interrupts, int maxInterrupts)
+static int
+_pic14_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
 {
-    int i;
-    
-    if (options.model != MODEL_FLAT24)
+  int i;
+
+  if (options.model != MODEL_FLAT24)
     {
-        /* Let the default code handle it. */
-       return FALSE;
+      /* Let the default code handle it. */
+      return FALSE;
     }
-    
-    fprintf (of, "\t;ajmp\t__sdcc_gsinit_startup\n");
-    
-    /* now for the other interrupts */
-    for (i = 0; i < maxInterrupts; i++) 
+
+  fprintf (of, "\t;ajmp\t__sdcc_gsinit_startup\n");
+
+  /* now for the other interrupts */
+  for (i = 0; i < maxInterrupts; i++)
     {
-       if (interrupts[i])
+      if (interrupts[i])
        {
-           fprintf(of, "\t;ljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
+         fprintf (of, "\t;ljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
        }
-       else
+      else
        {
-           fprintf(of, "\t;reti\n\t.ds\t7\n");
+         fprintf (of, "\t;reti\n\t.ds\t7\n");
        }
     }
-    
-    return TRUE;
+
+  return TRUE;
+}
+
+static bool
+_hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
+{
+/*
+  sym_link *test = NULL;
+  value *val;
+*/
+
+  fprintf(stderr,"checking for native mult\n");
+
+  if ( ic->op != '*')
+    {
+      return FALSE;
+    }
+
+  return TRUE;
+/*
+  if ( IS_LITERAL (left))
+    {
+      fprintf(stderr,"left is lit\n");
+      test = left;
+      val = OP_VALUE (IC_LEFT (ic));
+    }
+  else if ( IS_LITERAL (right))
+    {
+      fprintf(stderr,"right is lit\n");
+      test = left;
+      val = OP_VALUE (IC_RIGHT (ic));
+    }
+  else
+    {
+      fprintf(stderr,"oops, neither is lit so no\n");
+      return FALSE;
+    }
+
+  if ( getSize (test) <= 2)
+    {
+      fprintf(stderr,"yep\n");
+      return TRUE;
+    }
+  fprintf(stderr,"nope\n");
+
+  return FALSE;
+*/
 }
 
 /** $1 is always the basename.
@@ -182,92 +325,113 @@ static int _pic14_genIVT(FILE *of, symbol **interrupts, int maxInterrupts)
     $l is the list of extra options that should be there somewhere...
     MUST be terminated with a NULL.
 */
-static const char *_linkCmd[] = {
-    "aslink", "-nf", "$1", NULL
+static const char *_linkCmd[] =
+{
+  "gplink", "", "\"$1.o\"", NULL
 };
 
-static const char *_asmCmd[] = {
- "gpasm", NULL, NULL, NULL
+static const char *_asmCmd[] =
+{
+  "gpasm", "-c", "\"$1.asm\"", NULL
 
 };
 
 /* Globals */
-PORT pic14_port = {
-    "pic14",
-    "MCU pic",                 /* Target name */
-    {
-       TRUE,                   /* Emit glue around main */
-       MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
-       MODEL_SMALL
-    },
-    {  
-      _asmCmd,
-       NULL,
-       NULL,
-       //"-plosgffc",          /* Options with debug */
-       //"-plosgff",           /* Options without debug */
-       0
-    },
-    {
-       _linkCmd,
-       NULL,
-       ".rel"
-    },
-    {
-       _defaultRules
-    },
-    {
-       /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
-       1, 1, 2, 4, 1, 2, 1, 1, 4, 4
+PORT pic_port =
+{
+  TARGET_ID_PIC,
+  "pic14",
+  "MCU pic",                   /* Target name */
+  "",                    /* Processor */
+  {
+    TRUE,                      /* Emit glue around main */
+    MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
+    MODEL_SMALL
+  },
+  {
+    _asmCmd,
+    NULL,
+    NULL,
+    NULL,
+       //"-plosgffc",          /* Options with debug */
+       //"-plosgff",           /* Options without debug */
+    0,
+    ".asm",
+    NULL                       /* no do_assemble function */
+  },
+  {
+    _linkCmd,
+    NULL,
+    NULL,
+    ".o"
+  },
+  {
+    _defaultRules
+  },
+  {
+       /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
+    1, 2, 2, 4, 2, 2, 2, 1, 4, 4
        /* TSD - I changed the size of gptr from 3 to 1. However, it should be
           2 so that we can accomodate the PIC's with 4 register banks (like the
           16f877)
-       */
-    },
-    {
-       "XSEG    (XDATA)",
-       "STACK   (DATA)",
-       "CSEG    (CODE)",
-       "DSEG    (DATA)",
-       "ISEG    (DATA)",
-       "XSEG    (XDATA)",
-       "BSEG    (BIT)",
-       "RSEG    (DATA)",
-       "GSINIT  (CODE)",
-       "OSEG    (OVR,DATA)",
-       "GSFINAL (CODE)",
-       "HOME    (CODE)",
-       NULL,
-       NULL,
-       1
-    },
-    { 
-       +1, 1, 4, 1, 1, 0
-    },
-    /* pic14 has an 8 bit mul */
-    {
-       1, 0
-    },
-    "_",
-    _pic14_init,
-    _pic14_parseOptions,
-    _pic14_finaliseOptions,
-    _pic14_setDefaultOptions,
-    pic14_assignRegisters,
-    _pic14_getRegName ,
-    _pic14_keywords,
-    _pic14_genAssemblerPreamble,
-    _pic14_genIVT ,
-    _pic14_reset_regparm,
-    _pic14_regparm,
+        */
+  },
+  {
+    "XSEG    (XDATA)",
+    "STACK   (DATA)",
+    "code",
+    "DSEG    (DATA)",
+    "ISEG    (DATA)",
+    "XSEG    (XDATA)",
+    "BSEG    (BIT)",
+    "RSEG    (DATA)",
+    "GSINIT  (CODE)",
+    "udata_ovr",
+    "GSFINAL (CODE)",
+    "HOME       (CODE)",
+    NULL, // xidata
+    NULL, // xinit
+    NULL,
     NULL,
-    FALSE,
-    0,  /* leave lt */
-    0,  /* leave gt */
-    1,  /* transform <= to ! > */
-    1,  /* transform >= to ! < */
-    1,  /* transform != to !(a == b) */
-    0,  /* leave == */
-    PORT_MAGIC
+    1        // code is read only
+  },
+  {
+    +1, 1, 4, 1, 1, 0
+  },
+    /* pic14 has an 8 bit mul */
+  {
+    1, -1
+  },
+  "_",
+  _pic14_init,
+  _pic14_parseOptions,
+  NULL,
+  _pic14_finaliseOptions,
+  _pic14_setDefaultOptions,
+  pic14_assignRegisters,
+  _pic14_getRegName,
+  _pic14_keywords,
+  _pic14_genAssemblerPreamble,
+  NULL,                                /* no genAssemblerEnd */
+  _pic14_genIVT,
+  NULL, // _pic14_genXINIT
+  _pic14_reset_regparm,
+  _pic14_regparm,
+  _process_pragma,                             /* process a pragma */
+  NULL,
+  _hasNativeMulFor,
+  FALSE,
+  0,                           /* leave lt */
+  0,                           /* leave gt */
+  1,                           /* transform <= to ! > */
+  1,                           /* transform >= to ! < */
+  1,                           /* transform != to !(a == b) */
+  0,                           /* leave == */
+  FALSE,                        /* No array initializer support. */
+  0,                            /* no CSE cost estimation yet */
+  NULL,                        /* no builtin functions */
+  GPOINTER,                    /* treat unqualified pointers as "generic" pointers */
+  1,                           /* reset labelKey to 1 */
+  1,                           /* globals & local static allowed */
+  PORT_MAGIC
 };
-