Added the pic16 port for Martin Dubuc.
authorsdattalo <sdattalo@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 1 Dec 2002 03:24:42 +0000 (03:24 +0000)
committersdattalo <sdattalo@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 1 Dec 2002 03:24:42 +0000 (03:24 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2111 4a8a32a2-be11-0410-ad9d-d568d2c75423

22 files changed:
src/pic16/Makefile.bcc [new file with mode: 0644]
src/pic16/device.c [new file with mode: 0644]
src/pic16/device.h [new file with mode: 0644]
src/pic16/gen.c [new file with mode: 0644]
src/pic16/gen.h [new file with mode: 0644]
src/pic16/genarith.c [new file with mode: 0644]
src/pic16/glue.c [new file with mode: 0644]
src/pic16/glue.h [new file with mode: 0644]
src/pic16/main.c [new file with mode: 0644]
src/pic16/main.h [new file with mode: 0644]
src/pic16/pcode.c [new file with mode: 0644]
src/pic16/pcode.h [new file with mode: 0644]
src/pic16/pcodeflow.c [new file with mode: 0644]
src/pic16/pcodeflow.h [new file with mode: 0644]
src/pic16/pcodepeep.c [new file with mode: 0644]
src/pic16/pcoderegs.c [new file with mode: 0644]
src/pic16/pcoderegs.h [new file with mode: 0644]
src/pic16/peeph.def [new file with mode: 0644]
src/pic16/pic.dsp [new file with mode: 0644]
src/pic16/pica.dsp [new file with mode: 0644]
src/pic16/ralloc.c [new file with mode: 0644]
src/pic16/ralloc.h [new file with mode: 0644]

diff --git a/src/pic16/Makefile.bcc b/src/pic16/Makefile.bcc
new file mode 100644 (file)
index 0000000..445fa5f
--- /dev/null
@@ -0,0 +1,23 @@
+PRJDIR = ../..
+
+# !include $(PRJDIR)/Makefile.common
+
+OBJ = gen.obj genarith.obj ralloc.obj main.obj glue.obj pcode.obj pcodepeep.obj
+LIB = port.lib
+
+!include ..\..\Bcc.inc
+CFLAGS  = -I.. -I. -I..\.. -I..\..\support -D__FUNCTION__=__FILE__
+
+all: $(LIB)
+
+main.obj: main.c peeph.rul
+
+$(LIB): peeph.rul $(OBJ)
+       del $(LIB)
+        tlib /a $(LIB) +gen.obj +genarith.obj +ralloc.obj +main.obj +glue.obj
+        tlib /a $(LIB) +pcode.obj +pcodepeep.obj
+
+peeph.rul: peeph.def
+        gawk -f ../SDCCpeeph.awk peeph.def > peeph.rul
+
+# include clean.mk
diff --git a/src/pic16/device.c b/src/pic16/device.c
new file mode 100644 (file)
index 0000000..3b33b56
--- /dev/null
@@ -0,0 +1,686 @@
+/*-------------------------------------------------------------------------
+
+   device.c - Accomodates subtle variations in PIC16 devices
+   Written By -  Scott Dattalo scott@dattalo.com
+   Ported to PIC16 By -  Martin Dubuc m.dubuc@rogers.com
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+
+#include "common.h"   // Include everything in the SDCC src directory
+#include "newalloc.h"
+
+
+#include "pcode.h"
+#include "ralloc.h"
+#include "device.h"
+
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
+#endif
+
+static PIC_device Pics[] = {
+  {
+    {"p18f242", "18f242", "pic18f242", "f242"},
+    (memRange *)NULL,
+    (memRange *)NULL,
+    0,
+    0x300,
+  },
+
+  {
+    {"p18f252", "18f252", "pic18f252", "f252"},
+    (memRange *)NULL,
+    (memRange *)NULL,
+    0,
+    0x600,
+  },
+
+  {
+    {"p18f442", "18f442", "pic18f442", "f442"},
+    (memRange *)NULL,
+    (memRange *)NULL,
+    0,
+    0x300,
+  },
+
+  {
+    {"p18f452", "18f452", "pic18f452", "f452"},
+    (memRange *)NULL,
+    (memRange *)NULL,
+    0,
+    0x600,
+  },
+
+};
+
+static int num_of_supported_PICS = sizeof(Pics)/sizeof(PIC_device);
+
+#define DEFAULT_PIC "f452"
+
+static PIC_device *pic=NULL;
+
+AssignedMemory *pic16_finalMapping=NULL;
+
+#define DEFAULT_CONFIG_BYTE 0xff
+
+#define CONFIG1H_WORD_ADDRESS 0x300001
+#define DEFAULT_CONFIG1H_WORD DEFAULT_CONFIG_BYTE
+
+#define CONFIG2L_WORD_ADDRESS 0x300002
+#define DEFAULT_CONFIG2L_WORD DEFAULT_CONFIG_BYTE
+
+#define CONFIG2H_WORD_ADDRESS 0x300003
+#define DEFAULT_CONFIG2H_WORD DEFAULT_CONFIG_BYTE
+
+#define CONFIG3H_WORD_ADDRESS 0x300005
+#define DEFAULT_CONFIG3H_WORD DEFAULT_CONFIG_BYTE
+
+#define CONFIG4L_WORD_ADDRESS 0x300006
+#define DEFAULT_CONFIG4L_WORD DEFAULT_CONFIG_BYTE
+
+#define CONFIG5L_WORD_ADDRESS 0x300008
+#define DEFAULT_CONFIG5L_WORD DEFAULT_CONFIG_BYTE
+
+#define CONFIG5H_WORD_ADDRESS 0x300009
+#define DEFAULT_CONFIG5H_WORD DEFAULT_CONFIG_BYTE
+
+#define CONFIG6L_WORD_ADDRESS 0x30000a
+#define DEFAULT_CONFIG6L_WORD DEFAULT_CONFIG_BYTE
+
+#define CONFIG6H_WORD_ADDRESS 0x30000b
+#define DEFAULT_CONFIG6H_WORD DEFAULT_CONFIG_BYTE
+
+#define CONFIG7L_WORD_ADDRESS 0x30000c
+#define DEFAULT_CONFIG7L_WORD DEFAULT_CONFIG_BYTE
+
+#define CONFIG7H_WORD_ADDRESS 0x30000d
+#define DEFAULT_CONFIG7H_WORD DEFAULT_CONFIG_BYTE
+
+static unsigned int config1h_word = DEFAULT_CONFIG1H_WORD;
+static unsigned int config2l_word = DEFAULT_CONFIG2L_WORD;
+static unsigned int config2h_word = DEFAULT_CONFIG2H_WORD;
+static unsigned int config3h_word = DEFAULT_CONFIG3H_WORD;
+static unsigned int config4l_word = DEFAULT_CONFIG4L_WORD;
+static unsigned int config5l_word = DEFAULT_CONFIG5L_WORD;
+static unsigned int config5h_word = DEFAULT_CONFIG5H_WORD;
+static unsigned int config6l_word = DEFAULT_CONFIG6L_WORD;
+static unsigned int config6h_word = DEFAULT_CONFIG6H_WORD;
+static unsigned int config7l_word = DEFAULT_CONFIG7L_WORD;
+static unsigned int config7h_word = DEFAULT_CONFIG7H_WORD;
+
+void pic16_addMemRange(memRange *r, int type)
+{
+  int i;
+  int alias = r->alias;
+
+  if (pic->maxRAMaddress < 0) {
+    fprintf(stderr, "missing \"#pragma maxram\" setting\n");
+    return;
+  }
+
+  do {
+    for (i=r->start_address; i<= r->end_address; i++) {
+      if ((i|alias) <= pic->maxRAMaddress) {
+       pic16_finalMapping[i | alias].isValid = 1;
+       pic16_finalMapping[i | alias].alias = r->alias;
+       pic16_finalMapping[i | alias].bank  = r->bank;
+       if(type) {
+         /* hack for now */
+         pic16_finalMapping[i | alias].isSFR  = 1;
+       } else {
+         pic16_finalMapping[i | alias].isSFR  = 0;
+       }
+      } else {
+       fprintf(stderr, "WARNING: %s:%s memory at 0x%x is beyond max ram = 0x%x\n",
+               __FILE__,__FUNCTION__,(i|alias), pic->maxRAMaddress);
+      }
+    }
+
+    /* Decrement alias */
+    if (alias) {
+      alias -= ((alias & (alias - 1)) ^ alias);
+    } else {
+      alias--;
+    }
+
+  } while (alias >= 0);
+}
+
+void pic16_setMaxRAM(int size)
+{
+  int i;
+  pic->maxRAMaddress = size;
+
+  if (pic->maxRAMaddress < 0) {
+    fprintf(stderr, "invalid \"#pragma maxram 0x%x\" setting\n",
+           pic->maxRAMaddress);
+    return;
+  }
+
+  pic16_finalMapping = Safe_calloc(1+pic->maxRAMaddress,
+                            sizeof(AssignedMemory));
+
+  /* Now initialize the pic16_finalMapping array */
+
+  for(i=0; i<=pic->maxRAMaddress; i++) {
+    pic16_finalMapping[i].reg = NULL;
+    pic16_finalMapping[i].isValid = 0;
+  }
+}
+
+/*-----------------------------------------------------------------*
+ *-----------------------------------------------------------------*/
+
+int pic16_isREGinBank(regs *reg, int bank)
+{
+
+  if(!reg || !pic)
+    return 0;
+
+  if(pic16_finalMapping[reg->address].bank == bank)
+    return 1;
+
+  return 0;
+}
+
+/*-----------------------------------------------------------------*
+ *-----------------------------------------------------------------*/
+int pic16_REGallBanks(regs *reg)
+{
+
+  if(!reg || !pic)
+    return 0;
+
+  if (reg->address > pic->maxRAMaddress)
+    return 0;
+
+  return 1;
+
+}
+
+/*-----------------------------------------------------------------*
+ *-----------------------------------------------------------------*/
+
+/*
+ *  pic16_dump_map -- debug stuff
+ */
+
+void pic16_dump_map(void)
+{
+  int i;
+
+  for(i=0; i<=pic->maxRAMaddress; i++) {
+    //fprintf(stdout , "addr 0x%02x is %s\n", i, ((pic16_finalMapping[i].isValid) ? "valid":"invalid"));
+
+    if(pic16_finalMapping[i].isValid) {
+      fprintf(stderr,"addr: 0x%02x",i);
+      if(pic16_finalMapping[i].isSFR)
+       fprintf(stderr," isSFR");
+      if(pic16_finalMapping[i].reg) 
+       fprintf( stderr, "  reg %s", pic16_finalMapping[i].reg->name);
+      fprintf(stderr, "\n");
+    }
+  }
+
+}
+
+void pic16_dump_cblock(FILE *of)
+{
+  int start=-1;
+  int addr=0;
+  int bank_base;
+
+  //pic16_dump_map();   /* display the register map */
+
+  if (pic->maxRAMaddress < 0) {
+    fprintf(stderr, "missing \"#pragma maxram\" setting\n");
+    return;
+  }
+
+  do {
+
+    if(pic16_finalMapping[addr].reg && !pic16_finalMapping[addr].reg->isEmitted) {
+
+      if(start<0)
+       start = addr;
+    } else {
+      if(start>=0) {
+
+       /* clear the lower 7-bits of the start address of the first
+        * variable declared in this bank. The upper bits for the mid
+        * range pics are the bank select bits.
+        */
+
+       bank_base = start & 0xfff8;
+
+       /* The bank number printed in the cblock comment tacitly
+        * assumes that the first register in the contiguous group
+        * of registers represents the bank for the whole group */
+
+        if ((pic16_finalMapping[start].bank == 0 && start <= 0x7f) ||
+            pic16_finalMapping[start].isSFR)
+         fprintf(of,"  cblock  0X%04X\t; Access Bank\n",start);
+        else
+         fprintf(of,"  cblock  0X%04X\t; Bank %d\n",start,pic16_finalMapping[start].bank);
+
+       for( ; start < addr; start++) {
+         if((pic16_finalMapping[start].reg) && !pic16_finalMapping[start].reg->isEmitted ) {
+           fprintf(of,"\t%s",pic16_finalMapping[start].reg->name);
+
+           /* If this register is aliased in multiple banks, then
+            * mangle the variable name with the alias address: */
+           if(pic16_finalMapping[start].alias & start)
+             fprintf(of,"_%x",bank_base);
+
+           if(pic16_finalMapping[start].instance)
+             fprintf(of,"_%d",pic16_finalMapping[start].instance);
+
+           
+           fputc('\n',of);
+
+           //pic16_finalMapping[start].reg->isEmitted = 1;
+         }
+       }
+
+       fprintf(of,"  endc\n");
+
+       start = -1;
+      }
+
+    }
+
+    addr++;
+
+  } while(addr <= pic->maxRAMaddress);
+  
+
+}
+
+/*-----------------------------------------------------------------*
+ *  void pic16_list_valid_pics(int ncols, int list_alias)
+ *
+ * Print out a formatted list of valid PIC devices
+ *
+ * ncols - number of columns in the list.
+ *
+ * list_alias - if non-zero, print all of the supported aliases
+ *              for a device (e.g. F84, 16F84, etc...)
+ *-----------------------------------------------------------------*/
+void pic16_list_valid_pics(int ncols, int list_alias)
+{
+  int col,longest;
+  int i,j,k,l;
+
+  if(list_alias)
+    list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
+
+  /* decrement the column number if it's greater than zero */
+  ncols = (ncols > 1) ? ncols-1 : 4;
+
+  /* Find the device with the longest name */
+  for(i=0,longest=0; i<num_of_supported_PICS; i++) {
+    for(j=0; j<=list_alias; j++) {
+      k = strlen(Pics[i].name[j]);
+      if(k>longest)
+       longest = k;
+    }
+  }
+
+  col = 0;
+
+  for(i=0;  i < num_of_supported_PICS; i++) {
+    j = 0;
+    do {
+
+      fprintf(stderr,"%s", Pics[i].name[j]);
+      if(col<ncols) {
+       l = longest + 2 - strlen(Pics[i].name[j]);
+       for(k=0; k<l; k++)
+         fputc(' ',stderr);
+
+       col++;
+
+      } else {
+       fputc('\n',stderr);
+       col = 0;
+      }
+
+    } while(++j<list_alias);
+
+  }
+  if(col != ncols)
+    fputc('\n',stderr);
+
+}
+
+/*-----------------------------------------------------------------*
+ *  
+ *-----------------------------------------------------------------*/
+PIC_device *pic16_find_device(char *name)
+{
+
+  int i,j;
+
+  if(!name)
+    return NULL;
+
+  for(i = 0; i<num_of_supported_PICS; i++) {
+
+    for(j=0; j<PROCESSOR_NAMES; j++)
+      if(!STRCASECMP(Pics[i].name[j], name) )
+       return &Pics[i];
+  }
+
+  /* not found */
+  return NULL; 
+}
+
+/*-----------------------------------------------------------------*
+ *  
+ *-----------------------------------------------------------------*/
+void pic16_init_pic(char *pic_type)
+{
+  pic = pic16_find_device(pic_type);
+
+  if(!pic) {
+    if(pic_type)
+      fprintf(stderr, "'%s' was not found.\n", pic_type);
+    else
+      fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
+
+    fprintf(stderr,"Valid devices are:\n");
+
+    pic16_list_valid_pics(4,0);
+    exit(1);
+  }
+
+  pic->maxRAMaddress = -1;
+}
+
+/*-----------------------------------------------------------------*
+ *  
+ *-----------------------------------------------------------------*/
+int pic16_picIsInitialized(void)
+{
+  if(pic && pic->maxRAMaddress > 0)
+    return 1;
+
+  return 0;
+
+}
+
+/*-----------------------------------------------------------------*
+ *  char *pic16_processor_base_name(void) - Include file is derived from this.
+ *-----------------------------------------------------------------*/
+char *pic16_processor_base_name(void)
+{
+
+  if(!pic)
+    return NULL;
+
+  return pic->name[0];
+}
+
+static int isSFR(int address)
+{
+
+  if( (address > pic->maxRAMaddress) || !pic16_finalMapping[address].isSFR)
+    return 0;
+
+  return 1;
+
+}
+
+/*-----------------------------------------------------------------*
+ *-----------------------------------------------------------------*/
+static int validAddress(int address, int reg_size)
+{
+  int i;
+
+  if (pic->maxRAMaddress < 0) {
+    fprintf(stderr, "missing \"#pragma maxram\" setting\n");
+    return 0;
+  }
+  //  fprintf(stderr, "validAddress: Checking 0x%04x\n",address);
+  if(address > pic->maxRAMaddress)
+    return 0;
+
+  for (i=0; i<reg_size; i++)
+    if(!pic16_finalMapping[address + i].isValid || 
+       pic16_finalMapping[address+i].reg ||
+       pic16_finalMapping[address+i].isSFR )
+      return 0;
+
+  return 1;
+}
+
+/*-----------------------------------------------------------------*
+ *-----------------------------------------------------------------*/
+static void mapRegister(regs *reg)
+{
+
+  int i;
+  int alias;
+
+  if(!reg || !reg->size) {
+    fprintf(stderr,"WARNING: %s:%s:%d Bad register\n",__FILE__,__FUNCTION__,__LINE__);
+    return;
+  }
+
+  if (pic->maxRAMaddress < 0) {
+    fprintf(stderr, "missing \"#pragma maxram\" setting\n");
+    return;
+  }
+
+  for(i=0; i<reg->size; i++) {
+
+    alias = pic16_finalMapping[reg->address].alias;
+    reg->alias = alias;
+
+    do {
+
+      //fprintf(stdout,"mapping %s to address 0x%02x, reg size = %d\n",reg->name, (reg->address+alias+i),reg->size);
+
+      pic16_finalMapping[reg->address + alias + i].reg = reg;
+      pic16_finalMapping[reg->address + alias + i].instance = i;
+
+      /* Decrement alias */
+      if(alias)
+       alias -= ((alias & (alias - 1)) ^ alias);
+      else
+       alias--;
+
+    } while (alias>=0);
+  }
+
+  //  fprintf(stderr,"%s - %s addr = 0x%03x, size %d\n",__FUNCTION__,reg->name, reg->address,reg->size);
+
+  reg->isMapped = 1;
+
+}
+
+/*-----------------------------------------------------------------*
+ *-----------------------------------------------------------------*/
+static int assignRegister(regs *reg, int start_address)
+{
+  int i;
+
+  //fprintf(stderr,"%s -  %s start_address = 0x%03x\n",__FUNCTION__,reg->name, start_address);
+  if(reg->isFixed) {
+
+    if (validAddress(reg->address,reg->size)) {
+      //fprintf(stderr,"%s -  %s address = 0x%03x\n",__FUNCTION__,reg->name, reg->address);
+      mapRegister(reg);
+      return reg->address;
+    }
+
+    if( isSFR(reg->address)) {
+      mapRegister(reg);
+      return reg->address;
+    }
+
+    //fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
+    //    reg->address, reg->name);
+
+  } else {
+
+    /* This register does not have a fixed address requirement
+     * so we'll search through all availble ram address and
+     * assign the first one */
+
+    for (i=start_address; i<=pic->maxRAMaddress; i++) {
+
+      if (validAddress(i,reg->size)) {
+       reg->address = i;
+       mapRegister(reg);
+       return i;
+      }
+    }
+
+    fprintf(stderr, "WARNING: No more RAM available for %s\n",reg->name);
+
+  }
+
+  return -1;
+}
+
+/*-----------------------------------------------------------------*
+ *-----------------------------------------------------------------*/
+void pic16_assignFixedRegisters(set *regset)
+{
+  regs *reg;
+
+  for (reg = setFirstItem(regset) ; reg ; 
+       reg = setNextItem(regset)) {
+
+    if(reg->isFixed) 
+      assignRegister(reg,0);
+  }
+
+}
+
+/*-----------------------------------------------------------------*
+ *-----------------------------------------------------------------*/
+void pic16_assignRelocatableRegisters(set *regset, int used)
+{
+
+  regs *reg;
+  int address = 0;
+
+  for (reg = setFirstItem(regset) ; reg ; 
+       reg = setNextItem(regset)) {
+
+    //fprintf(stdout,"assigning %s isFixed=%d, wasUsed=%d\n",reg->name,reg->isFixed,reg->wasUsed);
+
+    if((!reg->isFixed) && ( used || reg->wasUsed))
+      address = assignRegister(reg,address);
+
+  }
+
+}
+
+
+/*-----------------------------------------------------------------*
+ *  void pic16_assignConfigWordValue(int address, int value)
+ *
+ * All high performance RISC CPU PICs have seven config word starting
+ * at address 0x300000.
+ * This routine will assign a value to that address.
+ *
+ *-----------------------------------------------------------------*/
+
+void pic16_assignConfigWordValue(int address, int value)
+{
+  switch(address) {
+  case CONFIG1H_WORD_ADDRESS:
+    config1h_word = value;
+    break;
+  case CONFIG2L_WORD_ADDRESS:
+    config2l_word = value;
+    break;
+  case CONFIG2H_WORD_ADDRESS:
+    config2h_word = value;
+    break;
+  case CONFIG3H_WORD_ADDRESS:
+    config3h_word = value;
+    break;
+  case CONFIG4L_WORD_ADDRESS:
+    config4l_word = value;
+    break;
+  case CONFIG5L_WORD_ADDRESS:
+    config5l_word = value;
+    break;
+  case CONFIG5H_WORD_ADDRESS:
+    config5h_word = value;
+    break;
+  case CONFIG6L_WORD_ADDRESS:
+    config6l_word = value;
+    break;
+  case CONFIG6H_WORD_ADDRESS:
+    config6h_word = value;
+    break;
+  case CONFIG7L_WORD_ADDRESS:
+    config7l_word = value;
+    break;
+  case CONFIG7H_WORD_ADDRESS:
+    config7h_word = value;
+    break;
+  }
+
+  //fprintf(stderr,"setting config word to 0x%x\n",value);
+
+}
+/*-----------------------------------------------------------------*
+ * int pic16_getConfigWord(int address)
+ *
+ * Get the current value of the config word.
+ *
+ *-----------------------------------------------------------------*/
+
+int pic16_getConfigWord(int address)
+{
+  switch(address) {
+  case CONFIG1H_WORD_ADDRESS:
+    return config1h_word;
+  case CONFIG2L_WORD_ADDRESS:
+    return config2l_word;
+  case CONFIG2H_WORD_ADDRESS:
+    return config2h_word;
+  case CONFIG3H_WORD_ADDRESS:
+    return config3h_word;
+  case CONFIG4L_WORD_ADDRESS:
+    return config4l_word;
+  case CONFIG5L_WORD_ADDRESS:
+    return config5l_word;
+  case CONFIG5H_WORD_ADDRESS:
+    return config5h_word;
+  case CONFIG6L_WORD_ADDRESS:
+    return config6l_word;
+  case CONFIG6H_WORD_ADDRESS:
+    return config6h_word;
+  case CONFIG7L_WORD_ADDRESS:
+    return config7l_word;
+  case CONFIG7H_WORD_ADDRESS:
+    return config7h_word;
+  default:
+    return 0;
+  }
+}
+
diff --git a/src/pic16/device.h b/src/pic16/device.h
new file mode 100644 (file)
index 0000000..f24cb7a
--- /dev/null
@@ -0,0 +1,103 @@
+/*-------------------------------------------------------------------------
+
+   device.c - Accomodates subtle variations in PIC16 devices
+   Written By -  Scott Dattalo scott@dattalo.com
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-------------------------------------------------------------------------*/
+
+/*
+  PIC device abstraction
+
+  There are dozens of variations of PIC microcontrollers. This include
+  file attempts to abstract those differences so that SDCC can easily
+  deal with them.
+*/
+
+#ifndef  __DEVICE_H__
+#define  __DEVICE_H__
+
+/* memRange - a structure to define a range of valid memory addresses 
+ * 
+ * The Memory of most PICs (and other micros) is a collection of
+ * disjoint chunks. The memRange structure will define the start
+ * and end address of one of these chunks. The memory map of a
+ * particular device is a collection of memRange struct's.
+ */
+
+typedef struct memRange {
+  int start_address;      /* first address in range */
+  int end_address;        /* last */
+  int alias;              /* bit mask defining how/if memory range is aliased 
+                          * e.g. alias = 0x80 means start_address is identical
+                          * to the memory location at (0x80 | start_address) */
+  int bank;               /* PIC memory bank this range occupies */
+
+} memRange;
+
+/* AssignedMemory - A structure to keep track of the memory that has been used.
+ *
+ * When a register gets assigned an address this struct is used to
+ * keep track of a few details about the register. There is one of
+ * these structures for each memory location in the device.
+ */
+
+typedef struct AssignedMemory {
+  regs *reg;        /* Pointer to the register (NULL if this is an invalid address) */
+  int  instance;    /* the i'th byte of a multibyte register */
+  int  alias;       /* Bit mapping of aliased addresses (see memRange) */
+  int  bank;        /* Memory bank of this register */
+  int  isValid:1;   /* True if the address is legal */
+  int  isSFR:1;     /* True if the address is that of a Special Function reg */
+  int  isEmitted:1; /* True if the register has been written to a cBlock */
+
+} AssignedMemory;
+
+
+/*
+ * pic16_finalMapping - Dynamically allocated array that records the register assignments
+ */
+
+extern AssignedMemory *pic16_finalMapping;
+#define PROCESSOR_NAMES    4
+/* Processor unique attributes */
+typedef struct PIC_device {
+  char *name[PROCESSOR_NAMES];/* aliases for the processor name */
+
+  memRange *ram;              /* RAM memory map */
+  memRange *sfr;              /* SFR memory map */
+
+  int maxRAMaddress;          /* maximum value for a data address */
+  int bankMask;               /* Bitmask that is ANDed with address to extract banking bits */
+  //  int hasAliasedRAM:1;        /* True if there are bank independent registers */
+
+} PIC_device;
+
+/* Given a pointer to a register, this macro returns the bank that it is in */
+#define REG_ADDR(r)        ((r)->isBitField ? (((r)->address)>>3) : (r)->address)
+#define REG_BANK(r)        (pic16_finalMapping[REG_ADDR(r)].bank)
+#define REG_isALIASED(r)   (pic16_finalMapping[REG_ADDR(r)].alias != 0)
+#define REG_isVALID(r)     (pic16_finalMapping[REG_ADDR(r)].isValid)
+
+
+/****************************************/
+void pic16_assignConfigWordValue(int address, int value);
+int pic16_getConfigWord(int address);
+int pic16_isREGinBank(regs *reg, int bank);
+int pic16_REGallBanks(regs *reg);
+void pic16_addMemRange(memRange *r, int type);
+void pic16_setMaxRAM(int size);
+
+#endif  /* __DEVICE_H__ */
diff --git a/src/pic16/gen.c b/src/pic16/gen.c
new file mode 100644 (file)
index 0000000..d9265bc
--- /dev/null
@@ -0,0 +1,10179 @@
+/*-------------------------------------------------------------------------
+  SDCCgen51.c - source file for code generation for 8051
+  
+  Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+         and -  Jean-Louis VERN.jlvern@writeme.com (1999)
+  Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
+  PIC port   -  Scott Dattalo scott@dattalo.com (2000)
+  PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
+  
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+  
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  
+  In other words, you are welcome to use, share and improve this program.
+  You are forbidden to forbid anyone else to use, share and improve
+  what you give them.   Help stamp out software-hoarding!
+  
+  Notes:
+  000123 mlh   Moved aopLiteral to SDCCglue.c to help the split
+               Made everything static
+-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "SDCCglobl.h"
+#include "newalloc.h"
+
+#ifdef HAVE_SYS_ISA_DEFS_H
+#include <sys/isa_defs.h>
+#else
+#ifdef HAVE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#else
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#else
+#if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+#warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
+#warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
+#endif
+#endif
+#endif
+#endif
+
+#include "common.h"
+#include "SDCCpeeph.h"
+#include "ralloc.h"
+#include "pcode.h"
+#include "gen.h"
+
+
+extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
+extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
+void pic16_genMult8X8_8 (operand *, operand *,operand *);
+pCode *pic16_AssembleLine(char *line);
+extern void pic16_printpBlock(FILE *of, pBlock *pb);
+static asmop *newAsmop (short type);
+static pCodeOp *popRegFromString(char *str, int size, int offset);
+static void mov2w (asmop *aop, int offset);
+static int aopIdx (asmop *aop, int offset);
+
+static int labelOffset=0;
+extern int pic16_debug_verbose;
+static int optimized_for_speed = 0;
+
+/* max_key keeps track of the largest label number used in 
+   a function. This is then used to adjust the label offset
+   for the next function.
+*/
+static int max_key=0;
+static int GpsuedoStkPtr=0;
+
+pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
+unsigned int pic16aopLiteral (value *val, int offset);
+const char *pic16_AopType(short type);
+static iCode *ifxForOp ( operand *op, iCode *ic );
+
+#define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
+
+/* this is the down and dirty file with all kinds of 
+   kludgy & hacky stuff. This is what it is all about
+   CODE GENERATION for a specific MCU . some of the
+   routines may be reusable, will have to see */
+
+static char *zero = "#0x00";
+static char *one  = "#0x01";
+static char *spname = "sp";
+
+char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
+//char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
+unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
+static char **fReturn = fReturnpic16;
+
+static char *accUse[] = {"a","b"};
+
+//static short rbank = -1;
+
+static struct {
+    short r0Pushed;
+    short r1Pushed;
+    short accInUse;
+    short inLine;
+    short debugLine;
+    short nRegsSaved;
+    set *sendSet;
+} _G;
+
+/* Resolved ifx structure. This structure stores information
+   about an iCode ifx that makes it easier to generate code.
+*/
+typedef struct resolvedIfx {
+  symbol *lbl;     /* pointer to a label */
+  int condition;   /* true or false ifx */
+  int generated;   /* set true when the code associated with the ifx
+                   * is generated */
+} resolvedIfx;
+
+extern int pic16_ptrRegReq ;
+extern int pic16_nRegs;
+extern FILE *codeOutFile;
+static void saverbank (int, iCode *,bool);
+
+static lineNode *lineHead = NULL;
+static lineNode *lineCurr = NULL;
+
+static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
+0xE0, 0xC0, 0x80, 0x00};
+static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
+0x07, 0x03, 0x01, 0x00};
+
+static  pBlock *pb;
+
+/*-----------------------------------------------------------------*/
+/*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
+/*                 exponent of 2 is returned, otherwise -1 is      */
+/*                 returned.                                       */
+/* note that this is similar to the function `powof2' in SDCCsymt  */
+/* if(n == 2^y)                                                    */
+/*   return y;                                                     */
+/* return -1;                                                      */
+/*-----------------------------------------------------------------*/
+static int my_powof2 (unsigned long num)
+{
+  if(num) {
+    if( (num & (num-1)) == 0) {
+      int nshifts = -1;
+      while(num) {
+       num>>=1;
+       nshifts++;
+      }
+      return nshifts;
+    }
+  }
+
+  return -1;
+}
+
+void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
+{
+
+  DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
+                      line_no,
+                      ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
+                      ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
+                      ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
+                      ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
+                      ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
+                      ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
+                      ((result) ? AOP_SIZE(result) : 0));
+
+}
+
+void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
+{
+
+  DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
+                      line_no,
+                      ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
+                      ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
+                      ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
+                      ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
+                      ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
+                      ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
+
+}
+
+void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
+{
+    va_list ap;
+    char lb[INITIAL_INLINEASM];  
+    char *lbp = lb;
+
+    if(!pic16_debug_verbose)
+      return;
+
+    va_start(ap,fmt);   
+
+    if (inst && *inst) {
+       if (fmt && *fmt)
+           sprintf(lb,"%s\t",inst);
+       else
+           sprintf(lb,"%s",inst);
+        vsprintf(lb+(strlen(lb)),fmt,ap);
+    }  else
+        vsprintf(lb,fmt,ap);
+
+    while (isspace(*lbp)) lbp++;
+
+    if (lbp && *lbp) 
+        lineCurr = (lineCurr ?
+                    connectLine(lineCurr,newLineNode(lb)) :
+                    (lineHead = newLineNode(lb)));
+    lineCurr->isInline = _G.inLine;
+    lineCurr->isDebug  = _G.debugLine;
+
+    pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
+
+    va_end(ap);
+}
+
+
+void pic16_emitpLabel(int key)
+{
+  pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
+}
+
+void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
+{
+
+  if(pcop)
+    pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
+  else
+    DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
+}
+
+void pic16_emitpcodeNULLop(PIC_OPCODE poc)
+{
+
+  pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
+
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_emitcode - writes the code into a file : for now it is simple    */
+/*-----------------------------------------------------------------*/
+void pic16_emitcode (char *inst,char *fmt, ...)
+{
+    va_list ap;
+    char lb[INITIAL_INLINEASM];  
+    char *lbp = lb;
+
+    va_start(ap,fmt);   
+
+    if (inst && *inst) {
+       if (fmt && *fmt)
+           sprintf(lb,"%s\t",inst);
+       else
+           sprintf(lb,"%s",inst);
+        vsprintf(lb+(strlen(lb)),fmt,ap);
+    }  else
+        vsprintf(lb,fmt,ap);
+
+    while (isspace(*lbp)) lbp++;
+
+    if (lbp && *lbp) 
+        lineCurr = (lineCurr ?
+                    connectLine(lineCurr,newLineNode(lb)) :
+                    (lineHead = newLineNode(lb)));
+    lineCurr->isInline = _G.inLine;
+    lineCurr->isDebug  = _G.debugLine;
+
+    if(pic16_debug_verbose)
+      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
+
+    va_end(ap);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
+/*-----------------------------------------------------------------*/
+static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
+{
+    bool r0iu = FALSE , r1iu = FALSE;
+    bool r0ou = FALSE , r1ou = FALSE;
+
+    /* the logic: if r0 & r1 used in the instruction
+    then we are in trouble otherwise */
+
+    /* first check if r0 & r1 are used by this
+    instruction, in which case we are in trouble */
+    if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
+        (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
+    {
+        goto endOfWorld;      
+    }
+
+    r0ou = bitVectBitValue(ic->rMask,R0_IDX);
+    r1ou = bitVectBitValue(ic->rMask,R1_IDX);
+
+    /* if no usage of r0 then return it */
+    if (!r0iu && !r0ou) {
+        ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
+        (*aopp)->type = AOP_R0;
+        
+        return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
+    }
+
+    /* if no usage of r1 then return it */
+    if (!r1iu && !r1ou) {
+        ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
+        (*aopp)->type = AOP_R1;
+
+        return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
+    }    
+
+    /* now we know they both have usage */
+    /* if r0 not used in this instruction */
+    if (!r0iu) {
+        /* push it if not already pushed */
+        if (!_G.r0Pushed) {
+         //pic16_emitcode ("push","%s",
+         //          pic16_regWithIdx(R0_IDX)->dname);
+            _G.r0Pushed++ ;
+        }
+        
+        ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
+        (*aopp)->type = AOP_R0;
+
+        return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
+    }
+
+    /* if r1 not used then */
+
+    if (!r1iu) {
+        /* push it if not already pushed */
+        if (!_G.r1Pushed) {
+         //pic16_emitcode ("push","%s",
+         //          pic16_regWithIdx(R1_IDX)->dname);
+            _G.r1Pushed++ ;
+        }
+        
+        ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
+        (*aopp)->type = AOP_R1;
+        return pic16_regWithIdx(R1_IDX);
+    }
+
+endOfWorld :
+    /* I said end of world but not quite end of world yet */
+    /* if this is a result then we can push it on the stack*/
+    if (result) {
+        (*aopp)->type = AOP_STK;    
+        return NULL;
+    }
+
+    /* other wise this is true end of the world */
+    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+           "getFreePtr should never reach here");
+    exit(0);
+}
+
+/*-----------------------------------------------------------------*/
+/* newAsmop - creates a new asmOp                                  */
+/*-----------------------------------------------------------------*/
+static asmop *newAsmop (short type)
+{
+    asmop *aop;
+
+    aop = Safe_calloc(1,sizeof(asmop));
+    aop->type = type;
+    return aop;
+}
+
+static void genSetDPTR(int n)
+{
+    if (!n)
+    {
+        pic16_emitcode(";", "Select standard DPTR");
+        pic16_emitcode("mov", "dps, #0x00");
+    }
+    else
+    {
+        pic16_emitcode(";", "Select alternate DPTR");
+        pic16_emitcode("mov", "dps, #0x01");
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* resolveIfx - converts an iCode ifx into a form more useful for  */
+/*              generating code                                    */
+/*-----------------------------------------------------------------*/
+static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
+{
+  if(!resIfx) 
+    return;
+
+  //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
+
+  resIfx->condition = 1;    /* assume that the ifx is true */
+  resIfx->generated = 0;    /* indicate that the ifx has not been used */
+
+  if(!ifx) {
+    resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
+/*
+    DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
+                       __FUNCTION__,__LINE__,resIfx->lbl->key);
+*/
+  } else {
+    if(IC_TRUE(ifx)) {
+      resIfx->lbl = IC_TRUE(ifx);
+    } else {
+      resIfx->lbl = IC_FALSE(ifx);
+      resIfx->condition = 0;
+    }
+/*
+    if(IC_TRUE(ifx)) 
+      DEBUGpic16_emitcode("; ***","ifx true is non-null");
+    if(IC_FALSE(ifx)) 
+      DEBUGpic16_emitcode("; ***","ifx false is non-null");
+*/
+  }
+
+  //  DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
+
+}
+/*-----------------------------------------------------------------*/
+/* pointerCode - returns the code for a pointer type               */
+/*-----------------------------------------------------------------*/
+static int pointerCode (sym_link *etype)
+{
+
+    return PTR_TYPE(SPEC_OCLS(etype));
+
+}
+
+/*-----------------------------------------------------------------*/
+/* aopForSym - for a true symbol                                   */
+/*-----------------------------------------------------------------*/
+static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
+{
+    asmop *aop;
+    memmap *space= SPEC_OCLS(sym->etype);
+
+    DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
+    /* if already has one */
+    if (sym->aop)
+        return sym->aop;
+
+    /* assign depending on the storage class */
+    /* if it is on the stack or indirectly addressable */
+    /* space we need to assign either r0 or r1 to it   */    
+    if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
+        sym->aop = aop = newAsmop(0);
+        aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
+        aop->size = getSize(sym->type);
+
+        /* now assign the address of the variable to 
+        the pointer register */
+        if (aop->type != AOP_STK) {
+
+            if (sym->onStack) {
+                    if ( _G.accInUse )
+                        pic16_emitcode("push","acc");
+
+                    pic16_emitcode("mov","a,_bp");
+                    pic16_emitcode("add","a,#0x%02x",
+                             ((sym->stack < 0) ?
+                             ((char)(sym->stack - _G.nRegsSaved )) :
+                             ((char)sym->stack)) & 0xff);
+                    pic16_emitcode("mov","%s,a",
+                             aop->aopu.aop_ptr->name);
+
+                    if ( _G.accInUse )
+                        pic16_emitcode("pop","acc");
+            } else
+                pic16_emitcode("mov","%s,#%s",
+                         aop->aopu.aop_ptr->name,
+                         sym->rname);
+            aop->paged = space->paged;
+        } else
+            aop->aopu.aop_stk = sym->stack;
+        return aop;
+    }
+    
+    if (sym->onStack && options.stack10bit)
+    {
+        /* It's on the 10 bit stack, which is located in
+         * far data space.
+         */
+         
+      //DEBUGpic16_emitcode(";","%d",__LINE__);
+
+        if ( _G.accInUse )
+               pic16_emitcode("push","acc");
+
+        pic16_emitcode("mov","a,_bp");
+        pic16_emitcode("add","a,#0x%02x",
+                 ((sym->stack < 0) ?
+                   ((char)(sym->stack - _G.nRegsSaved )) :
+                   ((char)sym->stack)) & 0xff);
+        
+        genSetDPTR(1);
+        pic16_emitcode ("mov","dpx1,#0x40");
+        pic16_emitcode ("mov","dph1,#0x00");
+        pic16_emitcode ("mov","dpl1, a");
+        genSetDPTR(0);
+       
+        if ( _G.accInUse )
+            pic16_emitcode("pop","acc");
+            
+        sym->aop = aop = newAsmop(AOP_DPTR2);
+       aop->size = getSize(sym->type); 
+       return aop;
+    }
+
+    //DEBUGpic16_emitcode(";","%d",__LINE__);
+    /* if in bit space */
+    if (IN_BITSPACE(space)) {
+        sym->aop = aop = newAsmop (AOP_CRY);
+        aop->aopu.aop_dir = sym->rname ;
+        aop->size = getSize(sym->type);
+       //DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
+        return aop;
+    }
+    /* if it is in direct space */
+    if (IN_DIRSPACE(space)) {
+        sym->aop = aop = newAsmop (AOP_DIR);
+        aop->aopu.aop_dir = sym->rname ;
+        aop->size = getSize(sym->type);
+       DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
+        return aop;
+    }
+
+    /* special case for a function */
+    if (IS_FUNC(sym->type)) {   
+        sym->aop = aop = newAsmop(AOP_IMMD);    
+        //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
+       aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
+        strcpy(aop->aopu.aop_immd,sym->rname);
+        aop->size = FPTRSIZE; 
+       DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
+        return aop;
+    }
+
+
+    /* only remaining is far space */
+    /* in which case DPTR gets the address */
+    sym->aop = aop = newAsmop(AOP_PCODE);
+
+    aop->aopu.pcop = pic16_popGetImmd(sym->rname,0,0);
+    PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
+    PCOI(aop->aopu.pcop)->index = 0;
+
+    DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
+                       __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
+
+    pic16_allocDirReg (IC_LEFT(ic));
+
+    aop->size = FPTRSIZE; 
+/*
+    DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
+    sym->aop = aop = newAsmop(AOP_DPTR);
+    pic16_emitcode ("mov","dptr,#%s", sym->rname);
+    aop->size = getSize(sym->type);
+
+    DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
+*/
+
+    /* if it is in code space */
+    if (IN_CODESPACE(space))
+        aop->code = 1;
+
+    return aop;     
+}
+
+/*-----------------------------------------------------------------*/
+/* aopForRemat - rematerialzes an object                           */
+/*-----------------------------------------------------------------*/
+static asmop *aopForRemat (operand *op) // x symbol *sym)
+{
+  symbol *sym = OP_SYMBOL(op);
+  iCode *ic = NULL;
+  asmop *aop = newAsmop(AOP_PCODE);
+  int val = 0;
+  int offset = 0;
+
+  ic = sym->rematiCode;
+
+  DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
+  if(IS_OP_POINTER(op)) {
+    DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
+  }
+  for (;;) {
+    if (ic->op == '+') {
+      val += (int) operandLitValue(IC_RIGHT(ic));
+    } else if (ic->op == '-') {
+      val -= (int) operandLitValue(IC_RIGHT(ic));
+    } else
+      break;
+       
+    ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
+  }
+
+  offset = OP_SYMBOL(IC_LEFT(ic))->offset;
+  aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
+  PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
+  PCOI(aop->aopu.pcop)->index = val;
+
+  DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
+                     __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
+                     val, IS_PTR_CONST(operandType(op)));
+
+  //    DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
+
+  pic16_allocDirReg (IC_LEFT(ic));
+
+  return aop;        
+}
+
+static int aopIdx (asmop *aop, int offset)
+{
+  if(!aop)
+    return -1;
+
+  if(aop->type !=  AOP_REG)
+    return -2;
+       
+  return aop->aopu.aop_reg[offset]->rIdx;
+
+}
+/*-----------------------------------------------------------------*/
+/* regsInCommon - two operands have some registers in common       */
+/*-----------------------------------------------------------------*/
+static bool regsInCommon (operand *op1, operand *op2)
+{
+    symbol *sym1, *sym2;
+    int i;
+
+    /* if they have registers in common */
+    if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
+        return FALSE ;
+
+    sym1 = OP_SYMBOL(op1);
+    sym2 = OP_SYMBOL(op2);
+
+    if (sym1->nRegs == 0 || sym2->nRegs == 0)
+        return FALSE ;
+
+    for (i = 0 ; i < sym1->nRegs ; i++) {
+        int j;
+        if (!sym1->regs[i])
+            continue ;
+
+        for (j = 0 ; j < sym2->nRegs ;j++ ) {
+            if (!sym2->regs[j])
+                continue ;
+
+            if (sym2->regs[j] == sym1->regs[i])
+                return TRUE ;
+        }
+    }
+
+    return FALSE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* operandsEqu - equivalent                                        */
+/*-----------------------------------------------------------------*/
+static bool operandsEqu ( operand *op1, operand *op2)
+{
+    symbol *sym1, *sym2;
+
+    /* if they not symbols */
+    if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
+        return FALSE;
+
+    sym1 = OP_SYMBOL(op1);
+    sym2 = OP_SYMBOL(op2);
+
+    /* if both are itemps & one is spilt
+       and the other is not then false */
+    if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
+       sym1->isspilt != sym2->isspilt )
+       return FALSE ;
+
+    /* if they are the same */
+    if (sym1 == sym2)
+        return TRUE ;
+
+    if (strcmp(sym1->rname,sym2->rname) == 0)
+        return TRUE;
+
+
+    /* if left is a tmp & right is not */
+    if (IS_ITEMP(op1)  && 
+        !IS_ITEMP(op2) &&
+        sym1->isspilt  &&
+        (sym1->usl.spillLoc == sym2))
+        return TRUE;
+
+    if (IS_ITEMP(op2)  && 
+        !IS_ITEMP(op1) &&
+        sym2->isspilt  &&
+       sym1->level > 0 &&
+        (sym2->usl.spillLoc == sym1))
+        return TRUE ;
+
+    return FALSE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_sameRegs - two asmops have the same registers                   */
+/*-----------------------------------------------------------------*/
+bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
+{
+    int i;
+
+    if (aop1 == aop2)
+        return TRUE ;
+
+    if (aop1->type != AOP_REG ||
+        aop2->type != AOP_REG )
+        return FALSE ;
+
+    if (aop1->size != aop2->size )
+        return FALSE ;
+
+    for (i = 0 ; i < aop1->size ; i++ )
+        if (aop1->aopu.aop_reg[i] !=
+            aop2->aopu.aop_reg[i] )
+            return FALSE ;
+
+    return TRUE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_aopOp - allocates an asmop for an operand  :                    */
+/*-----------------------------------------------------------------*/
+void pic16_aopOp (operand *op, iCode *ic, bool result)
+{
+    asmop *aop;
+    symbol *sym;
+    int i;
+
+    if (!op)
+        return ;
+
+    //    DEBUGpic16_emitcode(";","%d",__LINE__);
+    /* if this a literal */
+    if (IS_OP_LITERAL(op)) {
+        op->aop = aop = newAsmop(AOP_LIT);
+        aop->aopu.aop_lit = op->operand.valOperand;
+        aop->size = getSize(operandType(op));
+        return;
+    }
+
+    {
+      sym_link *type = operandType(op);
+      if(IS_PTR_CONST(type))
+       DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
+    }
+
+    /* if already has a asmop then continue */
+    if (op->aop)
+        return ;
+
+    /* if the underlying symbol has a aop */
+    if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
+      DEBUGpic16_emitcode(";","%d",__LINE__);
+        op->aop = OP_SYMBOL(op)->aop;
+        return;
+    }
+
+    /* if this is a true symbol */
+    if (IS_TRUE_SYMOP(op)) {    
+      //DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
+      op->aop = aopForSym(ic,OP_SYMBOL(op),result);
+      return ;
+    }
+
+    /* this is a temporary : this has
+    only four choices :
+    a) register
+    b) spillocation
+    c) rematerialize 
+    d) conditional   
+    e) can be a return use only */
+
+    sym = OP_SYMBOL(op);
+
+
+    /* if the type is a conditional */
+    if (sym->regType == REG_CND) {
+        aop = op->aop = sym->aop = newAsmop(AOP_CRY);
+        aop->size = 0;
+        return;
+    }
+
+    /* if it is spilt then two situations
+    a) is rematerialize 
+    b) has a spill location */
+    if (sym->isspilt || sym->nRegs == 0) {
+
+      DEBUGpic16_emitcode(";","%d",__LINE__);
+        /* rematerialize it NOW */
+        if (sym->remat) {
+
+            sym->aop = op->aop = aop =
+                                      aopForRemat (op);
+            aop->size = getSize(sym->type);
+           //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
+            return;
+        }
+
+       if (sym->accuse) {
+           int i;
+            aop = op->aop = sym->aop = newAsmop(AOP_ACC);
+            aop->size = getSize(sym->type);
+            for ( i = 0 ; i < 2 ; i++ )
+                aop->aopu.aop_str[i] = accUse[i];
+           DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
+            return;  
+       }
+
+        if (sym->ruonly ) {
+         /*
+         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
+         aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
+         //pic16_allocDirReg (IC_LEFT(ic));
+         aop->size = getSize(sym->type);
+         */
+
+         unsigned i;
+
+         aop = op->aop = sym->aop = newAsmop(AOP_STR);
+         aop->size = getSize(sym->type);
+         for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
+           aop->aopu.aop_str[i] = fReturn[i];
+
+         DEBUGpic16_emitcode(";","%d",__LINE__);
+         return;
+        }
+
+        /* else spill location  */
+       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
+           /* force a new aop if sizes differ */
+           sym->usl.spillLoc->aop = NULL;
+       }
+       DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
+                           __FUNCTION__,__LINE__,
+                           sym->usl.spillLoc->rname,
+                           sym->rname, sym->usl.spillLoc->offset);
+
+       sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
+       //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
+       aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
+                                         getSize(sym->type), 
+                                         sym->usl.spillLoc->offset);
+        aop->size = getSize(sym->type);
+
+        return;
+    }
+
+    {
+      sym_link *type = operandType(op);
+      if(IS_PTR_CONST(type)) 
+       DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
+    }
+
+    /* must be in a register */
+    DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
+    sym->aop = op->aop = aop = newAsmop(AOP_REG);
+    aop->size = sym->nRegs;
+    for ( i = 0 ; i < sym->nRegs ;i++)
+        aop->aopu.aop_reg[i] = sym->regs[i];
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_freeAsmop - free up the asmop given to an operand               */
+/*----------------------------------------------------------------*/
+void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
+{   
+    asmop *aop ;
+
+    if (!op)
+        aop = aaop;
+    else 
+        aop = op->aop;
+
+    if (!aop)
+        return ;
+
+    if (aop->freed)
+        goto dealloc; 
+
+    aop->freed = 1;
+
+    /* depending on the asmop type only three cases need work AOP_RO
+       , AOP_R1 && AOP_STK */
+#if 0
+    switch (aop->type) {
+        case AOP_R0 :
+            if (_G.r0Pushed ) {
+                if (pop) {
+                    pic16_emitcode ("pop","ar0");     
+                    _G.r0Pushed--;
+                }
+            }
+            bitVectUnSetBit(ic->rUsed,R0_IDX);
+            break;
+
+        case AOP_R1 :
+            if (_G.r1Pushed ) {
+                if (pop) {
+                    pic16_emitcode ("pop","ar1");
+                    _G.r1Pushed--;
+                }
+            }
+            bitVectUnSetBit(ic->rUsed,R1_IDX);          
+            break;
+
+        case AOP_STK :
+        {
+            int sz = aop->size;    
+            int stk = aop->aopu.aop_stk + aop->size;
+            bitVectUnSetBit(ic->rUsed,R0_IDX);
+            bitVectUnSetBit(ic->rUsed,R1_IDX);          
+
+            getFreePtr(ic,&aop,FALSE);
+            
+            if (options.stack10bit)
+            {
+                /* I'm not sure what to do here yet... */
+                /* #STUB */
+               fprintf(stderr, 
+                       "*** Warning: probably generating bad code for "
+                       "10 bit stack mode.\n");
+            }
+            
+            if (stk) {
+                pic16_emitcode ("mov","a,_bp");
+                pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
+                pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
+            } else {
+                pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
+            }
+
+            while (sz--) {
+                pic16_emitcode("pop","acc");
+                pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
+                if (!sz) break;
+                pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
+            }
+            op->aop = aop;
+            pic16_freeAsmop(op,NULL,ic,TRUE);
+            if (_G.r0Pushed) {
+                pic16_emitcode("pop","ar0");
+                _G.r0Pushed--;
+            }
+
+            if (_G.r1Pushed) {
+                pic16_emitcode("pop","ar1");
+                _G.r1Pushed--;
+            }       
+        }
+    }
+#endif
+
+dealloc:
+    /* all other cases just dealloc */
+    if (op ) {
+        op->aop = NULL;
+        if (IS_SYMOP(op)) {
+            OP_SYMBOL(op)->aop = NULL;    
+            /* if the symbol has a spill */
+           if (SPIL_LOC(op))
+                SPIL_LOC(op)->aop = NULL;
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_aopGet - for fetching value of the aop                          */
+/*-----------------------------------------------------------------*/
+char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
+{
+    char *s = buffer ;
+    char *rs;
+
+    //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* offset is greater than
+    size then zero */
+    if (offset > (aop->size - 1) &&
+        aop->type != AOP_LIT)
+        return zero;
+
+    /* depending on type */
+    switch (aop->type) {
+       
+    case AOP_R0:
+    case AOP_R1:
+        DEBUGpic16_emitcode(";","%d",__LINE__);
+       /* if we need to increment it */       
+       while (offset > aop->coff) {        
+           pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
+           aop->coff++;
+       }
+       
+       while (offset < aop->coff) {
+           pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
+           aop->coff--;
+       }
+       
+       aop->coff = offset ;
+       if (aop->paged) {
+           pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
+           return (dname ? "acc" : "a");
+       }       
+       sprintf(s,"@%s",aop->aopu.aop_ptr->name);
+       rs = Safe_calloc(1,strlen(s)+1);
+       strcpy(rs,s);   
+       return rs;
+       
+    case AOP_DPTR:
+    case AOP_DPTR2:
+        DEBUGpic16_emitcode(";","%d",__LINE__);
+    if (aop->type == AOP_DPTR2)
+    {
+        genSetDPTR(1);
+    }
+    
+       while (offset > aop->coff) {
+           pic16_emitcode ("inc","dptr");
+           aop->coff++;
+       }
+       
+       while (offset < aop->coff) {        
+           pic16_emitcode("lcall","__decdptr");
+           aop->coff--;
+       }
+       
+       aop->coff = offset;
+       if (aop->code) {
+           pic16_emitcode("clr","a");
+           pic16_emitcode("movc","a,@a+dptr");
+        }
+    else {
+           pic16_emitcode("movx","a,@dptr");
+    }
+           
+    if (aop->type == AOP_DPTR2)
+    {
+        genSetDPTR(0);
+    }
+           
+    return (dname ? "acc" : "a");
+       
+       
+    case AOP_IMMD:
+       if (bit16) 
+           sprintf (s,"%s",aop->aopu.aop_immd);
+       else
+           if (offset) 
+               sprintf(s,"(%s >> %d)",
+                       aop->aopu.aop_immd,
+                       offset*8);
+           else
+               sprintf(s,"%s",
+                       aop->aopu.aop_immd);
+       DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
+       rs = Safe_calloc(1,strlen(s)+1);
+       strcpy(rs,s);   
+       return rs;
+       
+    case AOP_DIR:
+      if (offset) {
+       sprintf(s,"(%s + %d)",
+               aop->aopu.aop_dir,
+               offset);
+       DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
+      } else
+           sprintf(s,"%s",aop->aopu.aop_dir);
+       rs = Safe_calloc(1,strlen(s)+1);
+       strcpy(rs,s);   
+       return rs;
+       
+    case AOP_REG:
+      //if (dname) 
+      //    return aop->aopu.aop_reg[offset]->dname;
+      //else
+           return aop->aopu.aop_reg[offset]->name;
+       
+    case AOP_CRY:
+      //pic16_emitcode(";","%d",__LINE__);
+      return aop->aopu.aop_dir;
+       
+    case AOP_ACC:
+        DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
+       return "AOP_accumulator_bug";
+
+    case AOP_LIT:
+       sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
+       rs = Safe_calloc(1,strlen(s)+1);
+       strcpy(rs,s);   
+       return rs;
+       
+    case AOP_STR:
+       aop->coff = offset ;
+       if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
+           dname)
+           return "acc";
+        DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
+       
+       return aop->aopu.aop_str[offset];
+       
+    case AOP_PCODE:
+      {
+       pCodeOp *pcop = aop->aopu.pcop;
+       DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
+       if(pcop->name) {
+         DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
+         //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
+         sprintf(s,"%s", pcop->name);
+       } else
+         sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
+
+      }
+      rs = Safe_calloc(1,strlen(s)+1);
+      strcpy(rs,s);   
+      return rs;
+
+    }
+
+    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+           "aopget got unsupported aop->type");
+    exit(0);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* pic16_popGetTempReg - create a new temporary pCodeOp                  */
+/*-----------------------------------------------------------------*/
+pCodeOp *pic16_popGetTempReg(void)
+{
+
+  pCodeOp *pcop;
+
+  pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
+  if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
+    PCOR(pcop)->r->wasUsed=1;
+    PCOR(pcop)->r->isFree=0;
+  }
+
+  return pcop;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_popGetTempReg - create a new temporary pCodeOp                  */
+/*-----------------------------------------------------------------*/
+void pic16_popReleaseTempReg(pCodeOp *pcop)
+{
+
+  if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
+    PCOR(pcop)->r->isFree = 1;
+
+}
+/*-----------------------------------------------------------------*/
+/* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
+/*-----------------------------------------------------------------*/
+pCodeOp *pic16_popGetLabel(unsigned int key)
+{
+
+  DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
+
+  if(key>max_key)
+    max_key = key;
+
+  return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_popCopyReg - copy a pcode operator                              */
+/*-----------------------------------------------------------------*/
+pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
+{
+  pCodeOpReg *pcor;
+
+  pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
+  pcor->pcop.type = pc->pcop.type;
+  if(pc->pcop.name) {
+    if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
+      fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
+  } else
+    pcor->pcop.name = NULL;
+
+  pcor->r = pc->r;
+  pcor->rIdx = pc->rIdx;
+  pcor->r->wasUsed=1;
+
+  //DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
+
+  return PCOP(pcor);
+}
+/*-----------------------------------------------------------------*/
+/* pic16_popGet - asm operator to pcode operator conversion              */
+/*-----------------------------------------------------------------*/
+pCodeOp *pic16_popGetLit(unsigned int lit)
+{
+
+  return pic16_newpCodeOpLit(lit);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* pic16_popGetImmd - asm operator to pcode immediate conversion         */
+/*-----------------------------------------------------------------*/
+pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
+{
+
+  return pic16_newpCodeOpImmd(name, offset,index, 0);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* pic16_popGet - asm operator to pcode operator conversion              */
+/*-----------------------------------------------------------------*/
+pCodeOp *pic16_popGetWithString(char *str)
+{
+  pCodeOp *pcop;
+
+
+  if(!str) {
+    fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
+    exit (1);
+  }
+
+  pcop = pic16_newpCodeOp(str,PO_STR);
+
+  return pcop;
+}
+
+/*-----------------------------------------------------------------*/
+/* popRegFromString -                                              */
+/*-----------------------------------------------------------------*/
+static pCodeOp *popRegFromString(char *str, int size, int offset)
+{
+
+  pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
+  pcop->type = PO_DIR;
+
+  DEBUGpic16_emitcode(";","%d",__LINE__);
+
+  if(!str)
+    str = "BAD_STRING";
+
+  pcop->name = Safe_calloc(1,strlen(str)+1);
+  strcpy(pcop->name,str);
+
+  //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
+
+  PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
+  if(PCOR(pcop)->r == NULL) {
+    //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
+    PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
+    DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
+  } else {
+    DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
+  }
+  PCOR(pcop)->instance = offset;
+
+  return pcop;
+}
+
+static pCodeOp *popRegFromIdx(int rIdx)
+{
+  pCodeOp *pcop;
+
+  DEBUGpic16_emitcode ("; ***","%s,%d  , rIdx=0x%x",
+                      __FUNCTION__,__LINE__,rIdx);
+
+  pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
+
+  PCOR(pcop)->rIdx = rIdx;
+  PCOR(pcop)->r = pic16_regWithIdx(rIdx);
+  PCOR(pcop)->r->isFree = 0;
+  PCOR(pcop)->r->wasUsed = 1;
+
+  pcop->type = PCOR(pcop)->r->pc_type;
+
+
+  return pcop;
+}
+/*-----------------------------------------------------------------*/
+/* pic16_popGet - asm operator to pcode operator conversion              */
+/*-----------------------------------------------------------------*/
+pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
+{
+  //char *s = buffer ;
+    //char *rs;
+
+    pCodeOp *pcop;
+
+    //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* offset is greater than
+    size then zero */
+
+    if (offset > (aop->size - 1) &&
+        aop->type != AOP_LIT)
+      return NULL;  //zero;
+
+    /* depending on type */
+    switch (aop->type) {
+       
+    case AOP_R0:
+    case AOP_R1:
+    case AOP_DPTR:
+    case AOP_DPTR2:
+    case AOP_ACC:
+        DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
+       return NULL;
+       
+    case AOP_IMMD:
+      DEBUGpic16_emitcode(";","%d",__LINE__);
+      return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
+
+    case AOP_DIR:
+      return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
+#if 0
+       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
+       pcop->type = PO_DIR;
+
+       /*
+       if (offset)
+           sprintf(s,"(%s + %d)",
+                   aop->aopu.aop_dir,
+                   offset);
+       else
+           sprintf(s,"%s",aop->aopu.aop_dir);
+       pcop->name = Safe_calloc(1,strlen(s)+1);
+       strcpy(pcop->name,s);   
+       */
+       pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
+       strcpy(pcop->name,aop->aopu.aop_dir);   
+       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
+       if(PCOR(pcop)->r == NULL) {
+         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
+         PCOR(pcop)->r = pic16_allocRegByName (aop->aopu.aop_dir,aop->size);
+         DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
+       } else {
+         DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
+       }
+       PCOR(pcop)->instance = offset;
+
+       return pcop;
+#endif
+       
+    case AOP_REG:
+      {
+       int rIdx = aop->aopu.aop_reg[offset]->rIdx;
+
+       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
+       PCOR(pcop)->rIdx = rIdx;
+       PCOR(pcop)->r = pic16_regWithIdx(rIdx);
+       PCOR(pcop)->r->wasUsed=1;
+       PCOR(pcop)->r->isFree=0;
+
+       PCOR(pcop)->instance = offset;
+       pcop->type = PCOR(pcop)->r->pc_type;
+       //rs = aop->aopu.aop_reg[offset]->name;
+       //DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
+       return pcop;
+      }
+
+    case AOP_CRY:
+      pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
+      PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
+      //if(PCOR(pcop)->r == NULL)
+      //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
+      return pcop;
+       
+    case AOP_LIT:
+      return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
+
+    case AOP_STR:
+      DEBUGpic16_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
+      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
+      /*
+      pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
+      PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
+      PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
+      pcop->type = PCOR(pcop)->r->pc_type;
+      pcop->name = PCOR(pcop)->r->name;
+
+      return pcop;
+      */
+
+    case AOP_PCODE:
+      DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s",pic16_pCodeOpType(aop->aopu.pcop),
+                         __LINE__, 
+                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
+      pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
+      PCOI(pcop)->offset = offset;
+      return pcop;
+    }
+
+    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+           "pic16_popGet got unsupported aop->type");
+    exit(0);
+}
+/*-----------------------------------------------------------------*/
+/* pic16_aopPut - puts a string for a aop                                */
+/*-----------------------------------------------------------------*/
+void pic16_aopPut (asmop *aop, char *s, int offset)
+{
+    char *d = buffer ;
+    symbol *lbl ;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    if (aop->size && offset > ( aop->size - 1)) {
+        werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+               "pic16_aopPut got offset > aop->size");
+        exit(0);
+    }
+
+    /* will assign value to value */
+    /* depending on where it is ofcourse */
+    switch (aop->type) {
+    case AOP_DIR:
+      if (offset) {
+       sprintf(d,"(%s + %d)",
+               aop->aopu.aop_dir,offset);
+       fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
+
+      } else
+           sprintf(d,"%s",aop->aopu.aop_dir);
+       
+       if (strcmp(d,s)) {
+         DEBUGpic16_emitcode(";","%d",__LINE__);
+         if(strcmp(s,"W"))
+           pic16_emitcode("movf","%s,w",s);
+         pic16_emitcode("movwf","%s",d);
+
+         if(strcmp(s,"W")) {
+           pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
+           if(offset >= aop->size) {
+             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
+             break;
+           } else
+             pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
+         }
+
+         pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
+
+
+       }
+       break;
+       
+    case AOP_REG:
+      if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
+       //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
+         /*
+           if (*s == '@'           ||
+               strcmp(s,"r0") == 0 ||
+               strcmp(s,"r1") == 0 ||
+               strcmp(s,"r2") == 0 ||
+               strcmp(s,"r3") == 0 ||
+               strcmp(s,"r4") == 0 ||
+               strcmp(s,"r5") == 0 ||
+               strcmp(s,"r6") == 0 || 
+               strcmp(s,"r7") == 0 )
+               pic16_emitcode("mov","%s,%s  ; %d",
+                        aop->aopu.aop_reg[offset]->dname,s,__LINE__);
+           else
+         */
+
+         if(strcmp(s,"W")==0 )
+           pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
+
+         pic16_emitcode("movwf","%s",
+                  aop->aopu.aop_reg[offset]->name);
+
+         if(strcmp(s,zero)==0) {
+           pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
+
+         } else if(strcmp(s,"W")==0) {
+           pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
+           pcop->type = PO_GPR_REGISTER;
+
+           PCOR(pcop)->rIdx = -1;
+           PCOR(pcop)->r = NULL;
+
+           DEBUGpic16_emitcode(";","%d",__LINE__);
+           pcop->name = Safe_strdup(s);
+           pic16_emitpcode(POC_MOVFW,pcop);
+           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
+         } else if(strcmp(s,one)==0) {
+           pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
+           pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
+         } else {
+           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
+         }
+       }
+       break;
+       
+    case AOP_DPTR:
+    case AOP_DPTR2:
+    
+    if (aop->type == AOP_DPTR2)
+    {
+        genSetDPTR(1);
+    }
+    
+       if (aop->code) {
+           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+                  "pic16_aopPut writting to code space");
+           exit(0);
+       }
+       
+       while (offset > aop->coff) {
+           aop->coff++;
+           pic16_emitcode ("inc","dptr");
+       }
+       
+       while (offset < aop->coff) {
+           aop->coff-- ;
+           pic16_emitcode("lcall","__decdptr");
+       }
+       
+       aop->coff = offset;
+       
+       /* if not in accumulater */
+       MOVA(s);        
+       
+       pic16_emitcode ("movx","@dptr,a");
+       
+    if (aop->type == AOP_DPTR2)
+    {
+        genSetDPTR(0);
+    }
+       break;
+       
+    case AOP_R0:
+    case AOP_R1:
+       while (offset > aop->coff) {
+           aop->coff++;
+           pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
+       }
+       while (offset < aop->coff) {
+           aop->coff-- ;
+           pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
+       }
+       aop->coff = offset;
+       
+       if (aop->paged) {
+           MOVA(s);           
+           pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
+           
+       } else
+           if (*s == '@') {
+               MOVA(s);
+               pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
+           } else
+               if (strcmp(s,"r0") == 0 ||
+                   strcmp(s,"r1") == 0 ||
+                   strcmp(s,"r2") == 0 ||
+                   strcmp(s,"r3") == 0 ||
+                   strcmp(s,"r4") == 0 ||
+                   strcmp(s,"r5") == 0 ||
+                   strcmp(s,"r6") == 0 || 
+                   strcmp(s,"r7") == 0 ) {
+                   char buffer[10];
+                   sprintf(buffer,"a%s",s);
+                   pic16_emitcode("mov","@%s,%s",
+                            aop->aopu.aop_ptr->name,buffer);
+               } else
+                   pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
+       
+       break;
+       
+    case AOP_STK:
+       if (strcmp(s,"a") == 0)
+           pic16_emitcode("push","acc");
+       else
+           pic16_emitcode("push","%s",s);
+       
+       break;
+       
+    case AOP_CRY:
+       /* if bit variable */
+       if (!aop->aopu.aop_dir) {
+           pic16_emitcode("clr","a");
+           pic16_emitcode("rlc","a");
+       } else {
+           if (s == zero) 
+               pic16_emitcode("clr","%s",aop->aopu.aop_dir);
+           else
+               if (s == one)
+                   pic16_emitcode("setb","%s",aop->aopu.aop_dir);
+               else
+                   if (!strcmp(s,"c"))
+                       pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
+                   else {
+                       lbl = newiTempLabel(NULL);
+                       
+                       if (strcmp(s,"a")) {
+                           MOVA(s);
+                       }
+                       pic16_emitcode("clr","c");
+                       pic16_emitcode("jz","%05d_DS_",lbl->key+100);
+                       pic16_emitcode("cpl","c");
+                       pic16_emitcode("","%05d_DS_:",lbl->key+100);
+                       pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
+                   }
+       }
+       break;
+       
+    case AOP_STR:
+       aop->coff = offset;
+       if (strcmp(aop->aopu.aop_str[offset],s))
+           pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
+       break;
+       
+    case AOP_ACC:
+       aop->coff = offset;
+       if (!offset && (strcmp(s,"acc") == 0))
+           break;
+       
+       if (strcmp(aop->aopu.aop_str[offset],s))
+           pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
+       break;
+
+    default :
+       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+              "pic16_aopPut got unsupported aop->type");
+       exit(0);    
+    }    
+
+}
+
+/*-----------------------------------------------------------------*/
+/* mov2w - generate either a MOVLW or MOVFW based operand type     */
+/*-----------------------------------------------------------------*/
+static void mov2w (asmop *aop, int offset)
+{
+
+  if(!aop)
+    return;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
+
+  if ( aop->type == AOP_PCODE ||
+       aop->type == AOP_LIT )
+    pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
+  else
+    pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
+
+}
+
+/*-----------------------------------------------------------------*/
+/* reAdjustPreg - points a register back to where it should        */
+/*-----------------------------------------------------------------*/
+static void reAdjustPreg (asmop *aop)
+{
+    int size ;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    aop->coff = 0;
+    if ((size = aop->size) <= 1)
+        return ;
+    size-- ;
+    switch (aop->type) {
+        case AOP_R0 :
+        case AOP_R1 :
+            while (size--)
+                pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
+            break;          
+        case AOP_DPTR :
+        case AOP_DPTR2:
+            if (aop->type == AOP_DPTR2)
+           {
+                genSetDPTR(1);
+           } 
+            while (size--)
+            {
+                pic16_emitcode("lcall","__decdptr");
+            }
+                
+           if (aop->type == AOP_DPTR2)
+           {
+                genSetDPTR(0);
+           }                
+            break;  
+
+    }   
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genNotFloat - generates not for float operations              */
+/*-----------------------------------------------------------------*/
+static void genNotFloat (operand *op, operand *res)
+{
+    int size, offset;
+    char *l;
+    symbol *tlbl ;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* we will put 127 in the first byte of 
+    the result */
+    pic16_aopPut(AOP(res),"#127",0);
+    size = AOP_SIZE(op) - 1;
+    offset = 1;
+
+    l = pic16_aopGet(op->aop,offset++,FALSE,FALSE);
+    MOVA(l);    
+
+    while(size--) {
+        pic16_emitcode("orl","a,%s",
+                 pic16_aopGet(op->aop,
+                        offset++,FALSE,FALSE));
+    }
+    tlbl = newiTempLabel(NULL);
+
+    tlbl = newiTempLabel(NULL);
+    pic16_aopPut(res->aop,one,1);
+    pic16_emitcode("jz","%05d_DS_",(tlbl->key+100));
+    pic16_aopPut(res->aop,zero,1);
+    pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
+
+    size = res->aop->size - 2;
+    offset = 2;    
+    /* put zeros in the rest */
+    while (size--) 
+        pic16_aopPut(res->aop,zero,offset++);
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* opIsGptr: returns non-zero if the passed operand is            */   
+/* a generic pointer type.                                        */
+/*-----------------------------------------------------------------*/ 
+static int opIsGptr(operand *op)
+{
+    sym_link *type = operandType(op);
+    
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
+    {
+        return 1;
+    }
+    return 0;        
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* pic16_getDataSize - get the operand data size                         */
+/*-----------------------------------------------------------------*/
+int pic16_getDataSize(operand *op)
+{
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+
+    return AOP_SIZE(op);
+
+    // tsd- in the pic port, the genptr size is 1, so this code here
+    // fails. ( in the 8051 port, the size was 4).
+#if 0
+    int size;
+    size = AOP_SIZE(op);
+    if (size == GPTRSIZE)
+    {
+        sym_link *type = operandType(op);
+        if (IS_GENPTR(type))
+        {
+            /* generic pointer; arithmetic operations
+             * should ignore the high byte (pointer type).
+             */
+            size--;
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+        }
+    }
+    return size;
+#endif
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_outAcc - output Acc                                             */
+/*-----------------------------------------------------------------*/
+void pic16_outAcc(operand *result)
+{
+  int size,offset;
+  DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
+  DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
+
+
+  size = pic16_getDataSize(result);
+  if(size){
+    pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
+    size--;
+    offset = 1;
+    /* unsigned or positive */
+    while(size--)
+      pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_outBitC - output a bit C                                        */
+/*-----------------------------------------------------------------*/
+void pic16_outBitC(operand *result)
+{
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* if the result is bit */
+    if (AOP_TYPE(result) == AOP_CRY) 
+        pic16_aopPut(AOP(result),"c",0);
+    else {
+        pic16_emitcode("clr","a  ; %d", __LINE__);
+        pic16_emitcode("rlc","a");
+        pic16_outAcc(result);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
+/*-----------------------------------------------------------------*/
+void pic16_toBoolean(operand *oper)
+{
+    int size = AOP_SIZE(oper) - 1;
+    int offset = 1;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    if ( AOP_TYPE(oper) != AOP_ACC) {
+      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
+    }
+    while (size--) {
+      pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genNot - generate code for ! operation                          */
+/*-----------------------------------------------------------------*/
+static void genNot (iCode *ic)
+{
+  symbol *tlbl;
+  sym_link *optype = operandType(IC_LEFT(ic));
+  int size;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  /* assign asmOps to operand & result */
+  pic16_aopOp (IC_LEFT(ic),ic,FALSE);
+  pic16_aopOp (IC_RESULT(ic),ic,TRUE);
+
+  DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
+  /* if in bit space then a special case */
+  if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
+    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
+      pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
+      pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+    } else {
+      pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+      pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
+      pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+    }
+    goto release;
+  }
+
+  /* if type float then do float */
+  if (IS_FLOAT(optype)) {
+    genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
+    goto release;
+  }
+
+  size = AOP_SIZE(IC_RESULT(ic));
+  if(size == 1) {
+    pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
+    pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
+    pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+    goto release;
+  }
+  pic16_toBoolean(IC_LEFT(ic));
+
+  tlbl = newiTempLabel(NULL);
+  pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
+  pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+  pic16_outBitC(IC_RESULT(ic));
+
+ release:    
+  /* release the aops */
+  pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
+  pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genCpl - generate code for complement                           */
+/*-----------------------------------------------------------------*/
+static void genCpl (iCode *ic)
+{
+    int offset = 0;
+    int size ;
+
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* assign asmOps to operand & result */
+    pic16_aopOp (IC_LEFT(ic),ic,FALSE);
+    pic16_aopOp (IC_RESULT(ic),ic,TRUE);
+
+    /* if both are in bit space then 
+    a special case */
+    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
+        AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
+
+        pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
+        pic16_emitcode("cpl","c"); 
+        pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
+        goto release; 
+    } 
+
+    size = AOP_SIZE(IC_RESULT(ic));
+    while (size--) {
+        char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
+        MOVA(l);       
+        pic16_emitcode("cpl","a");
+        pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+    }
+
+
+release:
+    /* release the aops */
+    pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
+    pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genUminusFloat - unary minus for floating points                */
+/*-----------------------------------------------------------------*/
+static void genUminusFloat(operand *op,operand *result)
+{
+    int size ,offset =0 ;
+    char *l;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* for this we just need to flip the 
+    first it then copy the rest in place */
+    size = AOP_SIZE(op) - 1;
+    l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
+
+    MOVA(l);    
+
+    pic16_emitcode("cpl","acc.7");
+    pic16_aopPut(AOP(result),"a",3);    
+
+    while(size--) {
+        pic16_aopPut(AOP(result),
+               pic16_aopGet(AOP(op),offset,FALSE,FALSE),
+               offset);
+        offset++;
+    }          
+}
+
+/*-----------------------------------------------------------------*/
+/* genUminus - unary minus code generation                         */
+/*-----------------------------------------------------------------*/
+static void genUminus (iCode *ic)
+{
+  int size, i;
+  sym_link *optype, *rtype;
+
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  /* assign asmops */
+  pic16_aopOp(IC_LEFT(ic),ic,FALSE);
+  pic16_aopOp(IC_RESULT(ic),ic,TRUE);
+
+  /* if both in bit space then special
+     case */
+  if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
+      AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
+
+    pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+    pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
+    pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+    goto release; 
+  } 
+
+  optype = operandType(IC_LEFT(ic));
+  rtype = operandType(IC_RESULT(ic));
+
+  /* if float then do float stuff */
+  if (IS_FLOAT(optype)) {
+    genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
+    goto release;
+  }
+
+  /* otherwise subtract from zero by taking the 2's complement */
+  size = AOP_SIZE(IC_LEFT(ic));
+
+  for(i=0; i<size; i++) {
+    if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
+      pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
+    else {
+      pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
+    }
+  }
+
+  pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
+  for(i=1; i<size; i++) {
+    emitSKPNZ;
+    pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
+  }
+
+ release:
+  /* release the aops */
+  pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
+  pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
+}
+
+/*-----------------------------------------------------------------*/
+/* saveRegisters - will look for a call and save the registers     */
+/*-----------------------------------------------------------------*/
+static void saveRegisters(iCode *lic) 
+{
+    int i;
+    iCode *ic;
+    bitVect *rsave;
+    sym_link *dtype;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* look for call */
+    for (ic = lic ; ic ; ic = ic->next) 
+        if (ic->op == CALL || ic->op == PCALL)
+            break;
+
+    if (!ic) {
+        fprintf(stderr,"found parameter push with no function call\n");
+        return ;
+    }
+
+    /* if the registers have been saved already then
+    do nothing */
+    if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
+        return ;
+
+    /* find the registers in use at this time 
+    and push them away to safety */
+    rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
+                          ic->rUsed);
+
+    ic->regsSaved = 1;
+    if (options.useXstack) {
+       if (bitVectBitValue(rsave,R0_IDX))
+           pic16_emitcode("mov","b,r0");
+       pic16_emitcode("mov","r0,%s",spname);
+       for (i = 0 ; i < pic16_nRegs ; i++) {
+           if (bitVectBitValue(rsave,i)) {
+               if (i == R0_IDX)
+                   pic16_emitcode("mov","a,b");
+               else
+                   pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
+               pic16_emitcode("movx","@r0,a");
+               pic16_emitcode("inc","r0");
+           }
+       }
+       pic16_emitcode("mov","%s,r0",spname);
+       if (bitVectBitValue(rsave,R0_IDX))
+           pic16_emitcode("mov","r0,b");           
+    }// else
+    //for (i = 0 ; i < pic16_nRegs ; i++) {
+    //    if (bitVectBitValue(rsave,i))
+    // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
+    //}
+
+    dtype = operandType(IC_LEFT(ic));
+    if (currFunc && dtype && 
+        (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
+       IFFUNC_ISISR(currFunc->type) &&
+        !ic->bankSaved) 
+
+        saverbank(FUNC_REGBANK(dtype),ic,TRUE);
+
+}
+/*-----------------------------------------------------------------*/
+/* unsaveRegisters - pop the pushed registers                      */
+/*-----------------------------------------------------------------*/
+static void unsaveRegisters (iCode *ic)
+{
+    int i;
+    bitVect *rsave;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* find the registers in use at this time 
+    and push them away to safety */
+    rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
+                          ic->rUsed);
+    
+    if (options.useXstack) {
+       pic16_emitcode("mov","r0,%s",spname);   
+       for (i =  pic16_nRegs ; i >= 0 ; i--) {
+           if (bitVectBitValue(rsave,i)) {
+               pic16_emitcode("dec","r0");
+               pic16_emitcode("movx","a,@r0");
+               if (i == R0_IDX)
+                   pic16_emitcode("mov","b,a");
+               else
+                   pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
+           }       
+
+       }
+       pic16_emitcode("mov","%s,r0",spname);
+       if (bitVectBitValue(rsave,R0_IDX))
+           pic16_emitcode("mov","r0,b");
+    } //else
+    //for (i =  pic16_nRegs ; i >= 0 ; i--) {
+    //    if (bitVectBitValue(rsave,i))
+    // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
+    //}
+
+}  
+
+
+/*-----------------------------------------------------------------*/
+/* pushSide -                                                     */
+/*-----------------------------------------------------------------*/
+static void pushSide(operand * oper, int size)
+{
+#if 0
+       int offset = 0;
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+       while (size--) {
+               char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
+               if (AOP_TYPE(oper) != AOP_REG &&
+                   AOP_TYPE(oper) != AOP_DIR &&
+                   strcmp(l,"a") ) {
+                       pic16_emitcode("mov","a,%s",l);
+                       pic16_emitcode("push","acc");
+               } else
+                       pic16_emitcode("push","%s",l);
+       }
+#endif
+}
+
+/*-----------------------------------------------------------------*/
+/* assignResultValue -                                            */
+/*-----------------------------------------------------------------*/
+static void assignResultValue(operand * oper)
+{
+  int size = AOP_SIZE(oper);
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
+
+  if(!GpsuedoStkPtr) {
+    /* The last byte in the assignment is in W */
+    size--;
+    pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
+    GpsuedoStkPtr++;
+  }
+
+  while (size--) {
+    pic16_emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
+    GpsuedoStkPtr++;
+    pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
+  }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genIpush - genrate code for pushing this gets a little complex  */
+/*-----------------------------------------------------------------*/
+static void genIpush (iCode *ic)
+{
+
+  DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
+#if 0
+    int size, offset = 0 ;
+    char *l;
+
+
+    /* if this is not a parm push : ie. it is spill push 
+    and spill push is always done on the local stack */
+    if (!ic->parmPush) {
+
+        /* and the item is spilt then do nothing */
+        if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
+            return ;
+
+        pic16_aopOp(IC_LEFT(ic),ic,FALSE);
+        size = AOP_SIZE(IC_LEFT(ic));
+        /* push it on the stack */
+        while(size--) {
+            l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
+            if (*l == '#') {
+                MOVA(l);
+                l = "acc";
+            }
+            pic16_emitcode("push","%s",l);
+        }
+        return ;        
+    }
+
+    /* this is a paramter push: in this case we call
+    the routine to find the call and save those
+    registers that need to be saved */   
+    saveRegisters(ic);
+
+    /* then do the push */
+    pic16_aopOp(IC_LEFT(ic),ic,FALSE);
+
+
+       // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
+    size = AOP_SIZE(IC_LEFT(ic));
+
+    while (size--) {
+        l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
+        if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
+            AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
+            strcmp(l,"a") ) {
+            pic16_emitcode("mov","a,%s",l);
+            pic16_emitcode("push","acc");
+        } else
+            pic16_emitcode("push","%s",l);
+    }       
+
+    pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
+#endif
+}
+
+/*-----------------------------------------------------------------*/
+/* genIpop - recover the registers: can happen only for spilling   */
+/*-----------------------------------------------------------------*/
+static void genIpop (iCode *ic)
+{
+  DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
+#if 0
+    int size,offset ;
+
+
+    /* if the temp was not pushed then */
+    if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
+        return ;
+
+    pic16_aopOp(IC_LEFT(ic),ic,FALSE);
+    size = AOP_SIZE(IC_LEFT(ic));
+    offset = (size-1);
+    while (size--) 
+        pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
+                                   FALSE,TRUE));
+
+    pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
+#endif
+}
+
+/*-----------------------------------------------------------------*/
+/* unsaverbank - restores the resgister bank from stack            */
+/*-----------------------------------------------------------------*/
+static void unsaverbank (int bank,iCode *ic,bool popPsw)
+{
+  DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
+#if 0
+    int i;
+    asmop *aop ;
+    regs *r = NULL;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if (popPsw) {
+       if (options.useXstack) {
+           aop = newAsmop(0);
+           r = getFreePtr(ic,&aop,FALSE);
+           
+           
+           pic16_emitcode("mov","%s,_spx",r->name);
+           pic16_emitcode("movx","a,@%s",r->name);
+           pic16_emitcode("mov","psw,a");
+           pic16_emitcode("dec","%s",r->name);
+           
+       }else
+           pic16_emitcode ("pop","psw");
+    }
+
+    for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
+        if (options.useXstack) {       
+            pic16_emitcode("movx","a,@%s",r->name);
+            //pic16_emitcode("mov","(%s+%d),a",
+           //       regspic16[i].base,8*bank+regspic16[i].offset);
+            pic16_emitcode("dec","%s",r->name);
+
+        } else 
+         pic16_emitcode("pop",""); //"(%s+%d)",
+       //regspic16[i].base,8*bank); //+regspic16[i].offset);
+    }
+
+    if (options.useXstack) {
+
+       pic16_emitcode("mov","_spx,%s",r->name);
+       pic16_freeAsmop(NULL,aop,ic,TRUE);
+
+    }
+#endif 
+}
+
+/*-----------------------------------------------------------------*/
+/* saverbank - saves an entire register bank on the stack          */
+/*-----------------------------------------------------------------*/
+static void saverbank (int bank, iCode *ic, bool pushPsw)
+{
+  DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
+#if 0
+    int i;
+    asmop *aop ;
+    regs *r = NULL;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if (options.useXstack) {
+
+       aop = newAsmop(0);
+       r = getFreePtr(ic,&aop,FALSE);  
+       pic16_emitcode("mov","%s,_spx",r->name);
+
+    }
+
+    for (i = 0 ; i < pic16_nRegs ;i++) {
+        if (options.useXstack) {
+            pic16_emitcode("inc","%s",r->name);
+            //pic16_emitcode("mov","a,(%s+%d)",
+            //         regspic16[i].base,8*bank+regspic16[i].offset);
+            pic16_emitcode("movx","@%s,a",r->name);           
+        } else 
+         pic16_emitcode("push","");// "(%s+%d)",
+                     //regspic16[i].base,8*bank+regspic16[i].offset);
+    }
+    
+    if (pushPsw) {
+       if (options.useXstack) {
+           pic16_emitcode("mov","a,psw");
+           pic16_emitcode("movx","@%s,a",r->name);     
+           pic16_emitcode("inc","%s",r->name);
+           pic16_emitcode("mov","_spx,%s",r->name);       
+           pic16_freeAsmop (NULL,aop,ic,TRUE);
+           
+       } else
+           pic16_emitcode("push","psw");
+       
+       pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
+    }
+    ic->bankSaved = 1;
+#endif
+}
+
+/*-----------------------------------------------------------------*/
+/* genCall - generates a call statement                            */
+/*-----------------------------------------------------------------*/
+static void genCall (iCode *ic)
+{
+  sym_link *dtype;   
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  /* if caller saves & we have not saved then */
+  if (!ic->regsSaved)
+    saveRegisters(ic);
+
+  /* if we are calling a function that is not using
+     the same register bank then we need to save the
+     destination registers on the stack */
+  dtype = operandType(IC_LEFT(ic));
+  if (currFunc && dtype && 
+      (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
+      IFFUNC_ISISR(currFunc->type) &&
+      !ic->bankSaved) 
+
+    saverbank(FUNC_REGBANK(dtype),ic,TRUE);
+
+  /* if send set is not empty the assign */
+  if (_G.sendSet) {
+    iCode *sic;
+    /* For the Pic port, there is no data stack.
+     * So parameters passed to functions are stored
+     * in registers. (The pCode optimizer will get
+     * rid of most of these :).
+     */
+    int psuedoStkPtr=-1; 
+    int firstTimeThruLoop = 1;
+
+    _G.sendSet = reverseSet(_G.sendSet);
+
+    /* First figure how many parameters are getting passed */
+    for (sic = setFirstItem(_G.sendSet) ; sic ; 
+        sic = setNextItem(_G.sendSet)) {
+
+      pic16_aopOp(IC_LEFT(sic),sic,FALSE);
+      psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
+      pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
+    }
+
+    for (sic = setFirstItem(_G.sendSet) ; sic ; 
+        sic = setNextItem(_G.sendSet)) {
+      int size, offset = 0;
+
+      pic16_aopOp(IC_LEFT(sic),sic,FALSE);
+      size = AOP_SIZE(IC_LEFT(sic));
+
+      while (size--) {
+       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
+                            pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
+
+       if(!firstTimeThruLoop) {
+         /* If this is not the first time we've been through the loop
+          * then we need to save the parameter in a temporary
+          * register. The last byte of the last parameter is
+          * passed in W. */
+         pic16_emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
+
+       }
+       firstTimeThruLoop=0;
+
+       //if (strcmp(l,fReturn[offset])) {
+       mov2w (AOP(IC_LEFT(sic)),  offset);
+/*
+       if ( ((AOP(IC_LEFT(sic))->type) == AOP_PCODE) ||
+            ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
+         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(sic)),offset));
+       else
+         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(IC_LEFT(sic)),offset));
+*/
+       //}
+       offset++;
+      }
+      pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
+    }
+    _G.sendSet = NULL;
+  }
+  /* make the call */
+  pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
+                                     OP_SYMBOL(IC_LEFT(ic))->rname :
+                                     OP_SYMBOL(IC_LEFT(ic))->name));
+
+  GpsuedoStkPtr=0;
+  /* if we need assign a result value */
+  if ((IS_ITEMP(IC_RESULT(ic)) && 
+       (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
+       OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
+      IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
+
+    _G.accInUse++;
+    pic16_aopOp(IC_RESULT(ic),ic,FALSE);
+    _G.accInUse--;
+
+    assignResultValue(IC_RESULT(ic));
+
+    DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
+                        pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
+               
+    pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
+  }
+
+  /* adjust the stack for parameters if 
+     required */
+  if (ic->parmBytes) {
+    int i;
+    if (ic->parmBytes > 3) {
+      pic16_emitcode("mov","a,%s",spname);
+      pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
+      pic16_emitcode("mov","%s,a",spname);
+    } else 
+      for ( i = 0 ; i <  ic->parmBytes ;i++)
+       pic16_emitcode("dec","%s",spname);
+
+  }
+
+  /* if register bank was saved then pop them */
+  if (ic->bankSaved)
+    unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
+
+  /* if we hade saved some registers then unsave them */
+  if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
+    unsaveRegisters (ic);
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genPcall - generates a call by pointer statement                */
+/*-----------------------------------------------------------------*/
+static void genPcall (iCode *ic)
+{
+    sym_link *dtype;
+    symbol *rlbl = newiTempLabel(NULL);
+
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* if caller saves & we have not saved then */
+    if (!ic->regsSaved)
+        saveRegisters(ic);
+
+    /* if we are calling a function that is not using
+    the same register bank then we need to save the
+    destination registers on the stack */
+    dtype = operandType(IC_LEFT(ic));
+    if (currFunc && dtype && 
+       IFFUNC_ISISR(currFunc->type) &&
+        (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
+        saverbank(FUNC_REGBANK(dtype),ic,TRUE);
+
+
+    /* push the return address on to the stack */
+    pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
+    pic16_emitcode("push","acc");    
+    pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
+    pic16_emitcode("push","acc");
+    
+    if (options.model == MODEL_FLAT24)
+    {
+       pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
+       pic16_emitcode("push","acc");    
+    }
+
+    /* now push the calling address */
+    pic16_aopOp(IC_LEFT(ic),ic,FALSE);
+
+    pushSide(IC_LEFT(ic), FPTRSIZE);
+
+    pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
+
+    /* if send set is not empty the assign */
+    if (_G.sendSet) {
+       iCode *sic ;
+
+       for (sic = setFirstItem(_G.sendSet) ; sic ; 
+            sic = setNextItem(_G.sendSet)) {
+           int size, offset = 0;
+           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
+           size = AOP_SIZE(IC_LEFT(sic));
+           while (size--) {
+               char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
+                               FALSE,FALSE);
+               if (strcmp(l,fReturn[offset]))
+                   pic16_emitcode("mov","%s,%s",
+                            fReturn[offset],
+                            l);
+               offset++;
+           }
+           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
+       }
+       _G.sendSet = NULL;
+    }
+
+    pic16_emitcode("ret","");
+    pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
+
+
+    /* if we need assign a result value */
+    if ((IS_ITEMP(IC_RESULT(ic)) &&
+         (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
+          OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
+        IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
+
+        _G.accInUse++;
+        pic16_aopOp(IC_RESULT(ic),ic,FALSE);
+        _G.accInUse--;
+       
+       assignResultValue(IC_RESULT(ic));
+
+        pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+    }
+
+    /* adjust the stack for parameters if 
+    required */
+    if (ic->parmBytes) {
+        int i;
+        if (ic->parmBytes > 3) {
+            pic16_emitcode("mov","a,%s",spname);
+            pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
+            pic16_emitcode("mov","%s,a",spname);
+        } else 
+            for ( i = 0 ; i <  ic->parmBytes ;i++)
+                pic16_emitcode("dec","%s",spname);
+
+    }
+
+    /* if register bank was saved then unsave them */
+    if (currFunc && dtype && 
+        (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
+        unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
+
+    /* if we hade saved some registers then
+    unsave them */
+    if (ic->regsSaved)
+        unsaveRegisters (ic);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* resultRemat - result  is rematerializable                       */
+/*-----------------------------------------------------------------*/
+static int resultRemat (iCode *ic)
+{
+  //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  if (SKIP_IC(ic) || ic->op == IFX)
+    return 0;
+
+  if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
+    symbol *sym = OP_SYMBOL(IC_RESULT(ic));
+    if (sym->remat && !POINTER_SET(ic)) 
+      return 1;
+  }
+
+  return 0;
+}
+
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
+#endif
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* inExcludeList - return 1 if the string is in exclude Reg list   */
+/*-----------------------------------------------------------------*/
+static bool inExcludeList(char *s)
+{
+  DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
+    int i =0;
+    
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if (options.excludeRegs[i] &&
+    STRCASECMP(options.excludeRegs[i],"none") == 0)
+       return FALSE ;
+
+    for ( i = 0 ; options.excludeRegs[i]; i++) {
+       if (options.excludeRegs[i] &&
+        STRCASECMP(s,options.excludeRegs[i]) == 0)
+           return TRUE;
+    }
+    return FALSE ;
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* genFunction - generated code for function entry                 */
+/*-----------------------------------------------------------------*/
+static void genFunction (iCode *ic)
+{
+    symbol *sym;
+    sym_link *ftype;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
+
+    labelOffset += (max_key+4);
+    max_key=0;
+    GpsuedoStkPtr=0;
+    _G.nRegsSaved = 0;
+    /* create the function header */
+    pic16_emitcode(";","-----------------------------------------");
+    pic16_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
+    pic16_emitcode(";","-----------------------------------------");
+
+    pic16_emitcode("","%s:",sym->rname);
+    pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,sym->rname));
+
+    ftype = operandType(IC_LEFT(ic));
+
+    /* if critical function then turn interrupts off */
+    if (IFFUNC_ISCRITICAL(ftype))
+        pic16_emitcode("clr","ea");
+
+    /* here we need to generate the equates for the
+       register bank if required */
+#if 0
+    if (FUNC_REGBANK(ftype) != rbank) {
+        int i ;
+
+        rbank = FUNC_REGBANK(ftype);
+        for ( i = 0 ; i < pic16_nRegs ; i++ ) {
+            if (strcmp(regspic16[i].base,"0") == 0)
+                pic16_emitcode("","%s = 0x%02x",
+                         regspic16[i].dname,
+                         8*rbank+regspic16[i].offset);
+            else
+                pic16_emitcode ("","%s = %s + 0x%02x",
+                          regspic16[i].dname,
+                          regspic16[i].base,
+                          8*rbank+regspic16[i].offset);
+        }
+    }
+#endif
+
+    /* if this is an interrupt service routine then
+    save acc, b, dpl, dph  */
+    if (IFFUNC_ISISR(sym->type)) {
+      pic16_addpCode2pBlock(pb,pic16_newpCode(POC_BRA,pic16_newpCodeOp("END_OF_INTERRUPT+2",PO_STR)));
+      pic16_emitpcodeNULLop(POC_NOP);
+      pic16_emitpcodeNULLop(POC_NOP);
+      pic16_emitpcodeNULLop(POC_NOP);
+      pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_wsave));
+      pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_status));
+      pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
+      pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_ssave));
+
+      pic16_pBlockConvert2ISR(pb);
+#if 0  
+       if (!inExcludeList("acc"))          
+           pic16_emitcode ("push","acc");      
+       if (!inExcludeList("b"))
+           pic16_emitcode ("push","b");
+       if (!inExcludeList("dpl"))
+           pic16_emitcode ("push","dpl");
+       if (!inExcludeList("dph"))
+           pic16_emitcode ("push","dph");
+       if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
+       {
+           pic16_emitcode ("push", "dpx");
+           /* Make sure we're using standard DPTR */
+           pic16_emitcode ("push", "dps");
+           pic16_emitcode ("mov", "dps, #0x00");
+           if (options.stack10bit)
+           {   
+               /* This ISR could conceivably use DPTR2. Better save it. */
+               pic16_emitcode ("push", "dpl1");
+               pic16_emitcode ("push", "dph1");
+               pic16_emitcode ("push", "dpx1");
+           }
+       }
+       /* if this isr has no bank i.e. is going to
+          run with bank 0 , then we need to save more
+          registers :-) */
+       if (!FUNC_REGBANK(sym->type)) {
+
+           /* if this function does not call any other
+              function then we can be economical and
+              save only those registers that are used */
+           if (! IFFUNC_HASFCALL(sym->type)) {
+               int i;
+
+               /* if any registers used */
+               if (sym->regsUsed) {
+                   /* save the registers used */
+                   for ( i = 0 ; i < sym->regsUsed->size ; i++) {
+                       if (bitVectBitValue(sym->regsUsed,i) ||
+                          (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
+                         pic16_emitcode("push","junk");//"%s",pic16_regWithIdx(i)->dname);                         
+                   }
+               }
+               
+           } else {
+               /* this function has  a function call cannot
+                  determines register usage so we will have the
+                  entire bank */
+               saverbank(0,ic,FALSE);
+           }       
+       }
+#endif
+    } else {
+       /* if callee-save to be used for this function
+          then save the registers being used in this function */
+       if (IFFUNC_CALLEESAVES(sym->type)) {
+           int i;
+           
+           /* if any registers used */
+           if (sym->regsUsed) {
+               /* save the registers used */
+               for ( i = 0 ; i < sym->regsUsed->size ; i++) {
+                   if (bitVectBitValue(sym->regsUsed,i) ||
+                      (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
+                     //pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
+                       _G.nRegsSaved++;
+                   }
+               }
+           }
+       }
+    }
+
+    /* set the register bank to the desired value */
+    if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
+        pic16_emitcode("push","psw");
+        pic16_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
+    }
+
+    if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
+
+       if (options.useXstack) {
+           pic16_emitcode("mov","r0,%s",spname);
+           pic16_emitcode("mov","a,_bp");
+           pic16_emitcode("movx","@r0,a");
+           pic16_emitcode("inc","%s",spname);
+       }
+       else
+       {
+           /* set up the stack */
+           pic16_emitcode ("push","_bp");     /* save the callers stack  */
+       }
+       pic16_emitcode ("mov","_bp,%s",spname);
+    }
+
+    /* adjust the stack for the function */
+    if (sym->stack) {
+
+       int i = sym->stack;
+       if (i > 256 ) 
+           werror(W_STACK_OVERFLOW,sym->name);
+
+       if (i > 3 && sym->recvSize < 4) {              
+
+           pic16_emitcode ("mov","a,sp");
+           pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
+           pic16_emitcode ("mov","sp,a");
+          
+       }
+       else
+           while(i--)
+               pic16_emitcode("inc","sp");
+    }
+
+     if (sym->xstack) {
+
+       pic16_emitcode ("mov","a,_spx");
+       pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
+       pic16_emitcode ("mov","_spx,a");
+    }    
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndFunction - generates epilogue for functions               */
+/*-----------------------------------------------------------------*/
+static void genEndFunction (iCode *ic)
+{
+    symbol *sym = OP_SYMBOL(IC_LEFT(ic));
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
+    {
+        pic16_emitcode ("mov","%s,_bp",spname);
+    }
+
+    /* if use external stack but some variables were
+    added to the local stack then decrement the
+    local stack */
+    if (options.useXstack && sym->stack) {      
+        pic16_emitcode("mov","a,sp");
+        pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
+        pic16_emitcode("mov","sp,a");
+    }
+
+
+    if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
+       if (options.useXstack) {
+           pic16_emitcode("mov","r0,%s",spname);
+           pic16_emitcode("movx","a,@r0");
+           pic16_emitcode("mov","_bp,a");
+           pic16_emitcode("dec","%s",spname);
+       }
+       else
+       {
+           pic16_emitcode ("pop","_bp");
+       }
+    }
+
+    /* restore the register bank  */    
+    if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
+        pic16_emitcode ("pop","psw");
+
+    if (IFFUNC_ISISR(sym->type)) {
+
+       /* now we need to restore the registers */
+       /* if this isr has no bank i.e. is going to
+          run with bank 0 , then we need to save more
+          registers :-) */
+       if (!FUNC_REGBANK(sym->type)) {
+           
+           /* if this function does not call any other
+              function then we can be economical and
+              save only those registers that are used */
+           if (! IFFUNC_HASFCALL(sym->type)) {
+               int i;
+               
+               /* if any registers used */
+               if (sym->regsUsed) {
+                   /* save the registers used */
+                   for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
+                       if (bitVectBitValue(sym->regsUsed,i) ||
+                          (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
+                         pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
+                   }
+               }
+               
+           } else {
+               /* this function has  a function call cannot
+                  determines register usage so we will have the
+                  entire bank */
+               unsaverbank(0,ic,FALSE);
+           }       
+       }
+#if 0
+       if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
+       {
+           if (options.stack10bit)
+           {
+               pic16_emitcode ("pop", "dpx1");
+               pic16_emitcode ("pop", "dph1");
+               pic16_emitcode ("pop", "dpl1");
+           }   
+           pic16_emitcode ("pop", "dps");
+           pic16_emitcode ("pop", "dpx");
+       }
+       if (!inExcludeList("dph"))
+           pic16_emitcode ("pop","dph");
+       if (!inExcludeList("dpl"))
+           pic16_emitcode ("pop","dpl");
+       if (!inExcludeList("b"))
+           pic16_emitcode ("pop","b");
+       if (!inExcludeList("acc"))
+           pic16_emitcode ("pop","acc");
+
+        if (IFFUNC_ISCRITICAL(sym->type))
+            pic16_emitcode("setb","ea");
+#endif
+
+       /* if debug then send end of function */
+/*     if (options.debug && currFunc) { */
+       if (currFunc) {
+           _G.debugLine = 1;
+           pic16_emitcode(";","C$%s$%d$%d$%d ==.",
+                    FileBaseName(ic->filename),currFunc->lastLine,
+                    ic->level,ic->block); 
+           if (IS_STATIC(currFunc->etype))         
+               pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
+           else
+               pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
+           _G.debugLine = 0;
+       }
+       
+        pic16_emitcode ("reti","");
+
+       pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
+       pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
+       pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
+       pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
+       pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
+       pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("END_OF_INTERRUPT",-1));
+
+       pic16_emitpcodeNULLop(POC_RETFIE);
+
+    }
+    else {
+        if (IFFUNC_ISCRITICAL(sym->type))
+            pic16_emitcode("setb","ea");
+       
+       if (IFFUNC_CALLEESAVES(sym->type)) {
+           int i;
+           
+           /* if any registers used */
+           if (sym->regsUsed) {
+               /* save the registers used */
+               for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
+                   if (bitVectBitValue(sym->regsUsed,i) ||
+                      (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
+                     pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
+               }
+           }
+           
+       }
+
+       /* if debug then send end of function */
+       if (currFunc) {
+           _G.debugLine = 1;
+           pic16_emitcode(";","C$%s$%d$%d$%d ==.",
+                    FileBaseName(ic->filename),currFunc->lastLine,
+                    ic->level,ic->block); 
+           if (IS_STATIC(currFunc->etype))         
+               pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
+           else
+               pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
+           _G.debugLine = 0;
+       }
+
+        pic16_emitcode ("return","");
+       pic16_emitpcodeNULLop(POC_RETURN);
+
+       /* Mark the end of a function */
+       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genRet - generate code for return statement                     */
+/*-----------------------------------------------------------------*/
+static void genRet (iCode *ic)
+{
+  int size,offset = 0 , pushed = 0;
+    
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  /* if we have no return value then
+     just generate the "ret" */
+  if (!IC_LEFT(ic)) 
+    goto jumpret;       
+    
+  /* we have something to return then
+     move the return value into place */
+  pic16_aopOp(IC_LEFT(ic),ic,FALSE);
+  size = AOP_SIZE(IC_LEFT(ic));
+    
+  while (size--) {
+    char *l ;
+    if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
+      /* #NOCHANGE */
+      l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,
+                FALSE,TRUE);
+      pic16_emitcode("push","%s",l);
+      pushed++;
+    } else {
+      l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,
+                FALSE,FALSE);
+      if (strcmp(fReturn[offset],l)) {
+       if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
+           ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
+         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
+       }else {
+         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
+       }
+       if(size) {
+         pic16_emitpcode(POC_MOVWF,popRegFromIdx(offset + pic16_Gstack_base_addr));
+       }
+       offset++;
+      }
+    }
+  }    
+
+  if (pushed) {
+    while(pushed) {
+      pushed--;
+      if (strcmp(fReturn[pushed],"a"))
+       pic16_emitcode("pop",fReturn[pushed]);
+      else
+       pic16_emitcode("pop","acc");
+    }
+  }
+  pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
+    
+ jumpret:
+  /* generate a jump to the return label
+     if the next is not the return statement */
+  if (!(ic->next && ic->next->op == LABEL &&
+       IC_LABEL(ic->next) == returnLabel)) {
+       
+    pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
+    pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
+  }
+    
+}
+
+/*-----------------------------------------------------------------*/
+/* genLabel - generates a label                                    */
+/*-----------------------------------------------------------------*/
+static void genLabel (iCode *ic)
+{
+    /* special case never generate */
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if (IC_LABEL(ic) == entryLabel)
+        return ;
+
+    pic16_emitpLabel(IC_LABEL(ic)->key);
+    pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
+}
+
+/*-----------------------------------------------------------------*/
+/* genGoto - generates a goto                                      */
+/*-----------------------------------------------------------------*/
+//tsd
+static void genGoto (iCode *ic)
+{
+  pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
+  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genMultbits :- multiplication of bits                           */
+/*-----------------------------------------------------------------*/
+static void genMultbits (operand *left, 
+                         operand *right, 
+                         operand *result)
+{
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  if(!pic16_sameRegs(AOP(result),AOP(right)))
+    pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
+
+  pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
+  pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
+  pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genMultOneByte : 8 bit multiplication & division                */
+/*-----------------------------------------------------------------*/
+static void genMultOneByte (operand *left,
+                            operand *right,
+                            operand *result)
+{
+  sym_link *opetype = operandType(result);
+
+  // symbol *lbl ;
+  int size,offset;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
+  DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
+
+  /* (if two literals, the value is computed before) */
+  /* if one literal, literal on the right */
+  if (AOP_TYPE(left) == AOP_LIT){
+    operand *t = right;
+    right = left;
+    left = t;
+  }
+
+  size = AOP_SIZE(result);
+  if(size == 1) {
+
+    if (AOP_TYPE(right) == AOP_LIT){
+      pic16_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
+                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
+                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
+                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
+      pic16_emitcode("call","genMultLit");
+    } else {
+      pic16_emitcode("multiply ","variable :%s by variable %s and store in %s", 
+                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
+                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
+                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
+      pic16_emitcode("call","pic16_genMult8X8_8");
+
+    }
+    pic16_genMult8X8_8 (left, right,result);
+
+
+    /* signed or unsigned */
+    //pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
+    //l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
+    //MOVA(l);       
+    //pic16_emitcode("mul","ab");
+    /* if result size = 1, mul signed = mul unsigned */
+    //pic16_aopPut(AOP(result),"a",0);
+
+  } else {  // (size > 1)
+
+    pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
+                  pic16_aopGet(AOP(right),0,FALSE,FALSE), 
+                  pic16_aopGet(AOP(left),0,FALSE,FALSE), 
+                  pic16_aopGet(AOP(result),0,FALSE,FALSE));
+
+    if (SPEC_USIGN(opetype)){
+      pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
+      pic16_genUMult8X8_16 (left, right, result, NULL);
+
+      if (size > 2) {
+       /* for filling the MSBs */
+       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
+       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
+      }
+    }
+    else{
+      pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
+
+      pic16_emitcode("mov","a,b");
+
+      /* adjust the MSB if left or right neg */
+
+      /* if one literal */
+      if (AOP_TYPE(right) == AOP_LIT){
+       pic16_emitcode("multiply ","right is a lit");
+       /* AND literal negative */
+       if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
+         /* adjust MSB (c==0 after mul) */
+         pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
+       }
+      }
+      else{
+       pic16_genSMult8X8_16 (left, right, result, NULL);
+      }
+
+      if(size > 2){
+       pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
+       /* get the sign */
+       pic16_emitcode("rlc","a");
+       pic16_emitcode("subb","a,acc");
+      }
+    }
+
+    size -= 2;   
+    offset = 2;
+    if (size > 0)
+      while (size--)
+       pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
+    //pic16_aopPut(AOP(result),"a",offset++);
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* genMult - generates code for multiplication                     */
+/*-----------------------------------------------------------------*/
+static void genMult (iCode *ic)
+{
+    operand *left = IC_LEFT(ic);
+    operand *right = IC_RIGHT(ic);
+    operand *result= IC_RESULT(ic);   
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* assign the amsops */
+    pic16_aopOp (left,ic,FALSE);
+    pic16_aopOp (right,ic,FALSE);
+    pic16_aopOp (result,ic,TRUE);
+
+  DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
+
+    /* special cases first */
+    /* both are bits */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        AOP_TYPE(right)== AOP_CRY) {
+        genMultbits(left,right,result);
+        goto release ;
+    }
+
+    /* if both are of size == 1 */
+    if (AOP_SIZE(left) == 1 &&
+        AOP_SIZE(right) == 1 ) {
+        genMultOneByte(left,right,result);
+        goto release ;
+    }
+
+    pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
+
+    /* should have been converted to function call */
+    //assert(0) ;
+
+release :
+    pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(result,NULL,ic,TRUE); 
+}
+
+/*-----------------------------------------------------------------*/
+/* genDivbits :- division of bits                                  */
+/*-----------------------------------------------------------------*/
+static void genDivbits (operand *left, 
+                        operand *right, 
+                        operand *result)
+{
+
+    char *l;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* the result must be bit */    
+    pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
+    l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
+
+    MOVA(l);    
+
+    pic16_emitcode("div","ab");
+    pic16_emitcode("rrc","a");
+    pic16_aopPut(AOP(result),"c",0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genDivOneByte : 8 bit division                                  */
+/*-----------------------------------------------------------------*/
+static void genDivOneByte (operand *left,
+                           operand *right,
+                           operand *result)
+{
+    sym_link *opetype = operandType(result);
+    char *l ;
+    symbol *lbl ;
+    int size,offset;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    size = AOP_SIZE(result) - 1;
+    offset = 1;
+    /* signed or unsigned */
+    if (SPEC_USIGN(opetype)) {
+        /* unsigned is easy */
+        pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
+        l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
+        MOVA(l);        
+        pic16_emitcode("div","ab");
+        pic16_aopPut(AOP(result),"a",0);
+        while (size--)
+            pic16_aopPut(AOP(result),zero,offset++);
+        return ;
+    }
+
+    /* signed is a little bit more difficult */
+
+    /* save the signs of the operands */
+    l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
+    MOVA(l);    
+    pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
+    pic16_emitcode("push","acc"); /* save it on the stack */
+
+    /* now sign adjust for both left & right */
+    l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
+    MOVA(l);       
+    lbl = newiTempLabel(NULL);
+    pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
+    pic16_emitcode("cpl","a");   
+    pic16_emitcode("inc","a");
+    pic16_emitcode("","%05d_DS_:",(lbl->key+100));
+    pic16_emitcode("mov","b,a");
+
+    /* sign adjust left side */
+    l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
+    MOVA(l);
+
+    lbl = newiTempLabel(NULL);
+    pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
+    pic16_emitcode("cpl","a");
+    pic16_emitcode("inc","a");
+    pic16_emitcode("","%05d_DS_:",(lbl->key+100));
+
+    /* now the division */
+    pic16_emitcode("div","ab");
+    /* we are interested in the lower order
+    only */
+    pic16_emitcode("mov","b,a");
+    lbl = newiTempLabel(NULL);
+    pic16_emitcode("pop","acc");   
+    /* if there was an over flow we don't 
+    adjust the sign of the result */
+    pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
+    pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
+    CLRC;
+    pic16_emitcode("clr","a");
+    pic16_emitcode("subb","a,b");
+    pic16_emitcode("mov","b,a");
+    pic16_emitcode("","%05d_DS_:",(lbl->key+100));
+
+    /* now we are done */
+    pic16_aopPut(AOP(result),"b",0);
+    if(size > 0){
+        pic16_emitcode("mov","c,b.7");
+        pic16_emitcode("subb","a,acc");   
+    }
+    while (size--)
+        pic16_aopPut(AOP(result),"a",offset++);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genDiv - generates code for division                            */
+/*-----------------------------------------------------------------*/
+static void genDiv (iCode *ic)
+{
+    operand *left = IC_LEFT(ic);
+    operand *right = IC_RIGHT(ic);
+    operand *result= IC_RESULT(ic);   
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* assign the amsops */
+    pic16_aopOp (left,ic,FALSE);
+    pic16_aopOp (right,ic,FALSE);
+    pic16_aopOp (result,ic,TRUE);
+
+    /* special cases first */
+    /* both are bits */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        AOP_TYPE(right)== AOP_CRY) {
+        genDivbits(left,right,result);
+        goto release ;
+    }
+
+    /* if both are of size == 1 */
+    if (AOP_SIZE(left) == 1 &&
+        AOP_SIZE(right) == 1 ) {
+        genDivOneByte(left,right,result);
+        goto release ;
+    }
+
+    /* should have been converted to function call */
+    assert(0);
+release :
+    pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(result,NULL,ic,TRUE); 
+}
+
+/*-----------------------------------------------------------------*/
+/* genModbits :- modulus of bits                                   */
+/*-----------------------------------------------------------------*/
+static void genModbits (operand *left, 
+                        operand *right, 
+                        operand *result)
+{
+
+    char *l;
+
+    /* the result must be bit */    
+    pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
+    l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
+
+    MOVA(l);       
+
+    pic16_emitcode("div","ab");
+    pic16_emitcode("mov","a,b");
+    pic16_emitcode("rrc","a");
+    pic16_aopPut(AOP(result),"c",0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genModOneByte : 8 bit modulus                                   */
+/*-----------------------------------------------------------------*/
+static void genModOneByte (operand *left,
+                           operand *right,
+                           operand *result)
+{
+    sym_link *opetype = operandType(result);
+    char *l ;
+    symbol *lbl ;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* signed or unsigned */
+    if (SPEC_USIGN(opetype)) {
+        /* unsigned is easy */
+        pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
+        l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
+        MOVA(l);    
+        pic16_emitcode("div","ab");
+        pic16_aopPut(AOP(result),"b",0);
+        return ;
+    }
+
+    /* signed is a little bit more difficult */
+
+    /* save the signs of the operands */
+    l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
+    MOVA(l);
+
+    pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
+    pic16_emitcode("push","acc"); /* save it on the stack */
+
+    /* now sign adjust for both left & right */
+    l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
+    MOVA(l);
+
+    lbl = newiTempLabel(NULL);
+    pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
+    pic16_emitcode("cpl","a");   
+    pic16_emitcode("inc","a");
+    pic16_emitcode("","%05d_DS_:",(lbl->key+100));
+    pic16_emitcode("mov","b,a"); 
+
+    /* sign adjust left side */
+    l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
+    MOVA(l);
+
+    lbl = newiTempLabel(NULL);
+    pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
+    pic16_emitcode("cpl","a");   
+    pic16_emitcode("inc","a");
+    pic16_emitcode("","%05d_DS_:",(lbl->key+100));
+
+    /* now the multiplication */
+    pic16_emitcode("div","ab");
+    /* we are interested in the lower order
+    only */
+    lbl = newiTempLabel(NULL);
+    pic16_emitcode("pop","acc");   
+    /* if there was an over flow we don't 
+    adjust the sign of the result */
+    pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
+    pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
+    CLRC ;
+    pic16_emitcode("clr","a");
+    pic16_emitcode("subb","a,b");
+    pic16_emitcode("mov","b,a");
+    pic16_emitcode("","%05d_DS_:",(lbl->key+100));
+
+    /* now we are done */
+    pic16_aopPut(AOP(result),"b",0);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genMod - generates code for division                            */
+/*-----------------------------------------------------------------*/
+static void genMod (iCode *ic)
+{
+    operand *left = IC_LEFT(ic);
+    operand *right = IC_RIGHT(ic);
+    operand *result= IC_RESULT(ic);  
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* assign the amsops */
+    pic16_aopOp (left,ic,FALSE);
+    pic16_aopOp (right,ic,FALSE);
+    pic16_aopOp (result,ic,TRUE);
+
+    /* special cases first */
+    /* both are bits */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        AOP_TYPE(right)== AOP_CRY) {
+        genModbits(left,right,result);
+        goto release ;
+    }
+
+    /* if both are of size == 1 */
+    if (AOP_SIZE(left) == 1 &&
+        AOP_SIZE(right) == 1 ) {
+        genModOneByte(left,right,result);
+        goto release ;
+    }
+
+    /* should have been converted to function call */
+    assert(0);
+
+release :
+    pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(result,NULL,ic,TRUE); 
+}
+
+/*-----------------------------------------------------------------*/
+/* genIfxJump :- will create a jump depending on the ifx           */
+/*-----------------------------------------------------------------*/
+/*
+  note: May need to add parameter to indicate when a variable is in bit space.
+*/
+static void genIfxJump (iCode *ic, char *jval)
+{
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* if true label then we jump if condition
+    supplied is true */
+    if ( IC_TRUE(ic) ) {
+
+       if(strcmp(jval,"a") == 0)
+         emitSKPZ;
+       else if (strcmp(jval,"c") == 0)
+         emitSKPC;
+       else {
+         DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
+         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
+       }
+
+       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
+       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
+
+    }
+    else {
+        /* false label is present */
+       if(strcmp(jval,"a") == 0)
+         emitSKPNZ;
+       else if (strcmp(jval,"c") == 0)
+         emitSKPNC;
+       else {
+         DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
+         pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
+       }
+
+       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
+       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
+
+    }
+
+
+    /* mark the icode as generated */
+    ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genSkip                                                         */
+/*-----------------------------------------------------------------*/
+static void genSkip(iCode *ifx,int status_bit)
+{
+  if(!ifx)
+    return;
+
+  if ( IC_TRUE(ifx) ) {
+    switch(status_bit) {
+    case 'z':
+      emitSKPNZ;
+      break;
+
+    case 'c':
+      emitSKPNC;
+      break;
+
+    case 'd':
+      emitSKPDC;
+      break;
+
+    }
+
+    pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
+    pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
+
+  } else {
+
+    switch(status_bit) {
+
+    case 'z':
+      emitSKPZ;
+      break;
+
+    case 'c':
+      emitSKPC;
+      break;
+
+    case 'd':
+      emitSKPDC;
+      break;
+    }
+    pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
+    pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
+
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genSkipc                                                        */
+/*-----------------------------------------------------------------*/
+static void genSkipc(resolvedIfx *rifx)
+{
+  if(!rifx)
+    return;
+
+  if(rifx->condition)
+    emitSKPC;
+  else
+    emitSKPNC;
+
+  pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
+  rifx->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genSkipz2                                                       */
+/*-----------------------------------------------------------------*/
+static void genSkipz2(resolvedIfx *rifx, int invert_condition)
+{
+  if(!rifx)
+    return;
+
+  if( (rifx->condition ^ invert_condition) & 1)
+    emitSKPZ;
+  else
+    emitSKPNZ;
+
+  pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
+  rifx->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genSkipz                                                        */
+/*-----------------------------------------------------------------*/
+static void genSkipz(iCode *ifx, int condition)
+{
+  if(!ifx)
+    return;
+
+  if(condition)
+    emitSKPNZ;
+  else
+    emitSKPZ;
+
+  if ( IC_TRUE(ifx) )
+    pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
+  else
+    pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
+
+  if ( IC_TRUE(ifx) )
+    pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
+  else
+    pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
+
+}
+/*-----------------------------------------------------------------*/
+/* genSkipCond                                                     */
+/*-----------------------------------------------------------------*/
+static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
+{
+  if(!rifx)
+    return;
+
+  if(rifx->condition)
+    pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
+  else
+    pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
+
+
+  pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
+  rifx->generated = 1;
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* genChkZeroes :- greater or less than comparison                 */
+/*     For each byte in a literal that is zero, inclusive or the   */
+/*     the corresponding byte in the operand with W                */
+/*     returns true if any of the bytes are zero                   */
+/*-----------------------------------------------------------------*/
+static int genChkZeroes(operand *op, int lit,  int size)
+{
+
+  int i;
+  int flag =1;
+
+  while(size--) {
+    i = (lit >> (size*8)) & 0xff;
+
+    if(i==0) {
+      if(flag) 
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
+      else
+       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
+      flag = 0;
+    }
+  }
+
+  return (flag==0);
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* genCmp :- greater or less than comparison                       */
+/*-----------------------------------------------------------------*/
+static void genCmp (operand *left,operand *right,
+                    operand *result, iCode *ifx, int sign)
+{
+  int size; //, offset = 0 ;
+  unsigned long lit = 0L,i = 0;
+  resolvedIfx rFalseIfx;
+  //  resolvedIfx rTrueIfx;
+  symbol *truelbl;
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+/*
+  if(ifx) {
+    DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
+    DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
+  }
+*/
+
+  resolveIfx(&rFalseIfx,ifx);
+  truelbl  = newiTempLabel(NULL);
+  size = max(AOP_SIZE(left),AOP_SIZE(right));
+
+  DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
+
+#define _swapp
+
+  /* if literal is on the right then swap with left */
+  if ((AOP_TYPE(right) == AOP_LIT)) {
+    operand *tmp = right ;
+    unsigned long mask = (0x100 << (8*(size-1))) - 1;
+    lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
+#ifdef _swapp
+
+    lit = (lit - 1) & mask;
+    right = left;
+    left = tmp;
+    rFalseIfx.condition ^= 1;
+#endif
+
+  } else if ((AOP_TYPE(left) == AOP_LIT)) {
+    lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
+  }
+
+
+  //if(IC_TRUE(ifx) == NULL)
+  /* if left & right are bit variables */
+  if (AOP_TYPE(left) == AOP_CRY &&
+      AOP_TYPE(right) == AOP_CRY ) {
+    pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
+    pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
+  } else {
+    /* subtract right from left if at the
+       end the carry flag is set then we know that
+       left is greater than right */
+
+    //    {
+
+    symbol *lbl  = newiTempLabel(NULL);
+
+#ifndef _swapp
+    if(AOP_TYPE(right) == AOP_LIT) {
+
+      //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
+
+      DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
+
+      /* special cases */
+
+      if(lit == 0) {
+
+       if(sign != 0) 
+         genSkipCond(&rFalseIfx,left,size-1,7);
+       else 
+         /* no need to compare to 0...*/
+         /* NOTE: this is a de-generate compare that most certainly 
+          *       creates some dead code. */
+         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
+
+       if(ifx) ifx->generated = 1;
+       return;
+
+      }
+      size--;
+
+      if(size == 0) {
+       //i = (lit >> (size*8)) & 0xff;
+       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
+       
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
+
+       i = ((0-lit) & 0xff);
+       if(sign) {
+         if( i == 0x81) { 
+           /* lit is 0x7f, all signed chars are less than
+            * this except for 0x7f itself */
+           pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
+           genSkipz2(&rFalseIfx,0);
+         } else {
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
+           genSkipc(&rFalseIfx);
+         }
+
+       } else {
+         if(lit == 1) {
+           genSkipz2(&rFalseIfx,1);
+         } else {
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
+           genSkipc(&rFalseIfx);
+         }
+       }
+
+       if(ifx) ifx->generated = 1;
+       return;
+      }
+
+      /* chars are out of the way. now do ints and longs */
+
+
+      DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
+       
+      /* special cases */
+
+      if(sign) {
+
+       if(lit == 0) {
+         genSkipCond(&rFalseIfx,left,size,7);
+         if(ifx) ifx->generated = 1;
+         return;
+       }
+
+       if(lit <0x100) {
+         DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
+
+         //rFalseIfx.condition ^= 1;
+         //genSkipCond(&rFalseIfx,left,size,7);
+         //rFalseIfx.condition ^= 1;
+
+         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
+         if(rFalseIfx.condition)
+           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+         else
+           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
+         pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
+         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
+
+         while(size > 1)
+           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
+
+         if(rFalseIfx.condition) {
+           emitSKPZ;
+           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+
+         } else {
+           emitSKPNZ;
+         }
+
+         genSkipc(&rFalseIfx);
+         pic16_emitpLabel(truelbl->key);
+         if(ifx) ifx->generated = 1;
+         return;
+
+       }
+
+       if(size == 1) {
+
+         if( (lit & 0xff) == 0) {
+           /* lower byte is zero */
+           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
+           i = ((lit >> 8) & 0xff) ^0x80;
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
+           genSkipc(&rFalseIfx);
+
+
+           if(ifx) ifx->generated = 1;
+           return;
+
+         }
+       } else {
+         /* Special cases for signed longs */
+         if( (lit & 0xffffff) == 0) {
+           /* lower byte is zero */
+           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
+           i = ((lit >> 8*3) & 0xff) ^0x80;
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
+           genSkipc(&rFalseIfx);
+
+
+           if(ifx) ifx->generated = 1;
+           return;
+
+         }
+
+       }
+
+
+       if(lit & (0x80 << (size*8))) {
+         /* lit is negative */
+         DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
+
+         //genSkipCond(&rFalseIfx,left,size,7);
+
+         pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
+
+         if(rFalseIfx.condition)
+           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+         else
+           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+
+
+       } else {
+         /* lit is positive */
+         DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
+         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
+         if(rFalseIfx.condition)
+           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+         else
+           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+
+       }
+
+       /*
+         This works, but is only good for ints.
+         It also requires a "known zero" register.
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
+         pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
+         pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
+         pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
+         pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
+         genSkipc(&rFalseIfx);
+
+         pic16_emitpLabel(truelbl->key);
+         if(ifx) ifx->generated = 1;
+         return;
+       **/
+         
+       /* There are no more special cases, so perform a general compare */
+  
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
+       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
+
+       while(size--) {
+
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
+         emitSKPNZ;
+         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
+       }
+       //rFalseIfx.condition ^= 1;
+       genSkipc(&rFalseIfx);
+
+       pic16_emitpLabel(truelbl->key);
+
+       if(ifx) ifx->generated = 1;
+       return;
+
+
+      }
+
+
+      /* sign is out of the way. So now do an unsigned compare */
+      DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
+
+
+      /* General case - compare to an unsigned literal on the right.*/
+
+      i = (lit >> (size*8)) & 0xff;
+      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
+      pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
+      while(size--) {
+       i = (lit >> (size*8)) & 0xff;
+
+       if(i) {
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
+         emitSKPNZ;
+         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
+       } else {
+         /* this byte of the lit is zero, 
+          *if it's not the last then OR in the variable */
+         if(size)
+           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
+       }
+      }
+
+
+      pic16_emitpLabel(lbl->key);
+      //if(emitFinalCheck)
+      genSkipc(&rFalseIfx);
+      if(sign)
+       pic16_emitpLabel(truelbl->key);
+
+      if(ifx) ifx->generated = 1;
+      return;
+
+
+    }
+#endif  // _swapp
+
+    if(AOP_TYPE(left) == AOP_LIT) {
+      //symbol *lbl = newiTempLabel(NULL);
+
+      //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
+
+
+      DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
+
+      /* Special cases */
+      if((lit == 0) && (sign == 0)){
+
+       size--;
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+       while(size) 
+         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
+
+       genSkipz2(&rFalseIfx,0);
+       if(ifx) ifx->generated = 1;
+       return;
+      }
+
+      if(size==1) {
+       /* Special cases */
+       lit &= 0xff;
+       if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
+         /* degenerate compare can never be true */
+         if(rFalseIfx.condition == 0)
+           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
+
+         if(ifx) ifx->generated = 1;
+         return;
+       }
+
+       if(sign) {
+         /* signed comparisons to a literal byte */
+
+         int lp1 = (lit+1) & 0xff;
+
+         DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
+         switch (lp1) {
+         case 0:
+           rFalseIfx.condition ^= 1;
+           genSkipCond(&rFalseIfx,right,0,7);
+           break;
+         case 0x7f:
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+           pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
+           genSkipz2(&rFalseIfx,1);
+           break;
+         default:
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
+           rFalseIfx.condition ^= 1;
+           genSkipc(&rFalseIfx);
+           break;
+         }
+       } else {
+         /* unsigned comparisons to a literal byte */
+
+         switch(lit & 0xff ) {
+         case 0:
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+           genSkipz2(&rFalseIfx,0);
+           break;
+         case 0x7f:
+           rFalseIfx.condition ^= 1;
+           genSkipCond(&rFalseIfx,right,0,7);
+           break;
+
+         default:
+           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
+           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
+           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+           rFalseIfx.condition ^= 1;
+           if (AOP_TYPE(result) == AOP_CRY)
+             genSkipc(&rFalseIfx);
+           else {
+             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
+             pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
+           }         
+           break;
+         }
+       }
+
+       if(ifx) ifx->generated = 1;
+       //goto check_carry;
+       return;
+
+      } else {
+
+       /* Size is greater than 1 */
+
+       if(sign) {
+         int lp1 = lit+1;
+
+         size--;
+
+         if(lp1 == 0) {
+           /* this means lit = 0xffffffff, or -1 */
+
+
+           DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
+           rFalseIfx.condition ^= 1;
+           genSkipCond(&rFalseIfx,right,size,7);
+           if(ifx) ifx->generated = 1;
+           return;
+         }
+
+         if(lit == 0) {
+           int s = size;
+
+           if(rFalseIfx.condition) {
+             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
+             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+           }
+
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+           while(size--)
+             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
+
+
+           emitSKPZ;
+           if(rFalseIfx.condition) {
+             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+             pic16_emitpLabel(truelbl->key);
+           }else {
+             rFalseIfx.condition ^= 1;
+             genSkipCond(&rFalseIfx,right,s,7);
+           }
+
+           if(ifx) ifx->generated = 1;
+           return;
+         }
+
+         if((size == 1) &&  (0 == (lp1&0xff))) {
+           /* lower byte of signed word is zero */
+           DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
+           i = ((lp1 >> 8) & 0xff) ^0x80;
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
+           rFalseIfx.condition ^= 1;
+           genSkipc(&rFalseIfx);
+
+
+           if(ifx) ifx->generated = 1;
+           return;
+         }
+
+         if(lit & (0x80 << (size*8))) {
+           /* Lit is less than zero */
+           DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
+           //rFalseIfx.condition ^= 1;
+           //genSkipCond(&rFalseIfx,left,size,7);
+           //rFalseIfx.condition ^= 1;
+           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
+           //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+
+           if(rFalseIfx.condition)
+             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+           else
+             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+
+
+         } else {
+           /* Lit is greater than or equal to zero */
+           DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
+           //rFalseIfx.condition ^= 1;
+           //genSkipCond(&rFalseIfx,right,size,7);
+           //rFalseIfx.condition ^= 1;
+
+           //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
+           //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+
+           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
+           if(rFalseIfx.condition)
+             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+           else
+             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+
+         }
+
+
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
+         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
+
+         while(size--) {
+
+           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
+           emitSKPNZ;
+           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
+         }
+         rFalseIfx.condition ^= 1;
+         //rFalseIfx.condition = 1;
+         genSkipc(&rFalseIfx);
+
+         pic16_emitpLabel(truelbl->key);
+
+         if(ifx) ifx->generated = 1;
+         return;
+         // end of if (sign)
+       } else {
+
+         /* compare word or long to an unsigned literal on the right.*/
+
+
+         size--;
+         if(lit < 0xff) {
+           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
+           switch (lit) {
+           case 0:
+             break; /* handled above */
+/*
+           case 0xff:
+             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+             while(size--)
+               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
+             genSkipz2(&rFalseIfx,0);
+             break;
+*/
+           default:
+             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+             while(--size)
+               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
+
+             emitSKPZ;
+             if(rFalseIfx.condition)
+               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+             else
+               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+
+
+             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
+             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
+
+             rFalseIfx.condition ^= 1;
+             genSkipc(&rFalseIfx);
+           }
+
+           pic16_emitpLabel(truelbl->key);
+
+           if(ifx) ifx->generated = 1;
+           return;
+         }
+
+
+         lit++;
+         DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
+         i = (lit >> (size*8)) & 0xff;
+
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
+         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
+
+         while(size--) {
+           i = (lit >> (size*8)) & 0xff;
+
+           if(i) {
+             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
+             emitSKPNZ;
+             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
+           } else {
+             /* this byte of the lit is zero, 
+              *if it's not the last then OR in the variable */
+             if(size)
+               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
+           }
+         }
+
+
+         pic16_emitpLabel(lbl->key);
+
+         rFalseIfx.condition ^= 1;
+         genSkipc(&rFalseIfx);
+       }
+
+       if(sign)
+         pic16_emitpLabel(truelbl->key);
+       if(ifx) ifx->generated = 1;
+       return;
+      }
+    }
+    /* Compare two variables */
+
+    DEBUGpic16_emitcode(";sign","%d",sign);
+
+    size--;
+    if(sign) {
+      /* Sigh. thus sucks... */
+      if(size) {
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
+       pic16_emitpcode(POC_MOVWF, popRegFromIdx(pic16_Gstack_base_addr));
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
+       pic16_emitpcode(POC_XORWF, popRegFromIdx(pic16_Gstack_base_addr));
+       pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
+       pic16_emitpcode(POC_SUBFW, popRegFromIdx(pic16_Gstack_base_addr));
+      } else {
+       /* Signed char comparison */
+       /* Special thanks to Nikolai Golovchenko for this snippet */
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
+       pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
+       pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
+       pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
+       pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
+
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+       genSkipc(&rFalseIfx);
+         
+       if(ifx) ifx->generated = 1;
+       return;
+      }
+
+    } else {
+
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+      pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
+    }
+
+
+    /* The rest of the bytes of a multi-byte compare */
+    while (size) {
+
+      emitSKPZ;
+      pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
+      size--;
+
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+      pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
+
+
+    }
+
+    pic16_emitpLabel(lbl->key);
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
+       (AOP_TYPE(result) == AOP_REG)) {
+      pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
+    } else {
+      genSkipc(&rFalseIfx);
+    }        
+    //genSkipc(&rFalseIfx);
+    if(ifx) ifx->generated = 1;
+
+    return;
+
+  }
+
+  // check_carry:
+  if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    pic16_outBitC(result);
+  } else {
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* if the result is used in the next
+       ifx conditional branch then generate
+       code a little differently */
+    if (ifx )
+      genIfxJump (ifx,"c");
+    else
+      pic16_outBitC(result);
+    /* leave the result in acc */
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmpGt :- greater than comparison                             */
+/*-----------------------------------------------------------------*/
+static void genCmpGt (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+    sym_link *letype , *retype;
+    int sign ;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    left = IC_LEFT(ic);
+    right= IC_RIGHT(ic);
+    result = IC_RESULT(ic);
+
+    letype = getSpec(operandType(left));
+    retype =getSpec(operandType(right));
+    sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
+    /* assign the amsops */
+    pic16_aopOp (left,ic,FALSE);
+    pic16_aopOp (right,ic,FALSE);
+    pic16_aopOp (result,ic,TRUE);
+
+    genCmp(right, left, result, ifx, sign);
+
+    pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(result,NULL,ic,TRUE); 
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmpLt - less than comparisons                                */
+/*-----------------------------------------------------------------*/
+static void genCmpLt (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+    sym_link *letype , *retype;
+    int sign ;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    left = IC_LEFT(ic);
+    right= IC_RIGHT(ic);
+    result = IC_RESULT(ic);
+
+    letype = getSpec(operandType(left));
+    retype =getSpec(operandType(right));
+    sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
+
+    /* assign the amsops */
+    pic16_aopOp (left,ic,FALSE);
+    pic16_aopOp (right,ic,FALSE);
+    pic16_aopOp (result,ic,TRUE);
+
+    genCmp(left, right, result, ifx, sign);
+
+    pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(result,NULL,ic,TRUE); 
+}
+
+/*-----------------------------------------------------------------*/
+/* genc16bit2lit - compare a 16 bit value to a literal             */
+/*-----------------------------------------------------------------*/
+static void genc16bit2lit(operand *op, int lit, int offset)
+{
+  int i;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
+  if( (lit&0xff) == 0) 
+    i=1;
+  else
+    i=0;
+
+  switch( BYTEofLONG(lit,i)) { 
+  case 0:
+    pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
+    break;
+  case 1:
+    pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
+    break;
+  case 0xff:
+    pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
+    break;
+  default:
+    pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
+    pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
+  }
+
+  i ^= 1;
+
+  switch( BYTEofLONG(lit,i)) { 
+  case 0:
+    pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
+    break;
+  case 1:
+    emitSKPNZ;
+    pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
+    break;
+  case 0xff:
+    emitSKPNZ;
+    pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
+    break;
+  default:
+    pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
+    emitSKPNZ;
+    pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
+
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* gencjneshort - compare and jump if not equal                    */
+/*-----------------------------------------------------------------*/
+static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
+{
+  int size = max(AOP_SIZE(left),AOP_SIZE(right));
+  int offset = 0;
+  int res_offset = 0;  /* the result may be a different size then left or right */
+  int res_size = AOP_SIZE(result);
+  resolvedIfx rIfx;
+  symbol *lbl;
+
+  unsigned long lit = 0L;
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
+  if(result)
+    DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
+  resolveIfx(&rIfx,ifx);
+  lbl =  newiTempLabel(NULL);
+
+
+  /* if the left side is a literal or 
+     if the right is in a pointer register and left 
+     is not */
+  if ((AOP_TYPE(left) == AOP_LIT) || 
+      (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
+    operand *t = right;
+    right = left;
+    left = t;
+  }
+  if(AOP_TYPE(right) == AOP_LIT)
+    lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
+
+  /* if the right side is a literal then anything goes */
+  if (AOP_TYPE(right) == AOP_LIT &&
+      AOP_TYPE(left) != AOP_DIR ) {
+    switch(size) {
+    case 2:
+      genc16bit2lit(left, lit, 0);
+      emitSKPNZ;
+      pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
+      break;
+    default:
+      while (size--) {
+       if(lit & 0xff) {
+         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
+         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
+       } else {
+         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
+       }
+
+       emitSKPNZ;
+       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
+       offset++;
+       if(res_offset < res_size-1)
+         res_offset++;
+       lit >>= 8;
+      }
+      break;
+    }
+  }
+
+  /* if the right side is in a register or in direct space or
+     if the left is a pointer register & right is not */    
+  else if (AOP_TYPE(right) == AOP_REG ||
+          AOP_TYPE(right) == AOP_DIR || 
+          (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
+          (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
+    //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
+    int lbl_key = lbl->key;
+
+    if(result) {
+      pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
+      //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
+    }else {
+      DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
+      fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
+             __FUNCTION__,__LINE__);
+      return;
+    }
+
+/*     switch(size) { */
+/*     case 2: */
+/*       genc16bit2lit(left, lit, 0); */
+/*       emitSKPNZ; */
+/*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
+/*       break; */
+/*     default: */
+    while (size--) {
+      int emit_skip=1;
+      if((AOP_TYPE(left) == AOP_DIR) && 
+        ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
+
+       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
+       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
+
+      } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
+           
+       switch (lit & 0xff) {
+       case 0:
+         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
+         break;
+       case 1:
+         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
+         pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
+         //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
+         emit_skip=0;
+         break;
+       case 0xff:
+         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
+         //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
+         //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
+         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
+         emit_skip=0;
+         break;
+       default:
+         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
+         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
+       }
+       lit >>= 8;
+
+      } else {
+       pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
+      }
+      if(emit_skip) {
+       if(AOP_TYPE(result) == AOP_CRY) {
+         pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
+         if(rIfx.condition)
+           emitSKPNZ;
+         else
+           emitSKPZ;
+         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
+       } else {
+         /* fix me. probably need to check result size too */
+         //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
+         if(rIfx.condition)
+           emitSKPZ;
+         else
+           emitSKPNZ;
+         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
+         //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
+       }
+       if(ifx)
+         ifx->generated=1;
+      }
+      emit_skip++;
+      offset++;
+      if(res_offset < res_size-1)
+       res_offset++;
+    }
+/*       break; */
+/*     } */
+  } else if(AOP_TYPE(right) == AOP_REG &&
+           AOP_TYPE(left) != AOP_DIR){
+
+    while(size--) {
+      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
+      pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
+      pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
+      if(rIfx.condition)
+       emitSKPNZ;
+      else
+       emitSKPZ;
+      pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
+      offset++;
+      if(res_offset < res_size-1)
+       res_offset++;
+    }
+      
+  }else{
+    /* right is a pointer reg need both a & b */
+    while(size--) {
+      char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
+      if(strcmp(l,"b"))
+       pic16_emitcode("mov","b,%s",l);
+      MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+      pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
+      offset++;
+    }
+  }
+
+  pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
+  if(!rIfx.condition)
+    pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
+
+  pic16_emitpLabel(lbl->key);
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  if(ifx)
+    ifx->generated = 1;
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* gencjne - compare and jump if not equal                         */
+/*-----------------------------------------------------------------*/
+static void gencjne(operand *left, operand *right, iCode *ifx)
+{
+    symbol *tlbl  = newiTempLabel(NULL);
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    gencjneshort(left, right, lbl);
+
+    pic16_emitcode("mov","a,%s",one);
+    pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
+    pic16_emitcode("","%05d_DS_:",lbl->key+100);
+    pic16_emitcode("clr","a");
+    pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+
+    pic16_emitpLabel(lbl->key);
+    pic16_emitpLabel(tlbl->key);
+
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* genCmpEq - generates code for equal to                          */
+/*-----------------------------------------------------------------*/
+static void genCmpEq (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+    unsigned long lit = 0L;
+    int size,offset=0;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    if(ifx)
+      DEBUGpic16_emitcode ("; ifx is non-null","");
+    else
+      DEBUGpic16_emitcode ("; ifx is null","");
+
+    pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
+    pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
+    pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
+
+    size = max(AOP_SIZE(left),AOP_SIZE(right));
+
+    DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
+
+    /* if literal, literal on the right or 
+    if the right is in a pointer register and left 
+    is not */
+    if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
+        (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
+      operand *tmp = right ;
+      right = left;
+      left = tmp;
+    }
+
+
+    if(ifx && !AOP_SIZE(result)){
+        symbol *tlbl;
+        /* if they are both bit variables */
+        if (AOP_TYPE(left) == AOP_CRY &&
+            ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
+            if(AOP_TYPE(right) == AOP_LIT){
+                unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
+                if(lit == 0L){
+                    pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+                    pic16_emitcode("cpl","c");
+                } else if(lit == 1L) {
+                    pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+                } else {
+                    pic16_emitcode("clr","c");
+                }
+                /* AOP_TYPE(right) == AOP_CRY */
+            } else {
+                symbol *lbl = newiTempLabel(NULL);
+                pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+                pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
+                pic16_emitcode("cpl","c");
+                pic16_emitcode("","%05d_DS_:",(lbl->key+100));
+            }
+            /* if true label then we jump if condition
+            supplied is true */
+            tlbl = newiTempLabel(NULL);
+            if ( IC_TRUE(ifx) ) {
+                pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
+                pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
+            } else {
+                pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
+                pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
+            }
+            pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
+
+           {
+             /* left and right are both bit variables, result is carry */
+             resolvedIfx rIfx;
+             
+             resolveIfx(&rIfx,ifx);
+
+             pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
+             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
+             pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
+             pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
+             genSkipz2(&rIfx,0);
+           }
+        } else {
+
+         /* They're not both bit variables. Is the right a literal? */
+         if(AOP_TYPE(right) == AOP_LIT) {
+           lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
+           
+           switch(size) {
+
+           case 1:
+             switch(lit & 0xff) {
+             case 1:
+               if ( IC_TRUE(ifx) ) {
+                 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
+                 emitSKPNZ;
+                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
+               } else {
+                 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
+                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
+               }
+               break;
+             case 0xff:
+               if ( IC_TRUE(ifx) ) {
+                 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
+                 emitSKPNZ;
+                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
+               } else {
+                 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
+                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
+               }
+               break;
+             default:
+               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
+               if(lit)
+                 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
+               genSkip(ifx,'z');
+             }
+
+
+             /* end of size == 1 */
+             break;
+             
+           case 2:
+             genc16bit2lit(left,lit,offset);
+             genSkip(ifx,'z');
+             break;
+             /* end of size == 2 */
+
+           default:
+             /* size is 4 */
+             if(lit==0) {
+               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
+               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
+               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
+               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
+
+             } else {
+
+               /* search for patterns that can be optimized */
+
+               genc16bit2lit(left,lit,0);
+               lit >>= 16;
+               if(lit) {
+                 genSkipz(ifx,IC_TRUE(ifx) == NULL);
+                 //genSkip(ifx,'z');
+                 genc16bit2lit(left,lit,2);
+               } else {
+                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
+                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
+
+               }
+               
+             }
+
+             genSkip(ifx,'z');
+           }
+         
+           ifx->generated = 1;
+           goto release ;
+           
+
+         } else if(AOP_TYPE(right) == AOP_CRY ) {
+           /* we know the left is not a bit, but that the right is */
+           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
+           pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
+                     pic16_popGet(AOP(right),offset));
+           pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
+
+           /* if the two are equal, then W will be 0 and the Z bit is set
+            * we could test Z now, or go ahead and check the high order bytes if
+            * the variable we're comparing is larger than a byte. */
+
+           while(--size)
+             pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
+
+           if ( IC_TRUE(ifx) ) {
+             emitSKPNZ;
+             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
+             pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
+           } else {
+             emitSKPZ;
+             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
+             pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
+           }
+
+         } else {
+           /* They're both variables that are larger than bits */
+           int s = size;
+
+           tlbl = newiTempLabel(NULL);
+
+           while(size--) {
+             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
+             pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
+
+             if ( IC_TRUE(ifx) ) {
+               if(size) {
+                 emitSKPZ;
+                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
+                 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
+               } else {
+                 emitSKPNZ;
+                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
+                 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
+               }
+             } else {
+               emitSKPZ;
+               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
+               pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
+             }
+             offset++;
+           }
+           if(s>1 && IC_TRUE(ifx)) {
+             pic16_emitpLabel(tlbl->key);
+             pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
+           }
+         }
+        }
+        /* mark the icode as generated */
+        ifx->generated = 1;
+        goto release ;
+    }
+
+    /* if they are both bit variables */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
+        if(AOP_TYPE(right) == AOP_LIT){
+            unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
+            if(lit == 0L){
+                pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+                pic16_emitcode("cpl","c");
+            } else if(lit == 1L) {
+                pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+            } else {
+                pic16_emitcode("clr","c");
+            }
+            /* AOP_TYPE(right) == AOP_CRY */
+        } else {
+            symbol *lbl = newiTempLabel(NULL);
+            pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+            pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
+            pic16_emitcode("cpl","c");
+            pic16_emitcode("","%05d_DS_:",(lbl->key+100));
+        }
+        /* c = 1 if egal */
+        if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
+            pic16_outBitC(result);
+            goto release ;
+        }
+        if (ifx) {
+            genIfxJump (ifx,"c");
+            goto release ;
+        }
+        /* if the result is used in an arithmetic operation
+        then put the result in place */
+        pic16_outBitC(result);
+    } else {
+      
+      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+      gencjne(left,right,result,ifx);
+/*
+      if(ifx) 
+       gencjne(left,right,newiTempLabel(NULL));
+      else {
+       if(IC_TRUE(ifx)->key)
+         gencjne(left,right,IC_TRUE(ifx)->key);
+       else
+         gencjne(left,right,IC_FALSE(ifx)->key);
+       ifx->generated = 1;
+       goto release ;
+      }
+      if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
+       pic16_aopPut(AOP(result),"a",0);
+       goto release ;
+      }
+
+      if (ifx) {
+       genIfxJump (ifx,"a");
+       goto release ;
+      }
+*/
+      /* if the result is used in an arithmetic operation
+        then put the result in place */
+/*
+      if (AOP_TYPE(result) != AOP_CRY) 
+       pic16_outAcc(result);
+*/
+      /* leave the result in acc */
+    }
+
+release:
+    pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* ifxForOp - returns the icode containing the ifx for operand     */
+/*-----------------------------------------------------------------*/
+static iCode *ifxForOp ( operand *op, iCode *ic )
+{
+    /* if true symbol then needs to be assigned */
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if (IS_TRUE_SYMOP(op))
+        return NULL ;
+
+    /* if this has register type condition and
+    the next instruction is ifx with the same operand
+    and live to of the operand is upto the ifx only then */
+    if (ic->next &&
+        ic->next->op == IFX &&
+        IC_COND(ic->next)->key == op->key &&
+        OP_SYMBOL(op)->liveTo <= ic->next->seq )
+        return ic->next;
+
+    if (ic->next &&
+        ic->next->op == IFX &&
+        IC_COND(ic->next)->key == op->key) {
+      DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
+      return ic->next;
+    }
+
+    DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
+    if (ic->next &&
+        ic->next->op == IFX)
+      DEBUGpic16_emitcode ("; ic-next"," is an IFX");
+
+    if (ic->next &&
+        ic->next->op == IFX &&
+        IC_COND(ic->next)->key == op->key) {
+      DEBUGpic16_emitcode ("; "," key is okay");
+      DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
+                          OP_SYMBOL(op)->liveTo,
+                          ic->next->seq);
+    }
+
+
+    return NULL;
+}
+/*-----------------------------------------------------------------*/
+/* genAndOp - for && operation                                     */
+/*-----------------------------------------------------------------*/
+static void genAndOp (iCode *ic)
+{
+    operand *left,*right, *result;
+/*     symbol *tlbl; */
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* note here that && operations that are in an
+    if statement are taken away by backPatchLabels
+    only those used in arthmetic operations remain */
+    pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
+    pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
+    pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
+
+    DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
+
+    pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
+    pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
+    pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
+
+    /* if both are bit variables */
+/*     if (AOP_TYPE(left) == AOP_CRY && */
+/*         AOP_TYPE(right) == AOP_CRY ) { */
+/*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
+/*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
+/*         pic16_outBitC(result); */
+/*     } else { */
+/*         tlbl = newiTempLabel(NULL); */
+/*         pic16_toBoolean(left);     */
+/*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
+/*         pic16_toBoolean(right); */
+/*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
+/*         pic16_outBitAcc(result); */
+/*     } */
+
+    pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genOrOp - for || operation                                      */
+/*-----------------------------------------------------------------*/
+/*
+  tsd pic port -
+  modified this code, but it doesn't appear to ever get called
+*/
+
+static void genOrOp (iCode *ic)
+{
+    operand *left,*right, *result;
+    symbol *tlbl;
+
+    /* note here that || operations that are in an
+    if statement are taken away by backPatchLabels
+    only those used in arthmetic operations remain */
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
+    pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
+    pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
+
+    DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
+
+    /* if both are bit variables */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        AOP_TYPE(right) == AOP_CRY ) {
+      pic16_emitcode("clrc","");
+      pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
+              AOP(left)->aopu.aop_dir,
+              AOP(left)->aopu.aop_dir);
+      pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+              AOP(right)->aopu.aop_dir,
+              AOP(right)->aopu.aop_dir);
+      pic16_emitcode("setc","");
+
+    } else {
+        tlbl = newiTempLabel(NULL);
+        pic16_toBoolean(left);
+       emitSKPZ;
+        pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
+        pic16_toBoolean(right);
+        pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
+
+        pic16_outBitAcc(result);
+    }
+
+    pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(result,NULL,ic,TRUE);            
+}
+
+/*-----------------------------------------------------------------*/
+/* isLiteralBit - test if lit == 2^n                               */
+/*-----------------------------------------------------------------*/
+static int isLiteralBit(unsigned long lit)
+{
+    unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
+    0x100L,0x200L,0x400L,0x800L,
+    0x1000L,0x2000L,0x4000L,0x8000L,
+    0x10000L,0x20000L,0x40000L,0x80000L,
+    0x100000L,0x200000L,0x400000L,0x800000L,
+    0x1000000L,0x2000000L,0x4000000L,0x8000000L,
+    0x10000000L,0x20000000L,0x40000000L,0x80000000L};
+    int idx;
+    
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    for(idx = 0; idx < 32; idx++)
+        if(lit == pw[idx])
+            return idx+1;
+    return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* continueIfTrue -                                                */
+/*-----------------------------------------------------------------*/
+static void continueIfTrue (iCode *ic)
+{
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if(IC_TRUE(ic))
+        pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
+    ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* jmpIfTrue -                                                     */
+/*-----------------------------------------------------------------*/
+static void jumpIfTrue (iCode *ic)
+{
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if(!IC_TRUE(ic))
+        pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
+    ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* jmpTrueOrFalse -                                                */
+/*-----------------------------------------------------------------*/
+static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
+{
+    // ugly but optimized by peephole
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if(IC_TRUE(ic)){
+        symbol *nlbl = newiTempLabel(NULL);
+        pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
+        pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+        pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
+        pic16_emitcode("","%05d_DS_:",nlbl->key+100);
+    }
+    else{
+        pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
+        pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+    }
+    ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genAnd  - code for and                                          */
+/*-----------------------------------------------------------------*/
+static void genAnd (iCode *ic, iCode *ifx)
+{
+  operand *left, *right, *result;
+  int size, offset=0;  
+  unsigned long lit = 0L;
+  int bytelit = 0;
+  resolvedIfx rIfx;
+
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
+  pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
+  pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
+
+  resolveIfx(&rIfx,ifx);
+
+  /* if left is a literal & right is not then exchange them */
+  if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
+      AOP_NEEDSACC(left)) {
+    operand *tmp = right ;
+    right = left;
+    left = tmp;
+  }
+
+  /* if result = right then exchange them */
+  if(pic16_sameRegs(AOP(result),AOP(right))){
+    operand *tmp = right ;
+    right = left;
+    left = tmp;
+  }
+
+  /* if right is bit then exchange them */
+  if (AOP_TYPE(right) == AOP_CRY &&
+      AOP_TYPE(left) != AOP_CRY){
+    operand *tmp = right ;
+    right = left;
+    left = tmp;
+  }
+  if(AOP_TYPE(right) == AOP_LIT)
+    lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
+
+  size = AOP_SIZE(result);
+
+  DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
+
+  // if(bit & yy)
+  // result = bit & yy;
+  if (AOP_TYPE(left) == AOP_CRY){
+    // c = bit & literal;
+    if(AOP_TYPE(right) == AOP_LIT){
+      if(lit & 1) {
+       if(size && pic16_sameRegs(AOP(result),AOP(left)))
+         // no change
+         goto release;
+       pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+      } else {
+       // bit(result) = 0;
+       if(size && (AOP_TYPE(result) == AOP_CRY)){
+         pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
+         goto release;
+       }
+       if((AOP_TYPE(result) == AOP_CRY) && ifx){
+         jumpIfTrue(ifx);
+         goto release;
+       }
+       pic16_emitcode("clr","c");
+      }
+    } else {
+      if (AOP_TYPE(right) == AOP_CRY){
+       // c = bit & bit;
+       pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
+       pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
+      } else {
+       // c = bit & val;
+       MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
+       // c = lsb
+       pic16_emitcode("rrc","a");
+       pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
+      }
+    }
+    // bit = c
+    // val = c
+    if(size)
+      pic16_outBitC(result);
+    // if(bit & ...)
+    else if((AOP_TYPE(result) == AOP_CRY) && ifx)
+      genIfxJump(ifx, "c");           
+    goto release ;
+  }
+
+  // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
+  // bit = val & 0xZZ     - size = 1, ifx = FALSE -
+  if((AOP_TYPE(right) == AOP_LIT) &&
+     (AOP_TYPE(result) == AOP_CRY) &&
+     (AOP_TYPE(left) != AOP_CRY)){
+    int posbit = isLiteralBit(lit);
+    /* left &  2^n */
+    if(posbit){
+      posbit--;
+      //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
+      // bit = left & 2^n
+      if(size)
+       pic16_emitcode("mov","c,acc.%d",posbit&0x07);
+      // if(left &  2^n)
+      else{
+       if(ifx){
+/*
+         if(IC_TRUE(ifx)) {
+           pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
+           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
+         } else {
+           pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
+           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
+         }
+*/
+         pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
+                   pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
+         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
+         
+         ifx->generated = 1;
+       }
+       goto release;
+      }
+    } else {
+      symbol *tlbl = newiTempLabel(NULL);
+      int sizel = AOP_SIZE(left);
+      if(size)
+       pic16_emitcode("setb","c");
+      while(sizel--){
+       if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
+         MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+         // byte ==  2^n ?
+         if((posbit = isLiteralBit(bytelit)) != 0)
+           pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
+         else{
+           if(bytelit != 0x0FFL)
+             pic16_emitcode("anl","a,%s",
+                            pic16_aopGet(AOP(right),offset,FALSE,TRUE));
+           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
+         }
+       }
+       offset++;
+      }
+      // bit = left & literal
+      if(size){
+       pic16_emitcode("clr","c");
+       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+      }
+      // if(left & literal)
+      else{
+       if(ifx)
+         jmpTrueOrFalse(ifx, tlbl);
+       goto release ;
+      }
+    }
+    pic16_outBitC(result);
+    goto release ;
+  }
+
+  /* if left is same as result */
+  if(pic16_sameRegs(AOP(result),AOP(left))){
+    int know_W = -1;
+    for(;size--; offset++,lit>>=8) {
+      if(AOP_TYPE(right) == AOP_LIT){
+       switch(lit & 0xff) {
+       case 0x00:
+         /*  and'ing with 0 has clears the result */
+         pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
+         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
+         break;
+       case 0xff:
+         /* and'ing with 0xff is a nop when the result and left are the same */
+         break;
+
+       default:
+         {
+           int p = my_powof2( (~lit) & 0xff );
+           if(p>=0) {
+             /* only one bit is set in the literal, so use a bcf instruction */
+             pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
+             pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
+
+           } else {
+             pic16_emitcode("movlw","0x%x", (lit & 0xff));
+             pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
+             if(know_W != (lit&0xff))
+               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+             know_W = lit &0xff;
+             pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
+           }
+         }    
+       }
+      } else {
+       if (AOP_TYPE(left) == AOP_ACC) {
+         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
+       } else {                    
+         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
+         pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
+
+       }
+      }
+    }
+
+  } else {
+    // left & result in different registers
+    if(AOP_TYPE(result) == AOP_CRY){
+      // result = bit
+      // if(size), result in bit
+      // if(!size && ifx), conditional oper: if(left & right)
+      symbol *tlbl = newiTempLabel(NULL);
+      int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
+      if(size)
+       pic16_emitcode("setb","c");
+      while(sizer--){
+       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+       pic16_emitcode("anl","a,%s",
+                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+       pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
+       offset++;
+      }
+      if(size){
+       CLRC;
+       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+       pic16_outBitC(result);
+      } else if(ifx)
+       jmpTrueOrFalse(ifx, tlbl);
+    } else {
+      for(;(size--);offset++) {
+       // normal case
+       // result = left & right
+       if(AOP_TYPE(right) == AOP_LIT){
+         int t = (lit >> (offset*8)) & 0x0FFL;
+         switch(t) { 
+         case 0x00:
+           pic16_emitcode("clrf","%s",
+                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
+           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
+           break;
+         case 0xff:
+           pic16_emitcode("movf","%s,w",
+                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+           pic16_emitcode("movwf","%s",
+                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
+           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
+           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
+           break;
+         default:
+           pic16_emitcode("movlw","0x%x",t);
+           pic16_emitcode("andwf","%s,w",
+                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+           pic16_emitcode("movwf","%s",
+                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
+             
+           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
+           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
+           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
+         }
+         continue;
+       }
+
+       if (AOP_TYPE(left) == AOP_ACC) {
+         pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
+       } else {
+         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+         pic16_emitcode("andwf","%s,w",
+                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
+         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
+       }
+       pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
+       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
+      }
+    }
+  }
+
+  release :
+    pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+  pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+  pic16_freeAsmop(result,NULL,ic,TRUE);     
+}
+
+/*-----------------------------------------------------------------*/
+/* genOr  - code for or                                            */
+/*-----------------------------------------------------------------*/
+static void genOr (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+    int size, offset=0;
+    unsigned long lit = 0L;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
+    pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
+    pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
+
+    DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
+
+    /* if left is a literal & right is not then exchange them */
+    if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
+       AOP_NEEDSACC(left)) {
+        operand *tmp = right ;
+        right = left;
+        left = tmp;
+    }
+
+    /* if result = right then exchange them */
+    if(pic16_sameRegs(AOP(result),AOP(right))){
+        operand *tmp = right ;
+        right = left;
+        left = tmp;
+    }
+
+    /* if right is bit then exchange them */
+    if (AOP_TYPE(right) == AOP_CRY &&
+        AOP_TYPE(left) != AOP_CRY){
+        operand *tmp = right ;
+        right = left;
+        left = tmp;
+    }
+
+    DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
+
+    if(AOP_TYPE(right) == AOP_LIT)
+        lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
+
+    size = AOP_SIZE(result);
+
+    // if(bit | yy)
+    // xx = bit | yy;
+    if (AOP_TYPE(left) == AOP_CRY){
+        if(AOP_TYPE(right) == AOP_LIT){
+            // c = bit & literal;
+            if(lit){
+                // lit != 0 => result = 1
+                if(AOP_TYPE(result) == AOP_CRY){
+                 if(size)
+                   pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
+                 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
+                 //     AOP(result)->aopu.aop_dir,
+                 //     AOP(result)->aopu.aop_dir);
+                    else if(ifx)
+                        continueIfTrue(ifx);
+                    goto release;
+                }
+            } else {
+                // lit == 0 => result = left
+                if(size && pic16_sameRegs(AOP(result),AOP(left)))
+                    goto release;
+                pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
+            }
+        } else {
+            if (AOP_TYPE(right) == AOP_CRY){
+             if(pic16_sameRegs(AOP(result),AOP(left))){
+                // c = bit | bit;
+               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
+               pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
+               pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
+
+               pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
+                        AOP(result)->aopu.aop_dir,
+                        AOP(result)->aopu.aop_dir);
+               pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                        AOP(right)->aopu.aop_dir,
+                        AOP(right)->aopu.aop_dir);
+               pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
+                        AOP(result)->aopu.aop_dir,
+                        AOP(result)->aopu.aop_dir);
+             } else {
+               if( AOP_TYPE(result) == AOP_ACC) {
+                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
+                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
+                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
+                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
+
+               } else {
+
+                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
+                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
+                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
+                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
+
+                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
+                                AOP(result)->aopu.aop_dir,
+                                AOP(result)->aopu.aop_dir);
+                 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
+                                AOP(right)->aopu.aop_dir,
+                                AOP(right)->aopu.aop_dir);
+                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                                AOP(left)->aopu.aop_dir,
+                                AOP(left)->aopu.aop_dir);
+                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
+                                AOP(result)->aopu.aop_dir,
+                                AOP(result)->aopu.aop_dir);
+               }
+             }
+            } else {
+                // c = bit | val;
+                symbol *tlbl = newiTempLabel(NULL);
+                pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
+
+
+               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
+               if( AOP_TYPE(right) == AOP_ACC) {
+                 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
+                 emitSKPNZ;
+                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
+                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
+               }
+
+
+
+                if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
+                    pic16_emitcode(";XXX setb","c");
+                pic16_emitcode(";XXX jb","%s,%05d_DS_",
+                         AOP(left)->aopu.aop_dir,tlbl->key+100);
+                pic16_toBoolean(right);
+                pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
+                if((AOP_TYPE(result) == AOP_CRY) && ifx){
+                    jmpTrueOrFalse(ifx, tlbl);
+                    goto release;
+                } else {
+                    CLRC;
+                    pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+                }
+            }
+        }
+        // bit = c
+        // val = c
+        if(size)
+            pic16_outBitC(result);
+        // if(bit | ...)
+        else if((AOP_TYPE(result) == AOP_CRY) && ifx)
+            genIfxJump(ifx, "c");           
+        goto release ;
+    }
+
+    // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
+    // bit = val | 0xZZ     - size = 1, ifx = FALSE -
+    if((AOP_TYPE(right) == AOP_LIT) &&
+       (AOP_TYPE(result) == AOP_CRY) &&
+       (AOP_TYPE(left) != AOP_CRY)){
+        if(lit){
+         pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
+            // result = 1
+            if(size)
+                pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
+            else 
+                continueIfTrue(ifx);
+            goto release;
+        } else {
+         pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
+            // lit = 0, result = boolean(left)
+            if(size)
+                pic16_emitcode(";XXX setb","c");
+            pic16_toBoolean(right);
+            if(size){
+                symbol *tlbl = newiTempLabel(NULL);
+                pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
+                CLRC;
+                pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+            } else {
+                genIfxJump (ifx,"a");
+                goto release;
+            }
+        }
+        pic16_outBitC(result);
+        goto release ;
+    }
+
+    /* if left is same as result */
+    if(pic16_sameRegs(AOP(result),AOP(left))){
+      int know_W = -1;
+      for(;size--; offset++,lit>>=8) {
+       if(AOP_TYPE(right) == AOP_LIT){
+         if((lit & 0xff) == 0)
+           /*  or'ing with 0 has no effect */
+           continue;
+         else {
+           int p = my_powof2(lit & 0xff);
+           if(p>=0) {
+             /* only one bit is set in the literal, so use a bsf instruction */
+             pic16_emitpcode(POC_BSF,
+                       pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
+           } else {
+             if(know_W != (lit & 0xff))
+               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+             know_W = lit & 0xff;
+             pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
+           }
+                   
+         }
+       } else {
+         if (AOP_TYPE(left) == AOP_ACC) {
+           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
+           pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+         } else {                  
+           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
+           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
+
+           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+           pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+
+         }
+       }
+      }
+    } else {
+        // left & result in different registers
+        if(AOP_TYPE(result) == AOP_CRY){
+            // result = bit
+            // if(size), result in bit
+            // if(!size && ifx), conditional oper: if(left | right)
+            symbol *tlbl = newiTempLabel(NULL);
+            int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
+           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
+
+
+            if(size)
+                pic16_emitcode(";XXX setb","c");
+            while(sizer--){
+                MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+                pic16_emitcode(";XXX orl","a,%s",
+                         pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+                pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
+                offset++;
+            }
+            if(size){
+                CLRC;
+                pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+                pic16_outBitC(result);
+            } else if(ifx)
+                jmpTrueOrFalse(ifx, tlbl);
+        } else for(;(size--);offset++){
+         // normal case
+         // result = left & right
+         if(AOP_TYPE(right) == AOP_LIT){
+           int t = (lit >> (offset*8)) & 0x0FFL;
+           switch(t) { 
+           case 0x00:
+             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
+             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
+
+             pic16_emitcode("movf","%s,w",
+                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+             pic16_emitcode("movwf","%s",
+                      pic16_aopGet(AOP(result),offset,FALSE,FALSE));
+             break;
+           default:
+             pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
+             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
+             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
+
+             pic16_emitcode("movlw","0x%x",t);
+             pic16_emitcode("iorwf","%s,w",
+                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+             pic16_emitcode("movwf","%s",
+                      pic16_aopGet(AOP(result),offset,FALSE,FALSE));
+             
+           }
+           continue;
+         }
+
+         // faster than result <- left, anl result,right
+         // and better if result is SFR
+         if (AOP_TYPE(left) == AOP_ACC) {
+           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
+           pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+         } else {
+           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
+           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
+
+           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+           pic16_emitcode("iorwf","%s,w",
+                    pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+         }
+         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
+         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
+       }
+    }
+
+release :
+    pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    pic16_freeAsmop(result,NULL,ic,TRUE);     
+}
+
+/*-----------------------------------------------------------------*/
+/* genXor - code for xclusive or                                   */
+/*-----------------------------------------------------------------*/
+static void genXor (iCode *ic, iCode *ifx)
+{
+  operand *left, *right, *result;
+  int size, offset=0;
+  unsigned long lit = 0L;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
+  pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
+  pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
+
+  /* if left is a literal & right is not ||
+     if left needs acc & right does not */
+  if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
+      (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
+    operand *tmp = right ;
+    right = left;
+    left = tmp;
+  }
+
+  /* if result = right then exchange them */
+  if(pic16_sameRegs(AOP(result),AOP(right))){
+    operand *tmp = right ;
+    right = left;
+    left = tmp;
+  }
+
+  /* if right is bit then exchange them */
+  if (AOP_TYPE(right) == AOP_CRY &&
+      AOP_TYPE(left) != AOP_CRY){
+    operand *tmp = right ;
+    right = left;
+    left = tmp;
+  }
+  if(AOP_TYPE(right) == AOP_LIT)
+    lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
+
+  size = AOP_SIZE(result);
+
+  // if(bit ^ yy)
+  // xx = bit ^ yy;
+  if (AOP_TYPE(left) == AOP_CRY){
+    if(AOP_TYPE(right) == AOP_LIT){
+      // c = bit & literal;
+      if(lit>>1){
+       // lit>>1  != 0 => result = 1
+       if(AOP_TYPE(result) == AOP_CRY){
+         if(size)
+           {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
+           pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
+         else if(ifx)
+           continueIfTrue(ifx);
+         goto release;
+       }
+       pic16_emitcode("setb","c");
+      } else{
+       // lit == (0 or 1)
+       if(lit == 0){
+         // lit == 0, result = left
+         if(size && pic16_sameRegs(AOP(result),AOP(left)))
+           goto release;
+         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+       } else{
+         // lit == 1, result = not(left)
+         if(size && pic16_sameRegs(AOP(result),AOP(left))){
+           pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
+           pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
+           pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
+           goto release;
+         } else {
+           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+           pic16_emitcode("cpl","c");
+         }
+       }
+      }
+
+    } else {
+      // right != literal
+      symbol *tlbl = newiTempLabel(NULL);
+      if (AOP_TYPE(right) == AOP_CRY){
+       // c = bit ^ bit;
+       pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
+      }
+      else{
+       int sizer = AOP_SIZE(right);
+       // c = bit ^ val
+       // if val>>1 != 0, result = 1
+       pic16_emitcode("setb","c");
+       while(sizer){
+         MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
+         if(sizer == 1)
+           // test the msb of the lsb
+           pic16_emitcode("anl","a,#0xfe");
+         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
+         sizer--;
+       }
+       // val = (0,1)
+       pic16_emitcode("rrc","a");
+      }
+      pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
+      pic16_emitcode("cpl","c");
+      pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
+    }
+    // bit = c
+    // val = c
+    if(size)
+      pic16_outBitC(result);
+    // if(bit | ...)
+    else if((AOP_TYPE(result) == AOP_CRY) && ifx)
+      genIfxJump(ifx, "c");           
+    goto release ;
+  }
+
+  if(pic16_sameRegs(AOP(result),AOP(left))){
+    /* if left is same as result */
+    for(;size--; offset++) {
+      if(AOP_TYPE(right) == AOP_LIT){
+       int t  = (lit >> (offset*8)) & 0x0FFL;
+       if(t == 0x00L)
+         continue;
+       else
+         if (IS_AOP_PREG(left)) {
+           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
+           pic16_aopPut(AOP(result),"a",offset);
+         } else {
+           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
+           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
+           pic16_emitcode("xrl","%s,%s",
+                          pic16_aopGet(AOP(left),offset,FALSE,TRUE),
+                          pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+         }
+      } else {
+       if (AOP_TYPE(left) == AOP_ACC)
+         pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+       else {
+         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
+         pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
+/*
+         if (IS_AOP_PREG(left)) {
+           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
+           pic16_aopPut(AOP(result),"a",offset);
+         } else
+           pic16_emitcode("xrl","%s,a",
+                          pic16_aopGet(AOP(left),offset,FALSE,TRUE));
+*/
+       }
+      }
+    }
+  } else {
+    // left & result in different registers
+    if(AOP_TYPE(result) == AOP_CRY){
+      // result = bit
+      // if(size), result in bit
+      // if(!size && ifx), conditional oper: if(left ^ right)
+      symbol *tlbl = newiTempLabel(NULL);
+      int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
+      if(size)
+       pic16_emitcode("setb","c");
+      while(sizer--){
+       if((AOP_TYPE(right) == AOP_LIT) &&
+          (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
+         MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+       } else {
+         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+         pic16_emitcode("xrl","a,%s",
+                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+       }
+       pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
+       offset++;
+      }
+      if(size){
+       CLRC;
+       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+       pic16_outBitC(result);
+      } else if(ifx)
+       jmpTrueOrFalse(ifx, tlbl);
+    } else for(;(size--);offset++){
+      // normal case
+      // result = left & right
+      if(AOP_TYPE(right) == AOP_LIT){
+       int t = (lit >> (offset*8)) & 0x0FFL;
+       switch(t) { 
+       case 0x00:
+         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
+         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
+         pic16_emitcode("movf","%s,w",
+                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+         pic16_emitcode("movwf","%s",
+                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
+         break;
+       case 0xff:
+         pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
+         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
+         pic16_emitcode("comf","%s,w",
+                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+         pic16_emitcode("movwf","%s",
+                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
+         break;
+       default:
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
+         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
+         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
+         pic16_emitcode("movlw","0x%x",t);
+         pic16_emitcode("xorwf","%s,w",
+                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+         pic16_emitcode("movwf","%s",
+                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
+
+       }
+       continue;
+      }
+
+      // faster than result <- left, anl result,right
+      // and better if result is SFR
+      if (AOP_TYPE(left) == AOP_ACC) {
+       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
+       pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+      } else {
+       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
+       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
+       pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+       pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+      }
+      if ( AOP_TYPE(result) != AOP_ACC){
+       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
+       pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
+      }
+    }
+  }
+
+  release :
+    pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+  pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+  pic16_freeAsmop(result,NULL,ic,TRUE);     
+}
+
+/*-----------------------------------------------------------------*/
+/* genInline - write the inline code out                           */
+/*-----------------------------------------------------------------*/
+static void genInline (iCode *ic)
+{
+    char *buffer, *bp, *bp1;
+    
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    _G.inLine += (!options.asmpeep);
+
+    buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
+    strcpy(buffer,IC_INLINE(ic));
+
+    /* emit each line as a code */
+    while (*bp) {
+        if (*bp == '\n') {
+            *bp++ = '\0';
+
+           if(*bp1)
+             pic16_addpCode2pBlock(pb,pic16_AssembleLine(bp1));
+            bp1 = bp;
+        } else {
+            if (*bp == ':') {
+                bp++;
+                *bp = '\0';
+                bp++;
+                pic16_emitcode(bp1,"");
+                bp1 = bp;
+            } else
+                bp++;
+        }
+    }
+    if ((bp1 != bp) && *bp1)
+      pic16_addpCode2pBlock(pb,pic16_AssembleLine(bp1));
+
+    Safe_free(buffer);
+
+    _G.inLine -= (!options.asmpeep);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRRC - rotate right with carry                                */
+/*-----------------------------------------------------------------*/
+static void genRRC (iCode *ic)
+{
+  operand *left , *result ;
+  int size, offset = 0, same;
+
+  /* rotate right with carry */
+  left = IC_LEFT(ic);
+  result=IC_RESULT(ic);
+  pic16_aopOp (left,ic,FALSE);
+  pic16_aopOp (result,ic,FALSE);
+
+  DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
+
+  same = pic16_sameRegs(AOP(result),AOP(left));
+
+  size = AOP_SIZE(result);    
+
+  /* get the lsb and put it into the carry */
+  pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
+
+  offset = 0 ;
+
+  while(size--) {
+
+    if(same) {
+      pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
+    } else {
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+    }
+
+    offset++;
+  }
+
+  pic16_freeAsmop(left,NULL,ic,TRUE);
+  pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRLC - generate code for rotate left with carry               */
+/*-----------------------------------------------------------------*/
+static void genRLC (iCode *ic)
+{    
+  operand *left , *result ;
+  int size, offset = 0;
+  int same;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  /* rotate right with carry */
+  left = IC_LEFT(ic);
+  result=IC_RESULT(ic);
+  pic16_aopOp (left,ic,FALSE);
+  pic16_aopOp (result,ic,FALSE);
+
+  DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
+
+  same = pic16_sameRegs(AOP(result),AOP(left));
+
+  /* move it to the result */
+  size = AOP_SIZE(result);    
+
+  /* get the msb and put it into the carry */
+  pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
+
+  offset = 0 ;
+
+  while(size--) {
+
+    if(same) {
+      pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
+    } else {
+      pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+    }
+
+    offset++;
+  }
+
+
+  pic16_freeAsmop(left,NULL,ic,TRUE);
+  pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genGetHbit - generates code get highest order bit               */
+/*-----------------------------------------------------------------*/
+static void genGetHbit (iCode *ic)
+{
+    operand *left, *result;
+    left = IC_LEFT(ic);
+    result=IC_RESULT(ic);
+    pic16_aopOp (left,ic,FALSE);
+    pic16_aopOp (result,ic,FALSE);
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* get the highest order byte into a */
+    MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
+    if(AOP_TYPE(result) == AOP_CRY){
+        pic16_emitcode("rlc","a");
+        pic16_outBitC(result);
+    }
+    else{
+        pic16_emitcode("rl","a");
+        pic16_emitcode("anl","a,#0x01");
+        pic16_outAcc(result);
+    }
+
+
+    pic16_freeAsmop(left,NULL,ic,TRUE);
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* AccRol - rotate left accumulator by known count                 */
+/*-----------------------------------------------------------------*/
+static void AccRol (int shCount)
+{
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    shCount &= 0x0007;              // shCount : 0..7
+    switch(shCount){
+        case 0 :
+            break;
+        case 1 :
+            pic16_emitcode("rl","a");
+            break;
+        case 2 :
+            pic16_emitcode("rl","a");
+            pic16_emitcode("rl","a");
+            break;
+        case 3 :
+            pic16_emitcode("swap","a");
+            pic16_emitcode("rr","a");
+            break;
+        case 4 :
+            pic16_emitcode("swap","a");
+            break;
+        case 5 :
+            pic16_emitcode("swap","a");
+            pic16_emitcode("rl","a");
+            break;
+        case 6 :
+            pic16_emitcode("rr","a");
+            pic16_emitcode("rr","a");
+            break;
+        case 7 :
+            pic16_emitcode("rr","a");
+            break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccLsh - left shift accumulator by known count                  */
+/*-----------------------------------------------------------------*/
+static void AccLsh (int shCount)
+{
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if(shCount != 0){
+        if(shCount == 1)
+            pic16_emitcode("add","a,acc");
+        else 
+           if(shCount == 2) {
+            pic16_emitcode("add","a,acc");
+            pic16_emitcode("add","a,acc");
+        } else {
+            /* rotate left accumulator */
+            AccRol(shCount);
+            /* and kill the lower order bits */
+            pic16_emitcode("anl","a,#0x%02x", SLMask[shCount]);
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccRsh - right shift accumulator by known count                 */
+/*-----------------------------------------------------------------*/
+static void AccRsh (int shCount)
+{
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if(shCount != 0){
+        if(shCount == 1){
+            CLRC;
+            pic16_emitcode("rrc","a");
+        } else {
+            /* rotate right accumulator */
+            AccRol(8 - shCount);
+            /* and kill the higher order bits */
+            pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
+        }
+    }
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* AccSRsh - signed right shift accumulator by known count                 */
+/*-----------------------------------------------------------------*/
+static void AccSRsh (int shCount)
+{
+    symbol *tlbl ;
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if(shCount != 0){
+        if(shCount == 1){
+            pic16_emitcode("mov","c,acc.7");
+            pic16_emitcode("rrc","a");
+        } else if(shCount == 2){
+            pic16_emitcode("mov","c,acc.7");
+            pic16_emitcode("rrc","a");
+            pic16_emitcode("mov","c,acc.7");
+            pic16_emitcode("rrc","a");
+        } else {
+            tlbl = newiTempLabel(NULL);
+            /* rotate right accumulator */
+            AccRol(8 - shCount);
+            /* and kill the higher order bits */
+            pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
+            pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
+            pic16_emitcode("orl","a,#0x%02x",
+                     (unsigned char)~SRMask[shCount]);
+            pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+        }
+    }
+}
+#endif
+/*-----------------------------------------------------------------*/
+/* shiftR1Left2Result - shift right one byte from left to result   */
+/*-----------------------------------------------------------------*/
+static void shiftR1Left2ResultSigned (operand *left, int offl,
+                                operand *result, int offr,
+                                int shCount)
+{
+  int same;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
+
+  switch(shCount) {
+  case 1:
+    pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
+    if(same) 
+      pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
+    else {
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    }
+
+    break;
+  case 2:
+
+    pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
+    if(same) 
+      pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
+    else {
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    }
+    pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
+
+    break;
+
+  case 3:
+    if(same)
+      pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
+    else {
+      pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    }
+
+    pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
+
+    pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
+    pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
+
+    pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    break;
+
+  case 4:
+    pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
+    pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
+    pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
+    pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
+    pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
+    break;
+  case 5:
+    if(same) {
+      pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
+    } else {
+      pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
+    }
+    pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
+    pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
+    pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
+    pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
+    break;
+
+  case 6:
+    if(same) {
+      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
+      pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
+      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
+      pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
+      pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    } else {
+      pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
+      pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
+      pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
+    }
+    break;
+
+  case 7:
+    if(same) {
+      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
+      pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
+      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    } else {
+      pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
+      pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
+    }
+
+  default:
+    break;
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftR1Left2Result - shift right one byte from left to result   */
+/*-----------------------------------------------------------------*/
+static void shiftR1Left2Result (operand *left, int offl,
+                                operand *result, int offr,
+                                int shCount, int sign)
+{
+  int same;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
+
+  /* Copy the msb into the carry if signed. */
+  if(sign) {
+    shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
+    return;
+  }
+
+
+
+  switch(shCount) {
+  case 1:
+    emitCLRC;
+    if(same) 
+      pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
+    else {
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    }
+    break;
+  case 2:
+    emitCLRC;
+    if(same) {
+      pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
+    } else {
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    }
+    emitCLRC;
+    pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
+
+    break;
+  case 3:
+    if(same)
+      pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
+    else {
+      pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    }
+
+    pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
+    pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    break;
+      
+  case 4:
+    pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
+    pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
+    pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    break;
+
+  case 5:
+    pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
+    pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
+    pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    emitCLRC;
+    pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
+
+    break;
+  case 6:
+
+    pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
+    pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
+    pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
+    break;
+
+  case 7:
+
+    pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
+    pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
+
+    break;
+
+  default:
+    break;
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftL1Left2Result - shift left one byte from left to result    */
+/*-----------------------------------------------------------------*/
+static void shiftL1Left2Result (operand *left, int offl,
+                                operand *result, int offr, int shCount)
+{
+  int same;
+
+  //    char *l;
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
+  DEBUGpic16_emitcode ("; ***","same =  %d",same);
+    //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
+    //    MOVA(l);
+    /* shift left accumulator */
+    //AccLsh(shCount); // don't comment out just yet...
+  //    pic16_aopPut(AOP(result),"a",offr);
+
+  switch(shCount) {
+  case 1:
+    /* Shift left 1 bit position */
+    pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
+    if(same) {
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
+    } else {
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    }
+    break;
+  case 2:
+    pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
+    pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
+    pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
+    break;
+  case 3:
+    pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
+    pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
+    pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
+    break;
+  case 4:
+    pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
+    pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
+    pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
+    break;
+  case 5:
+    pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
+    pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
+    pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
+    break;
+  case 6:
+    pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
+    pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
+    pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
+    break;
+  case 7:
+    pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
+    pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
+    break;
+
+  default:
+    DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* movLeft2Result - move byte from left to result                  */
+/*-----------------------------------------------------------------*/
+static void movLeft2Result (operand *left, int offl,
+                            operand *result, int offr)
+{
+  char *l;
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
+    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
+
+    if (*l == '@' && (IS_AOP_PREG(result))) {
+      pic16_emitcode("mov","a,%s",l);
+      pic16_aopPut(AOP(result),"a",offr);
+    } else {
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+    }
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftL2Left2Result - shift left two bytes from left to result   */
+/*-----------------------------------------------------------------*/
+static void shiftL2Left2Result (operand *left, int offl,
+                                operand *result, int offr, int shCount)
+{
+
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  if(pic16_sameRegs(AOP(result), AOP(left))) {
+    switch(shCount) {
+    case 0:
+      break;
+    case 1:
+    case 2:
+    case 3:
+
+      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
+
+      while(--shCount) {
+       emitCLRC;
+       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
+       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
+      }
+
+      break;
+    case 4:
+    case 5:
+      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
+      pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
+      if(shCount >=5) {
+       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
+       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
+      }
+      break;
+    case 6:
+      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
+      pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
+      break;
+    case 7:
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
+    }
+
+  } else {
+    switch(shCount) {
+    case 0:
+      break;
+    case 1:
+    case 2:
+    case 3:
+      /* note, use a mov/add for the shift since the mov has a
+        chance of getting optimized out */
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
+
+      while(--shCount) {
+       emitCLRC;
+       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
+       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
+      }
+      break;
+
+    case 4:
+    case 5:
+      pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
+      pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
+      pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
+
+
+      if(shCount == 5) {
+       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
+       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
+      }
+      break;
+    case 6:
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
+      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
+
+      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
+      pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
+      break;
+    case 7:
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
+    }
+  }
+
+}
+/*-----------------------------------------------------------------*/
+/* shiftR2Left2Result - shift right two bytes from left to result  */
+/*-----------------------------------------------------------------*/
+static void shiftR2Left2Result (operand *left, int offl,
+                                operand *result, int offr,
+                                int shCount, int sign)
+{
+  int same=0;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  same = pic16_sameRegs(AOP(result), AOP(left));
+
+  if(same && ((offl + MSB16) == offr)){
+    same=1;
+    /* don't crash result[offr] */
+    MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
+    pic16_emitcode("xch","a,%s", pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
+  }
+/* else {
+    movLeft2Result(left,offl, result, offr);
+    MOVA(pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
+  }
+*/
+  /* a:x >> shCount (x = lsb(result))*/
+/*
+  if(sign)
+    AccAXRshS( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
+  else {
+    AccAXRsh( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
+*/
+  switch(shCount) {
+  case 0:
+    break;
+  case 1:
+  case 2:
+  case 3:
+    if(sign)
+      pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
+    else
+      emitCLRC;
+
+    if(same) {
+      pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
+    } else {
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
+    }
+
+    while(--shCount) {
+      if(sign)
+       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
+      else
+       emitCLRC;
+      pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
+    }
+    break;
+  case 4:
+  case 5:
+    if(same) {
+
+      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
+      pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
+
+      pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
+    } else {
+      pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
+
+      pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
+      pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
+    }
+
+    if(shCount >=5) {
+      pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
+    }
+
+    if(sign) {
+      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
+      pic16_emitpcode(POC_BTFSC, 
+               pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
+    }
+
+    break;
+
+  case 6:
+    if(same) {
+
+      pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
+
+      pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
+      if(sign) {
+       pic16_emitpcode(POC_BTFSC, 
+                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
+       pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
+      }
+      pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
+    } else {
+      pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
+      if(sign) {
+       pic16_emitpcode(POC_BTFSC, 
+                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
+       pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
+      }
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
+      //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
+
+       
+    }
+
+    break;
+  case 7:
+    pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
+    pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
+    pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
+    pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
+    if(sign) {
+      emitSKPNC;
+      pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
+    } else 
+      pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
+  }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* shiftLLeftOrResult - shift left one byte from left, or to result*/
+/*-----------------------------------------------------------------*/
+static void shiftLLeftOrResult (operand *left, int offl,
+                                operand *result, int offr, int shCount)
+{
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
+    /* shift left accumulator */
+    AccLsh(shCount);
+    /* or with result */
+    pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
+    /* back to result */
+    pic16_aopPut(AOP(result),"a",offr);
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftRLeftOrResult - shift right one byte from left,or to result*/
+/*-----------------------------------------------------------------*/
+static void shiftRLeftOrResult (operand *left, int offl,
+                                operand *result, int offr, int shCount)
+{
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
+    /* shift right accumulator */
+    AccRsh(shCount);
+    /* or with result */
+    pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
+    /* back to result */
+    pic16_aopPut(AOP(result),"a",offr);
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshOne - left shift a one byte quantity by known count       */
+/*-----------------------------------------------------------------*/
+static void genlshOne (operand *result, operand *left, int shCount)
+{       
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    shiftL1Left2Result(left, LSB, result, LSB, shCount);
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshTwo - left shift two bytes by known amount != 0           */
+/*-----------------------------------------------------------------*/
+static void genlshTwo (operand *result,operand *left, int shCount)
+{
+    int size;
+    
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    size = pic16_getDataSize(result);
+
+    /* if shCount >= 8 */
+    if (shCount >= 8) {
+        shCount -= 8 ;
+
+        if (size > 1){
+            if (shCount)
+                shiftL1Left2Result(left, LSB, result, MSB16, shCount);
+            else 
+                movLeft2Result(left, LSB, result, MSB16);
+        }
+       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
+    }
+
+    /*  1 <= shCount <= 7 */
+    else {  
+        if(size == 1)
+            shiftL1Left2Result(left, LSB, result, LSB, shCount); 
+        else 
+            shiftL2Left2Result(left, LSB, result, LSB, shCount);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftLLong - shift left one long from left to result            */
+/* offl = LSB or MSB16                                             */
+/*-----------------------------------------------------------------*/
+static void shiftLLong (operand *left, operand *result, int offr )
+{
+    char *l;
+    int size = AOP_SIZE(result);
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if(size >= LSB+offr){
+        l = pic16_aopGet(AOP(left),LSB,FALSE,FALSE);
+        MOVA(l);
+        pic16_emitcode("add","a,acc");
+       if (pic16_sameRegs(AOP(left),AOP(result)) && 
+           size >= MSB16+offr && offr != LSB )
+           pic16_emitcode("xch","a,%s",
+                    pic16_aopGet(AOP(left),LSB+offr,FALSE,FALSE));
+       else        
+           pic16_aopPut(AOP(result),"a",LSB+offr);
+    }
+
+    if(size >= MSB16+offr){
+       if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
+           l = pic16_aopGet(AOP(left),MSB16,FALSE,FALSE);
+           MOVA(l);
+       }
+        pic16_emitcode("rlc","a");
+       if (pic16_sameRegs(AOP(left),AOP(result)) && 
+           size >= MSB24+offr && offr != LSB)
+           pic16_emitcode("xch","a,%s",
+                    pic16_aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
+       else        
+           pic16_aopPut(AOP(result),"a",MSB16+offr);
+    }
+
+    if(size >= MSB24+offr){
+       if (!(pic16_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
+           l = pic16_aopGet(AOP(left),MSB24,FALSE,FALSE);
+           MOVA(l);
+       }
+        pic16_emitcode("rlc","a");
+       if (pic16_sameRegs(AOP(left),AOP(result)) && 
+           size >= MSB32+offr && offr != LSB )
+           pic16_emitcode("xch","a,%s",
+                    pic16_aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
+       else        
+           pic16_aopPut(AOP(result),"a",MSB24+offr);
+    }
+
+    if(size > MSB32+offr){
+       if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
+           l = pic16_aopGet(AOP(left),MSB32,FALSE,FALSE);
+           MOVA(l);    
+       }
+        pic16_emitcode("rlc","a");
+        pic16_aopPut(AOP(result),"a",MSB32+offr);
+    }
+    if(offr != LSB)
+        pic16_aopPut(AOP(result),zero,LSB);       
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshFour - shift four byte by a known amount != 0             */
+/*-----------------------------------------------------------------*/
+static void genlshFour (operand *result, operand *left, int shCount)
+{
+    int size;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    size = AOP_SIZE(result);
+
+    /* if shifting more that 3 bytes */
+    if (shCount >= 24 ) {
+        shCount -= 24;
+        if (shCount)
+            /* lowest order of left goes to the highest
+            order of the destination */
+            shiftL1Left2Result(left, LSB, result, MSB32, shCount);
+        else
+            movLeft2Result(left, LSB, result, MSB32);
+        pic16_aopPut(AOP(result),zero,LSB);
+        pic16_aopPut(AOP(result),zero,MSB16);
+        pic16_aopPut(AOP(result),zero,MSB32);
+        return;
+    }
+
+    /* more than two bytes */
+    else if ( shCount >= 16 ) {
+        /* lower order two bytes goes to higher order two bytes */
+        shCount -= 16;
+        /* if some more remaining */
+        if (shCount)
+            shiftL2Left2Result(left, LSB, result, MSB24, shCount);
+        else {
+            movLeft2Result(left, MSB16, result, MSB32);
+            movLeft2Result(left, LSB, result, MSB24);
+        }
+        pic16_aopPut(AOP(result),zero,MSB16);
+        pic16_aopPut(AOP(result),zero,LSB);
+        return;
+    }    
+
+    /* if more than 1 byte */
+    else if ( shCount >= 8 ) {
+        /* lower order three bytes goes to higher order  three bytes */
+        shCount -= 8;
+        if(size == 2){
+            if(shCount)
+                shiftL1Left2Result(left, LSB, result, MSB16, shCount);
+            else
+                movLeft2Result(left, LSB, result, MSB16);
+        }
+        else{   /* size = 4 */
+            if(shCount == 0){
+                movLeft2Result(left, MSB24, result, MSB32);
+                movLeft2Result(left, MSB16, result, MSB24);
+                movLeft2Result(left, LSB, result, MSB16);
+                pic16_aopPut(AOP(result),zero,LSB);
+            }
+            else if(shCount == 1)
+                shiftLLong(left, result, MSB16);
+            else{
+                shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
+                shiftL1Left2Result(left, LSB, result, MSB16, shCount);
+                shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
+                pic16_aopPut(AOP(result),zero,LSB);
+            }
+        }
+    }
+
+    /* 1 <= shCount <= 7 */
+    else if(shCount <= 2){
+        shiftLLong(left, result, LSB);
+        if(shCount == 2)
+            shiftLLong(result, result, LSB);
+    }
+    /* 3 <= shCount <= 7, optimize */
+    else{
+        shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
+        shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
+        shiftL2Left2Result(left, LSB, result, LSB, shCount);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genLeftShiftLiteral - left shifting by known count              */
+/*-----------------------------------------------------------------*/
+static void genLeftShiftLiteral (operand *left,
+                                 operand *right,
+                                 operand *result,
+                                 iCode *ic)
+{    
+    int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
+    int size;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    pic16_freeAsmop(right,NULL,ic,TRUE);
+
+    pic16_aopOp(left,ic,FALSE);
+    pic16_aopOp(result,ic,FALSE);
+
+    size = getSize(operandType(result));
+
+#if VIEW_SIZE
+    pic16_emitcode("; shift left ","result %d, left %d",size,
+             AOP_SIZE(left));
+#endif
+
+    /* I suppose that the left size >= result size */
+    if(shCount == 0){
+        while(size--){
+            movLeft2Result(left, size, result, size);
+        }
+    }
+
+    else if(shCount >= (size * 8))
+        while(size--)
+            pic16_aopPut(AOP(result),zero,size);
+    else{
+        switch (size) {
+            case 1:
+                genlshOne (result,left,shCount);
+                break;
+
+            case 2:
+            case 3:
+                genlshTwo (result,left,shCount);
+                break;
+
+            case 4:
+                genlshFour (result,left,shCount);
+                break;
+        }
+    }
+    pic16_freeAsmop(left,NULL,ic,TRUE);
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*
+ * genMultiAsm - repeat assembly instruction for size of register.
+ * if endian == 1, then the high byte (i.e base address + size of 
+ * register) is used first else the low byte is used first;
+ *-----------------------------------------------------------------*/
+static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
+{
+
+  int offset = 0;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  if(!reg)
+    return;
+
+  if(!endian) {
+    endian = 1;
+  } else {
+    endian = -1;
+    offset = size-1;
+  }
+
+  while(size--) {
+    pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
+    offset += endian;
+  }
+
+}
+/*-----------------------------------------------------------------*/
+/* genLeftShift - generates code for left shifting                 */
+/*-----------------------------------------------------------------*/
+static void genLeftShift (iCode *ic)
+{
+  operand *left,*right, *result;
+  int size, offset;
+  char *l;
+  symbol *tlbl , *tlbl1;
+  pCodeOp *pctemp;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  right = IC_RIGHT(ic);
+  left  = IC_LEFT(ic);
+  result = IC_RESULT(ic);
+
+  pic16_aopOp(right,ic,FALSE);
+
+  /* if the shift count is known then do it 
+     as efficiently as possible */
+  if (AOP_TYPE(right) == AOP_LIT) {
+    genLeftShiftLiteral (left,right,result,ic);
+    return ;
+  }
+
+  /* shift count is unknown then we have to form 
+     a loop get the loop count in B : Note: we take
+     only the lower order byte since shifting
+     more that 32 bits make no sense anyway, ( the
+     largest size of an object can be only 32 bits ) */  
+
+    
+  pic16_aopOp(left,ic,FALSE);
+  pic16_aopOp(result,ic,FALSE);
+
+  /* now move the left to the result if they are not the
+     same */
+  if (!pic16_sameRegs(AOP(left),AOP(result)) && 
+      AOP_SIZE(result) > 1) {
+
+    size = AOP_SIZE(result);
+    offset=0;
+    while (size--) {
+      l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
+      if (*l == '@' && (IS_AOP_PREG(result))) {
+
+       pic16_emitcode("mov","a,%s",l);
+       pic16_aopPut(AOP(result),"a",offset);
+      } else {
+       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
+       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
+       //pic16_aopPut(AOP(result),l,offset);
+      }
+      offset++;
+    }
+  }
+
+  size = AOP_SIZE(result);
+
+  /* if it is only one byte then */
+  if (size == 1) {
+    if(optimized_for_speed) {
+      pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
+      pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
+      pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
+      pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
+      pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
+      pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
+    } else {
+
+      tlbl = newiTempLabel(NULL);
+      if (!pic16_sameRegs(AOP(left),AOP(result))) {
+       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
+       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
+      }
+
+      pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
+      pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
+      pic16_emitpLabel(tlbl->key);
+      pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
+      emitSKPC;
+      pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
+    }
+    goto release ;
+  }
+    
+  if (pic16_sameRegs(AOP(left),AOP(result))) {
+
+    tlbl = newiTempLabel(NULL);
+    pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
+    genMultiAsm(POC_RRCF, result, size,1);
+    pic16_emitpLabel(tlbl->key);
+    genMultiAsm(POC_RLCF, result, size,0);
+    pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
+    emitSKPC;
+    pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
+    goto release;
+  }
+
+  //tlbl = newiTempLabel(NULL);
+  //offset = 0 ;   
+  //tlbl1 = newiTempLabel(NULL);
+
+  //reAdjustPreg(AOP(result));    
+    
+  //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
+  //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
+  //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
+  //MOVA(l);
+  //pic16_emitcode("add","a,acc");         
+  //pic16_aopPut(AOP(result),"a",offset++);
+  //while (--size) {
+  //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
+  //  MOVA(l);
+  //  pic16_emitcode("rlc","a");         
+  //  pic16_aopPut(AOP(result),"a",offset++);
+  //}
+  //reAdjustPreg(AOP(result));
+
+  //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
+  //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
+
+
+  tlbl = newiTempLabel(NULL);
+  tlbl1= newiTempLabel(NULL);
+
+  size = AOP_SIZE(result);
+  offset = 1;
+
+  pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
+
+  pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+
+  /* offset should be 0, 1 or 3 */
+  pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
+  emitSKPNZ;
+  pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
+
+  pic16_emitpcode(POC_MOVWF, pctemp);
+
+
+  pic16_emitpLabel(tlbl->key);
+
+  emitCLRC;
+  pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
+  while(--size)
+    pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
+
+  pic16_emitpcode(POC_DECFSZ,  pctemp);
+  pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
+  pic16_emitpLabel(tlbl1->key);
+
+  pic16_popReleaseTempReg(pctemp);
+
+
+ release:
+  pic16_freeAsmop (right,NULL,ic,TRUE);
+  pic16_freeAsmop(left,NULL,ic,TRUE);
+  pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshOne - right shift a one byte quantity by known count      */
+/*-----------------------------------------------------------------*/
+static void genrshOne (operand *result, operand *left,
+                       int shCount, int sign)
+{
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshTwo - right shift two bytes by known amount != 0          */
+/*-----------------------------------------------------------------*/
+static void genrshTwo (operand *result,operand *left,
+                       int shCount, int sign)
+{
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  /* if shCount >= 8 */
+  if (shCount >= 8) {
+    shCount -= 8 ;
+    if (shCount)
+      shiftR1Left2Result(left, MSB16, result, LSB,
+                        shCount, sign);
+    else
+      movLeft2Result(left, MSB16, result, LSB);
+
+    pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
+
+    if(sign) {
+      pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
+      pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
+    }
+  }
+
+  /*  1 <= shCount <= 7 */
+  else
+    shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftRLong - shift right one long from left to result           */
+/* offl = LSB or MSB16                                             */
+/*-----------------------------------------------------------------*/
+static void shiftRLong (operand *left, int offl,
+                        operand *result, int sign)
+{
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if(!sign)
+        pic16_emitcode("clr","c");
+    MOVA(pic16_aopGet(AOP(left),MSB32,FALSE,FALSE));
+    if(sign)
+        pic16_emitcode("mov","c,acc.7");
+    pic16_emitcode("rrc","a");
+    pic16_aopPut(AOP(result),"a",MSB32-offl);
+    if(offl == MSB16)
+        /* add sign of "a" */
+        pic16_addSign(result, MSB32, sign);
+
+    MOVA(pic16_aopGet(AOP(left),MSB24,FALSE,FALSE));
+    pic16_emitcode("rrc","a");
+    pic16_aopPut(AOP(result),"a",MSB24-offl);
+
+    MOVA(pic16_aopGet(AOP(left),MSB16,FALSE,FALSE));
+    pic16_emitcode("rrc","a");
+    pic16_aopPut(AOP(result),"a",MSB16-offl);
+
+    if(offl == LSB){
+        MOVA(pic16_aopGet(AOP(left),LSB,FALSE,FALSE));
+        pic16_emitcode("rrc","a");
+        pic16_aopPut(AOP(result),"a",LSB);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshFour - shift four byte by a known amount != 0             */
+/*-----------------------------------------------------------------*/
+static void genrshFour (operand *result, operand *left,
+                        int shCount, int sign)
+{
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  /* if shifting more that 3 bytes */
+  if(shCount >= 24 ) {
+    shCount -= 24;
+    if(shCount)
+      shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
+    else
+      movLeft2Result(left, MSB32, result, LSB);
+
+    pic16_addSign(result, MSB16, sign);
+  }
+  else if(shCount >= 16){
+    shCount -= 16;
+    if(shCount)
+      shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
+    else{
+      movLeft2Result(left, MSB24, result, LSB);
+      movLeft2Result(left, MSB32, result, MSB16);
+    }
+    pic16_addSign(result, MSB24, sign);
+  }
+  else if(shCount >= 8){
+    shCount -= 8;
+    if(shCount == 1)
+      shiftRLong(left, MSB16, result, sign);
+    else if(shCount == 0){
+      movLeft2Result(left, MSB16, result, LSB);
+      movLeft2Result(left, MSB24, result, MSB16);
+      movLeft2Result(left, MSB32, result, MSB24);
+      pic16_addSign(result, MSB32, sign);
+    }
+    else{
+      shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
+      shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
+      /* the last shift is signed */
+      shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
+      pic16_addSign(result, MSB32, sign);
+    }
+  }
+  else{   /* 1 <= shCount <= 7 */
+    if(shCount <= 2){
+      shiftRLong(left, LSB, result, sign);
+      if(shCount == 2)
+       shiftRLong(result, LSB, result, sign);
+    }
+    else{
+      shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
+      shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
+      shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
+    }
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* genRightShiftLiteral - right shifting by known count            */
+/*-----------------------------------------------------------------*/
+static void genRightShiftLiteral (operand *left,
+                                  operand *right,
+                                  operand *result,
+                                  iCode *ic,
+                                  int sign)
+{    
+  int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
+  int lsize,res_size;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  pic16_freeAsmop(right,NULL,ic,TRUE);
+
+  pic16_aopOp(left,ic,FALSE);
+  pic16_aopOp(result,ic,FALSE);
+
+#if VIEW_SIZE
+  pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
+                AOP_SIZE(left));
+#endif
+
+  lsize = pic16_getDataSize(left);
+  res_size = pic16_getDataSize(result);
+  /* test the LEFT size !!! */
+
+  /* I suppose that the left size >= result size */
+  if(shCount == 0){
+    while(res_size--)
+      movLeft2Result(left, lsize, result, res_size);
+  }
+
+  else if(shCount >= (lsize * 8)){
+
+    if(res_size == 1) {
+      pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
+      if(sign) {
+       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
+       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
+      }
+    } else {
+
+      if(sign) {
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
+       while(res_size--)
+         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
+
+      } else {
+
+       while(res_size--)
+         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
+      }
+    }
+  } else {
+
+    switch (res_size) {
+    case 1:
+      genrshOne (result,left,shCount,sign);
+      break;
+
+    case 2:
+      genrshTwo (result,left,shCount,sign);
+      break;
+
+    case 4:
+      genrshFour (result,left,shCount,sign);
+      break;
+    default :
+      break;
+    }
+
+  }
+
+  pic16_freeAsmop(left,NULL,ic,TRUE);
+  pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genSignedRightShift - right shift of signed number              */
+/*-----------------------------------------------------------------*/
+static void genSignedRightShift (iCode *ic)
+{
+  operand *right, *left, *result;
+  int size, offset;
+  //  char *l;
+  symbol *tlbl, *tlbl1 ;
+  pCodeOp *pctemp;
+
+  //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
+
+  /* we do it the hard way put the shift count in b
+     and loop thru preserving the sign */
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  right = IC_RIGHT(ic);
+  left  = IC_LEFT(ic);
+  result = IC_RESULT(ic);
+
+  pic16_aopOp(right,ic,FALSE);  
+  pic16_aopOp(left,ic,FALSE);
+  pic16_aopOp(result,ic,FALSE);
+
+
+  if ( AOP_TYPE(right) == AOP_LIT) {
+    genRightShiftLiteral (left,right,result,ic,1);
+    return ;
+  }
+  /* shift count is unknown then we have to form 
+     a loop get the loop count in B : Note: we take
+     only the lower order byte since shifting
+     more that 32 bits make no sense anyway, ( the
+     largest size of an object can be only 32 bits ) */  
+
+  //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
+  //pic16_emitcode("inc","b");
+  //pic16_freeAsmop (right,NULL,ic,TRUE);
+  //pic16_aopOp(left,ic,FALSE);
+  //pic16_aopOp(result,ic,FALSE);
+
+  /* now move the left to the result if they are not the
+     same */
+  if (!pic16_sameRegs(AOP(left),AOP(result)) && 
+      AOP_SIZE(result) > 1) {
+
+    size = AOP_SIZE(result);
+    offset=0;
+    while (size--) { 
+      /*
+       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
+       if (*l == '@' && IS_AOP_PREG(result)) {
+
+       pic16_emitcode("mov","a,%s",l);
+       pic16_aopPut(AOP(result),"a",offset);
+       } else
+       pic16_aopPut(AOP(result),l,offset);
+      */
+      pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
+      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
+
+      offset++;
+    }
+  }
+
+  /* mov the highest order bit to OVR */    
+  tlbl = newiTempLabel(NULL);
+  tlbl1= newiTempLabel(NULL);
+
+  size = AOP_SIZE(result);
+  offset = size - 1;
+
+  pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
+
+  pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+
+  /* offset should be 0, 1 or 3 */
+  pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
+  emitSKPNZ;
+  pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
+
+  pic16_emitpcode(POC_MOVWF, pctemp);
+
+
+  pic16_emitpLabel(tlbl->key);
+
+  pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
+  pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
+
+  while(--size) {
+    pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
+  }
+
+  pic16_emitpcode(POC_DECFSZ,  pctemp);
+  pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
+  pic16_emitpLabel(tlbl1->key);
+
+  pic16_popReleaseTempReg(pctemp);
+#if 0
+  size = AOP_SIZE(result);
+  offset = size - 1;
+  pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
+  pic16_emitcode("rlc","a");
+  pic16_emitcode("mov","ov,c");
+  /* if it is only one byte then */
+  if (size == 1) {
+    l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
+    MOVA(l);
+    pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
+    pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+    pic16_emitcode("mov","c,ov");
+    pic16_emitcode("rrc","a");
+    pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
+    pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
+    pic16_aopPut(AOP(result),"a",0);
+    goto release ;
+  }
+
+  reAdjustPreg(AOP(result));
+  pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
+  pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
+  pic16_emitcode("mov","c,ov");
+  while (size--) {
+    l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
+    MOVA(l);
+    pic16_emitcode("rrc","a");         
+    pic16_aopPut(AOP(result),"a",offset--);
+  }
+  reAdjustPreg(AOP(result));
+  pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
+  pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
+
+ release:
+#endif
+
+  pic16_freeAsmop(left,NULL,ic,TRUE);
+  pic16_freeAsmop(result,NULL,ic,TRUE);
+  pic16_freeAsmop(right,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRightShift - generate code for right shifting                */
+/*-----------------------------------------------------------------*/
+static void genRightShift (iCode *ic)
+{
+    operand *right, *left, *result;
+    sym_link *retype ;
+    int size, offset;
+    char *l;
+    symbol *tlbl, *tlbl1 ;
+
+    /* if signed then we do it the hard way preserve the
+    sign bit moving it inwards */
+    retype = getSpec(operandType(IC_RESULT(ic)));
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    if (!SPEC_USIGN(retype)) {
+        genSignedRightShift (ic);
+        return ;
+    }
+
+    /* signed & unsigned types are treated the same : i.e. the
+    signed is NOT propagated inwards : quoting from the
+    ANSI - standard : "for E1 >> E2, is equivalent to division
+    by 2**E2 if unsigned or if it has a non-negative value,
+    otherwise the result is implementation defined ", MY definition
+    is that the sign does not get propagated */
+
+    right = IC_RIGHT(ic);
+    left  = IC_LEFT(ic);
+    result = IC_RESULT(ic);
+
+    pic16_aopOp(right,ic,FALSE);
+
+    /* if the shift count is known then do it 
+    as efficiently as possible */
+    if (AOP_TYPE(right) == AOP_LIT) {
+        genRightShiftLiteral (left,right,result,ic, 0);
+        return ;
+    }
+
+    /* shift count is unknown then we have to form 
+    a loop get the loop count in B : Note: we take
+    only the lower order byte since shifting
+    more that 32 bits make no sense anyway, ( the
+    largest size of an object can be only 32 bits ) */  
+
+    pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
+    pic16_emitcode("inc","b");
+    pic16_aopOp(left,ic,FALSE);
+    pic16_aopOp(result,ic,FALSE);
+
+    /* now move the left to the result if they are not the
+    same */
+    if (!pic16_sameRegs(AOP(left),AOP(result)) && 
+        AOP_SIZE(result) > 1) {
+
+        size = AOP_SIZE(result);
+        offset=0;
+        while (size--) {
+            l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
+            if (*l == '@' && IS_AOP_PREG(result)) {
+
+                pic16_emitcode("mov","a,%s",l);
+                pic16_aopPut(AOP(result),"a",offset);
+            } else
+                pic16_aopPut(AOP(result),l,offset);
+            offset++;
+        }
+    }
+
+    tlbl = newiTempLabel(NULL);
+    tlbl1= newiTempLabel(NULL);
+    size = AOP_SIZE(result);
+    offset = size - 1;
+
+    /* if it is only one byte then */
+    if (size == 1) {
+
+      tlbl = newiTempLabel(NULL);
+      if (!pic16_sameRegs(AOP(left),AOP(result))) {
+       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
+       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
+      }
+
+      pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
+      pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
+      pic16_emitpLabel(tlbl->key);
+      pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
+      emitSKPC;
+      pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
+
+      goto release ;
+    }
+
+    reAdjustPreg(AOP(result));
+    pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
+    pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
+    CLRC;
+    while (size--) {
+        l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
+        MOVA(l);
+        pic16_emitcode("rrc","a");         
+        pic16_aopPut(AOP(result),"a",offset--);
+    }
+    reAdjustPreg(AOP(result));
+
+    pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
+    pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
+
+release:
+    pic16_freeAsmop(left,NULL,ic,TRUE);
+    pic16_freeAsmop (right,NULL,ic,TRUE);
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genUnpackBits - generates code for unpacking bits               */
+/*-----------------------------------------------------------------*/
+static void genUnpackBits (operand *result, char *rname, int ptype)
+{    
+    int shCnt ;
+    int rlen = 0 ;
+    sym_link *etype;
+    int offset = 0 ;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    etype = getSpec(operandType(result));
+
+    /* read the first byte  */
+    switch (ptype) {
+
+    case POINTER:
+    case IPOINTER:
+       pic16_emitcode("mov","a,@%s",rname);
+       break;
+       
+    case PPOINTER:
+       pic16_emitcode("movx","a,@%s",rname);
+       break;
+       
+    case FPOINTER:
+       pic16_emitcode("movx","a,@dptr");
+       break;
+
+    case CPOINTER:
+       pic16_emitcode("clr","a");
+       pic16_emitcode("movc","a","@a+dptr");
+       break;
+
+    case GPOINTER:
+       pic16_emitcode("lcall","__gptrget");
+       break;
+    }
+
+    /* if we have bitdisplacement then it fits   */
+    /* into this byte completely or if length is */
+    /* less than a byte                          */
+    if ((shCnt = SPEC_BSTR(etype)) || 
+        (SPEC_BLEN(etype) <= 8))  {
+
+        /* shift right acc */
+        AccRsh(shCnt);
+
+        pic16_emitcode("anl","a,#0x%02x",
+                 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
+        pic16_aopPut(AOP(result),"a",offset);
+        return ;
+    }
+
+    /* bit field did not fit in a byte  */
+    rlen = SPEC_BLEN(etype) - 8;
+    pic16_aopPut(AOP(result),"a",offset++);
+
+    while (1)  {
+
+       switch (ptype) {
+       case POINTER:
+       case IPOINTER:
+           pic16_emitcode("inc","%s",rname);
+           pic16_emitcode("mov","a,@%s",rname);
+           break;
+           
+       case PPOINTER:
+           pic16_emitcode("inc","%s",rname);
+           pic16_emitcode("movx","a,@%s",rname);
+           break;
+
+       case FPOINTER:
+           pic16_emitcode("inc","dptr");
+           pic16_emitcode("movx","a,@dptr");
+           break;
+           
+       case CPOINTER:
+           pic16_emitcode("clr","a");
+           pic16_emitcode("inc","dptr");
+           pic16_emitcode("movc","a","@a+dptr");
+           break;
+           
+       case GPOINTER:
+           pic16_emitcode("inc","dptr");
+           pic16_emitcode("lcall","__gptrget");
+           break;
+       }
+
+       rlen -= 8;            
+       /* if we are done */
+       if ( rlen <= 0 )
+           break ;
+       
+       pic16_aopPut(AOP(result),"a",offset++);
+                                     
+    }
+    
+    if (rlen) {
+       pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
+       pic16_aopPut(AOP(result),"a",offset);          
+    }
+    
+    return ;
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* genDataPointerGet - generates code when ptr offset is known     */
+/*-----------------------------------------------------------------*/
+static void genDataPointerGet (operand *left, 
+                              operand *result, 
+                              iCode *ic)
+{
+  int size , offset = 0;
+
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+
+  /* optimization - most of the time, left and result are the same
+   * address, but different types. for the pic code, we could omit
+   * the following
+   */
+
+  pic16_aopOp(result,ic,TRUE);
+
+  DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
+
+  pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+
+  size = AOP_SIZE(result);
+
+  while (size--) {
+    pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+    offset++;
+  }
+
+  pic16_freeAsmop(left,NULL,ic,TRUE);
+  pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+#endif
+/*-----------------------------------------------------------------*/
+/* genNearPointerGet - pic16_emitcode for near pointer fetch             */
+/*-----------------------------------------------------------------*/
+static void genNearPointerGet (operand *left, 
+                              operand *result, 
+                              iCode *ic)
+{
+    asmop *aop = NULL;
+    //regs *preg = NULL ;
+    char *rname ;
+    sym_link *rtype, *retype;
+    sym_link *ltype = operandType(left);    
+    //char buffer[80];
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    rtype = operandType(result);
+    retype= getSpec(rtype);
+    
+    pic16_aopOp(left,ic,FALSE);
+    
+    /* if left is rematerialisable and
+       result is not bit variable type and
+       the left is pointer to data space i.e
+       lower 128 bytes of space */
+    if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
+       !IS_BITVAR(retype)         &&
+       DCL_TYPE(ltype) == POINTER) {
+      //genDataPointerGet (left,result,ic);
+       return ;
+    }
+    
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+       /* if the value is already in a pointer register
+       then don't need anything more */
+    if (!AOP_INPREG(AOP(left))) {
+       /* otherwise get a free pointer register */
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+/*
+       aop = newAsmop(0);
+       preg = getFreePtr(ic,&aop,FALSE);
+       pic16_emitcode("mov","%s,%s",
+               preg->name,
+               pic16_aopGet(AOP(left),0,FALSE,TRUE));
+       rname = preg->name ;
+*/
+    rname ="BAD";
+    } else
+       rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
+    
+    pic16_aopOp (result,ic,FALSE);
+    
+      /* if bitfield then unpack the bits */
+    if (IS_BITVAR(retype)) 
+       genUnpackBits (result,rname,POINTER);
+    else {
+       /* we have can just get the values */
+      int size = AOP_SIZE(result);
+      int offset = 0 ; 
+       
+      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
+      while(size--) {
+       pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
+       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
+       if(size)
+         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
+      }
+/*
+       while (size--) {
+           if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
+
+               pic16_emitcode("mov","a,@%s",rname);
+               pic16_aopPut(AOP(result),"a",offset);
+           } else {
+               sprintf(buffer,"@%s",rname);
+               pic16_aopPut(AOP(result),buffer,offset);
+           }
+           offset++ ;
+           if (size)
+               pic16_emitcode("inc","%s",rname);
+       }
+*/
+    }
+
+    /* now some housekeeping stuff */
+    if (aop) {
+       /* we had to allocate for this iCode */
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+       pic16_freeAsmop(NULL,aop,ic,TRUE);
+    } else { 
+       /* we did not allocate which means left
+          already in a pointer register, then
+          if size > 0 && this could be used again
+          we have to point it back to where it 
+          belongs */
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+       if (AOP_SIZE(result) > 1 &&
+           !OP_SYMBOL(left)->remat &&
+           ( OP_SYMBOL(left)->liveTo > ic->seq ||
+             ic->depth )) {
+           int size = AOP_SIZE(result) - 1;
+           while (size--)
+               pic16_emitcode("dec","%s",rname);
+       }
+    }
+
+    /* done */
+    pic16_freeAsmop(left,NULL,ic,TRUE);
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+     
+}
+
+/*-----------------------------------------------------------------*/
+/* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
+/*-----------------------------------------------------------------*/
+static void genPagedPointerGet (operand *left, 
+                              operand *result, 
+                              iCode *ic)
+{
+    asmop *aop = NULL;
+    regs *preg = NULL ;
+    char *rname ;
+    sym_link *rtype, *retype;    
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    rtype = operandType(result);
+    retype= getSpec(rtype);
+    
+    pic16_aopOp(left,ic,FALSE);
+
+  /* if the value is already in a pointer register
+       then don't need anything more */
+    if (!AOP_INPREG(AOP(left))) {
+       /* otherwise get a free pointer register */
+       aop = newAsmop(0);
+       preg = getFreePtr(ic,&aop,FALSE);
+       pic16_emitcode("mov","%s,%s",
+               preg->name,
+               pic16_aopGet(AOP(left),0,FALSE,TRUE));
+       rname = preg->name ;
+    } else
+       rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
+    
+    pic16_freeAsmop(left,NULL,ic,TRUE);
+    pic16_aopOp (result,ic,FALSE);
+
+    /* if bitfield then unpack the bits */
+    if (IS_BITVAR(retype)) 
+       genUnpackBits (result,rname,PPOINTER);
+    else {
+       /* we have can just get the values */
+       int size = AOP_SIZE(result);
+       int offset = 0 ;        
+       
+       while (size--) {
+           
+           pic16_emitcode("movx","a,@%s",rname);
+           pic16_aopPut(AOP(result),"a",offset);
+           
+           offset++ ;
+           
+           if (size)
+               pic16_emitcode("inc","%s",rname);
+       }
+    }
+
+    /* now some housekeeping stuff */
+    if (aop) {
+       /* we had to allocate for this iCode */
+       pic16_freeAsmop(NULL,aop,ic,TRUE);
+    } else { 
+       /* we did not allocate which means left
+          already in a pointer register, then
+          if size > 0 && this could be used again
+          we have to point it back to where it 
+          belongs */
+       if (AOP_SIZE(result) > 1 &&
+           !OP_SYMBOL(left)->remat &&
+           ( OP_SYMBOL(left)->liveTo > ic->seq ||
+             ic->depth )) {
+           int size = AOP_SIZE(result) - 1;
+           while (size--)
+               pic16_emitcode("dec","%s",rname);
+       }
+    }
+
+    /* done */
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+    
+       
+}
+
+/*-----------------------------------------------------------------*/
+/* genFarPointerGet - gget value from far space                    */
+/*-----------------------------------------------------------------*/
+static void genFarPointerGet (operand *left,
+                              operand *result, iCode *ic)
+{
+    int size, offset ;
+    sym_link *retype = getSpec(operandType(result));
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    pic16_aopOp(left,ic,FALSE);
+
+    /* if the operand is already in dptr 
+    then we do nothing else we move the value to dptr */
+    if (AOP_TYPE(left) != AOP_STR) {
+        /* if this is remateriazable */
+        if (AOP_TYPE(left) == AOP_IMMD)
+            pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
+        else { /* we need to get it byte by byte */
+            pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
+            pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
+            if (options.model == MODEL_FLAT24)
+            {
+               pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
+            }
+        }
+    }
+    /* so dptr know contains the address */
+    pic16_freeAsmop(left,NULL,ic,TRUE);
+    pic16_aopOp(result,ic,FALSE);
+
+    /* if bit then unpack */
+    if (IS_BITVAR(retype)) 
+        genUnpackBits(result,"dptr",FPOINTER);
+    else {
+        size = AOP_SIZE(result);
+        offset = 0 ;
+
+        while (size--) {
+            pic16_emitcode("movx","a,@dptr");
+            pic16_aopPut(AOP(result),"a",offset++);
+            if (size)
+                pic16_emitcode("inc","dptr");
+        }
+    }
+
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+#if 0
+/*-----------------------------------------------------------------*/
+/* genCodePointerGet - get value from code space                  */
+/*-----------------------------------------------------------------*/
+static void genCodePointerGet (operand *left,
+                                operand *result, iCode *ic)
+{
+    int size, offset ;
+    sym_link *retype = getSpec(operandType(result));
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    pic16_aopOp(left,ic,FALSE);
+
+    /* if the operand is already in dptr 
+    then we do nothing else we move the value to dptr */
+    if (AOP_TYPE(left) != AOP_STR) {
+        /* if this is remateriazable */
+        if (AOP_TYPE(left) == AOP_IMMD)
+            pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
+        else { /* we need to get it byte by byte */
+            pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
+            pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
+            if (options.model == MODEL_FLAT24)
+            {
+               pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
+            }
+        }
+    }
+    /* so dptr know contains the address */
+    pic16_freeAsmop(left,NULL,ic,TRUE);
+    pic16_aopOp(result,ic,FALSE);
+
+    /* if bit then unpack */
+    if (IS_BITVAR(retype)) 
+        genUnpackBits(result,"dptr",CPOINTER);
+    else {
+        size = AOP_SIZE(result);
+        offset = 0 ;
+
+        while (size--) {
+            pic16_emitcode("clr","a");
+            pic16_emitcode("movc","a,@a+dptr");
+            pic16_aopPut(AOP(result),"a",offset++);
+            if (size)
+                pic16_emitcode("inc","dptr");
+        }
+    }
+
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+#endif
+/*-----------------------------------------------------------------*/
+/* genGenPointerGet - gget value from generic pointer space        */
+/*-----------------------------------------------------------------*/
+static void genGenPointerGet (operand *left,
+                              operand *result, iCode *ic)
+{
+  int size, offset ;
+  sym_link *retype = getSpec(operandType(result));
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  pic16_aopOp(left,ic,FALSE);
+  pic16_aopOp(result,ic,FALSE);
+
+
+  DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
+
+  /* if the operand is already in dptr 
+     then we do nothing else we move the value to dptr */
+  //  if (AOP_TYPE(left) != AOP_STR) {
+    /* if this is remateriazable */
+    if (AOP_TYPE(left) == AOP_IMMD) {
+      pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
+      pic16_emitcode("mov","b,#%d",pointerCode(retype));
+    }
+    else { /* we need to get it byte by byte */
+
+      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
+
+      size = AOP_SIZE(result);
+      offset = 0 ;
+
+      while(size--) {
+       pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
+       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
+       if(size)
+         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
+      }
+      goto release;
+    }
+    //}
+  /* so dptr know contains the address */
+
+  /* if bit then unpack */
+  //if (IS_BITVAR(retype)) 
+  //  genUnpackBits(result,"dptr",GPOINTER);
+
+ release:
+  pic16_freeAsmop(left,NULL,ic,TRUE);
+  pic16_freeAsmop(result,NULL,ic,TRUE);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genConstPointerGet - get value from const generic pointer space */
+/*-----------------------------------------------------------------*/
+static void genConstPointerGet (operand *left,
+                               operand *result, iCode *ic)
+{
+  //sym_link *retype = getSpec(operandType(result));
+  symbol *albl = newiTempLabel(NULL);
+  symbol *blbl = newiTempLabel(NULL);
+  PIC_OPCODE poc;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  pic16_aopOp(left,ic,FALSE);
+  pic16_aopOp(result,ic,FALSE);
+
+
+  DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
+
+  DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
+
+  pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
+  pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
+  pic16_emitpLabel(albl->key);
+
+  poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
+    
+  pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
+  pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
+  pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
+  pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
+
+  pic16_emitpLabel(blbl->key);
+
+  pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
+
+
+  pic16_freeAsmop(left,NULL,ic,TRUE);
+  pic16_freeAsmop(result,NULL,ic,TRUE);
+
+}
+/*-----------------------------------------------------------------*/
+/* genPointerGet - generate code for pointer get                   */
+/*-----------------------------------------------------------------*/
+static void genPointerGet (iCode *ic)
+{
+    operand *left, *result ;
+    sym_link *type, *etype;
+    int p_type;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    left = IC_LEFT(ic);
+    result = IC_RESULT(ic) ;
+
+    /* depending on the type of pointer we need to
+    move it to the correct pointer register */
+    type = operandType(left);
+    etype = getSpec(type);
+
+    if (IS_PTR_CONST(type))
+      DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
+
+    /* if left is of type of pointer then it is simple */
+    if (IS_PTR(type) && !IS_FUNC(type->next)) 
+        p_type = DCL_TYPE(type);
+    else {
+       /* we have to go by the storage class */
+       p_type = PTR_TYPE(SPEC_OCLS(etype));
+
+       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
+
+       if (SPEC_OCLS(etype)->codesp ) {
+         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
+         //p_type = CPOINTER ; 
+       }
+       else
+           if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
+             DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
+              /*p_type = FPOINTER ;*/ 
+           else
+               if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
+                 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
+/*                 p_type = PPOINTER; */
+               else
+                   if (SPEC_OCLS(etype) == idata )
+                     DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
+/*                     p_type = IPOINTER; */
+                   else
+                     DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
+/*                     p_type = POINTER ; */
+    }
+
+    /* now that we have the pointer type we assign
+    the pointer values */
+    switch (p_type) {
+
+    case POINTER:      
+    case IPOINTER:
+       genNearPointerGet (left,result,ic);
+       break;
+
+    case PPOINTER:
+       genPagedPointerGet(left,result,ic);
+       break;
+
+    case FPOINTER:
+       genFarPointerGet (left,result,ic);
+       break;
+
+    case CPOINTER:
+       genConstPointerGet (left,result,ic);
+       //pic16_emitcodePointerGet (left,result,ic);
+       break;
+
+    case GPOINTER:
+      if (IS_PTR_CONST(type))
+       genConstPointerGet (left,result,ic);
+      else
+       genGenPointerGet (left,result,ic);
+      break;
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genPackBits - generates code for packed bit storage             */
+/*-----------------------------------------------------------------*/
+static void genPackBits (sym_link    *etype ,
+                         operand *right ,
+                         char *rname, int p_type)
+{
+    int shCount = 0 ;
+    int offset = 0  ;
+    int rLen = 0 ;
+    int blen, bstr ;   
+    char *l ;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    blen = SPEC_BLEN(etype);
+    bstr = SPEC_BSTR(etype);
+
+    l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
+    MOVA(l);   
+
+    /* if the bit lenth is less than or    */
+    /* it exactly fits a byte then         */
+    if (SPEC_BLEN(etype) <= 8 )  {
+        shCount = SPEC_BSTR(etype) ;
+
+        /* shift left acc */
+        AccLsh(shCount);
+
+        if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
+
+
+            switch (p_type) {
+                case POINTER:
+                    pic16_emitcode ("mov","b,a");
+                    pic16_emitcode("mov","a,@%s",rname);
+                    break;
+
+                case FPOINTER:
+                    pic16_emitcode ("mov","b,a");
+                    pic16_emitcode("movx","a,@dptr");
+                    break;
+
+                case GPOINTER:
+                    pic16_emitcode ("push","b");
+                    pic16_emitcode ("push","acc");
+                    pic16_emitcode ("lcall","__gptrget");
+                    pic16_emitcode ("pop","b");
+                    break;
+            }
+
+            pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
+                      ((unsigned char)(0xFF << (blen+bstr)) | 
+                       (unsigned char)(0xFF >> (8-bstr)) ) );
+            pic16_emitcode ("orl","a,b");
+            if (p_type == GPOINTER)
+                pic16_emitcode("pop","b");
+        }
+    }
+
+    switch (p_type) {
+        case POINTER:
+            pic16_emitcode("mov","@%s,a",rname);
+            break;
+
+        case FPOINTER:
+            pic16_emitcode("movx","@dptr,a");
+            break;
+
+        case GPOINTER:
+            DEBUGpic16_emitcode(";lcall","__gptrput");
+            break;
+    }
+
+    /* if we r done */
+    if ( SPEC_BLEN(etype) <= 8 )
+        return ;
+
+    pic16_emitcode("inc","%s",rname);
+    rLen = SPEC_BLEN(etype) ;     
+
+    /* now generate for lengths greater than one byte */
+    while (1) {
+
+        l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
+
+        rLen -= 8 ;
+        if (rLen <= 0 )
+            break ;
+
+        switch (p_type) {
+            case POINTER:
+                if (*l == '@') {
+                    MOVA(l);
+                    pic16_emitcode("mov","@%s,a",rname);
+                } else
+                    pic16_emitcode("mov","@%s,%s",rname,l);
+                break;
+
+            case FPOINTER:
+                MOVA(l);
+                pic16_emitcode("movx","@dptr,a");
+                break;
+
+            case GPOINTER:
+                MOVA(l);
+                DEBUGpic16_emitcode(";lcall","__gptrput");
+                break;  
+        }   
+        pic16_emitcode ("inc","%s",rname);
+    }
+
+    MOVA(l);
+
+    /* last last was not complete */
+    if (rLen)   {
+        /* save the byte & read byte */
+        switch (p_type) {
+            case POINTER:
+                pic16_emitcode ("mov","b,a");
+                pic16_emitcode("mov","a,@%s",rname);
+                break;
+
+            case FPOINTER:
+                pic16_emitcode ("mov","b,a");
+                pic16_emitcode("movx","a,@dptr");
+                break;
+
+            case GPOINTER:
+                pic16_emitcode ("push","b");
+                pic16_emitcode ("push","acc");
+                pic16_emitcode ("lcall","__gptrget");
+                pic16_emitcode ("pop","b");
+                break;
+        }
+
+        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
+        pic16_emitcode ("orl","a,b");
+    }
+
+    if (p_type == GPOINTER)
+        pic16_emitcode("pop","b");
+
+    switch (p_type) {
+
+    case POINTER:
+       pic16_emitcode("mov","@%s,a",rname);
+       break;
+       
+    case FPOINTER:
+       pic16_emitcode("movx","@dptr,a");
+       break;
+       
+    case GPOINTER:
+       DEBUGpic16_emitcode(";lcall","__gptrput");
+       break;                  
+    }
+}
+/*-----------------------------------------------------------------*/
+/* genDataPointerSet - remat pointer to data space                 */
+/*-----------------------------------------------------------------*/
+static void genDataPointerSet(operand *right,
+                             operand *result,
+                             iCode *ic)
+{
+    int size, offset = 0 ;
+    char *l, buffer[256];
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    pic16_aopOp(right,ic,FALSE);
+    
+    l = pic16_aopGet(AOP(result),0,FALSE,TRUE);
+    size = AOP_SIZE(right);
+/*
+    if ( AOP_TYPE(result) == AOP_PCODE) {
+      fprintf(stderr,"genDataPointerSet   %s, %d\n",
+             AOP(result)->aopu.pcop->name,
+             PCOI(AOP(result)->aopu.pcop)->offset);
+    }
+*/
+
+    // tsd, was l+1 - the underline `_' prefix was being stripped
+    while (size--) {
+      if (offset) {
+       sprintf(buffer,"(%s + %d)",l,offset);
+       fprintf(stderr,"oops  %s\n",buffer);
+      } else
+       sprintf(buffer,"%s",l);
+
+       if (AOP_TYPE(right) == AOP_LIT) {
+         unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
+         lit = lit >> (8*offset);
+         if(lit&0xff) {
+           pic16_emitcode("movlw","%d",lit);
+           pic16_emitcode("movwf","%s",buffer);
+
+           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
+           //pic16_emitpcode(POC_MOVWF, popRegFromString(buffer));
+           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
+
+         } else {
+           pic16_emitcode("clrf","%s",buffer);
+           //pic16_emitpcode(POC_CLRF, popRegFromString(buffer));
+           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
+         }
+       }else {
+         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+         pic16_emitcode("movwf","%s",buffer);
+
+         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
+         //pic16_emitpcode(POC_MOVWF, popRegFromString(buffer));
+         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
+
+       }
+
+       offset++;
+    }
+
+    pic16_freeAsmop(right,NULL,ic,TRUE);
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genNearPointerSet - pic16_emitcode for near pointer put                */
+/*-----------------------------------------------------------------*/
+static void genNearPointerSet (operand *right,
+                               operand *result, 
+                               iCode *ic)
+{
+  asmop *aop = NULL;
+  char *l;
+  sym_link *retype;
+  sym_link *ptype = operandType(result);
+
+    
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  retype= getSpec(operandType(right));
+
+  pic16_aopOp(result,ic,FALSE);
+
+    
+  /* if the result is rematerializable &
+     in data space & not a bit variable */
+  //if (AOP_TYPE(result) == AOP_IMMD &&
+  if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
+      DCL_TYPE(ptype) == POINTER   &&
+      !IS_BITVAR(retype)) {
+    genDataPointerSet (right,result,ic);
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+    return;
+  }
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  pic16_aopOp(right,ic,FALSE);
+  DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
+
+  /* if the value is already in a pointer register
+     then don't need anything more */
+  if (!AOP_INPREG(AOP(result))) {
+    /* otherwise get a free pointer register */
+    //aop = newAsmop(0);
+    //preg = getFreePtr(ic,&aop,FALSE);
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    //pic16_emitcode("mov","%s,%s",
+    //         preg->name,
+    //         pic16_aopGet(AOP(result),0,FALSE,TRUE));
+    //rname = preg->name ;
+    //pic16_emitcode("movwf","fsr0");
+    pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0));
+    pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_fsr0));
+    pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+    pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
+    goto release;
+
+  }// else
+  //   rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
+
+
+  /* if bitfield then unpack the bits */
+  if (IS_BITVAR(retype)) {
+    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+          "The programmer is obviously confused");
+    //genPackBits (retype,right,rname,POINTER);
+    exit(1);
+  }
+  else {
+    /* we have can just get the values */
+    int size = AOP_SIZE(right);
+    int offset = 0 ;    
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    while (size--) {
+      l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
+      if (*l == '@' ) {
+       //MOVA(l);
+       //pic16_emitcode("mov","@%s,a",rname);
+       pic16_emitcode("movf","indf0,w ;1");
+      } else {
+
+       if (AOP_TYPE(right) == AOP_LIT) {
+         unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
+         if(lit) {
+           pic16_emitcode("movlw","%s",l);
+           pic16_emitcode("movwf","indf0 ;2");
+         } else 
+           pic16_emitcode("clrf","indf0");
+       }else {
+         pic16_emitcode("movf","%s,w",l);
+         pic16_emitcode("movwf","indf0 ;2");
+       }
+       //pic16_emitcode("mov","@%s,%s",rname,l);
+      }
+      if (size)
+       pic16_emitcode("incf","fsr0,f ;3");
+      //pic16_emitcode("inc","%s",rname);
+      offset++;
+    }
+  }
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  /* now some housekeeping stuff */
+  if (aop) {
+    /* we had to allocate for this iCode */
+    pic16_freeAsmop(NULL,aop,ic,TRUE);
+  } else { 
+    /* we did not allocate which means left
+       already in a pointer register, then
+       if size > 0 && this could be used again
+       we have to point it back to where it 
+       belongs */
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if (AOP_SIZE(right) > 1 &&
+       !OP_SYMBOL(result)->remat &&
+       ( OP_SYMBOL(result)->liveTo > ic->seq ||
+         ic->depth )) {
+      int size = AOP_SIZE(right) - 1;
+      while (size--)
+       pic16_emitcode("decf","fsr0,f");
+      //pic16_emitcode("dec","%s",rname);
+    }
+  }
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  /* done */
+ release:
+  pic16_freeAsmop(right,NULL,ic,TRUE);
+  pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
+/*-----------------------------------------------------------------*/
+static void genPagedPointerSet (operand *right,
+                              operand *result, 
+                              iCode *ic)
+{
+    asmop *aop = NULL;
+    regs *preg = NULL ;
+    char *rname , *l;
+    sym_link *retype;
+       
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    retype= getSpec(operandType(right));
+    
+    pic16_aopOp(result,ic,FALSE);
+    
+    /* if the value is already in a pointer register
+       then don't need anything more */
+    if (!AOP_INPREG(AOP(result))) {
+       /* otherwise get a free pointer register */
+       aop = newAsmop(0);
+       preg = getFreePtr(ic,&aop,FALSE);
+       pic16_emitcode("mov","%s,%s",
+               preg->name,
+               pic16_aopGet(AOP(result),0,FALSE,TRUE));
+       rname = preg->name ;
+    } else
+       rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
+    
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+    pic16_aopOp (right,ic,FALSE);
+
+    /* if bitfield then unpack the bits */
+    if (IS_BITVAR(retype)) 
+       genPackBits (retype,right,rname,PPOINTER);
+    else {
+       /* we have can just get the values */
+       int size = AOP_SIZE(right);
+       int offset = 0 ;        
+       
+       while (size--) {
+           l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
+           
+           MOVA(l);
+           pic16_emitcode("movx","@%s,a",rname);
+
+           if (size)
+               pic16_emitcode("inc","%s",rname);
+
+           offset++;
+       }
+    }
+    
+    /* now some housekeeping stuff */
+    if (aop) {
+       /* we had to allocate for this iCode */
+       pic16_freeAsmop(NULL,aop,ic,TRUE);
+    } else { 
+       /* we did not allocate which means left
+          already in a pointer register, then
+          if size > 0 && this could be used again
+          we have to point it back to where it 
+          belongs */
+       if (AOP_SIZE(right) > 1 &&
+           !OP_SYMBOL(result)->remat &&
+           ( OP_SYMBOL(result)->liveTo > ic->seq ||
+             ic->depth )) {
+           int size = AOP_SIZE(right) - 1;
+           while (size--)
+               pic16_emitcode("dec","%s",rname);
+       }
+    }
+
+    /* done */
+    pic16_freeAsmop(right,NULL,ic,TRUE);
+    
+       
+}
+
+/*-----------------------------------------------------------------*/
+/* genFarPointerSet - set value from far space                     */
+/*-----------------------------------------------------------------*/
+static void genFarPointerSet (operand *right,
+                              operand *result, iCode *ic)
+{
+    int size, offset ;
+    sym_link *retype = getSpec(operandType(right));
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    pic16_aopOp(result,ic,FALSE);
+
+    /* if the operand is already in dptr 
+    then we do nothing else we move the value to dptr */
+    if (AOP_TYPE(result) != AOP_STR) {
+        /* if this is remateriazable */
+        if (AOP_TYPE(result) == AOP_IMMD)
+            pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
+        else { /* we need to get it byte by byte */
+            pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
+            pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
+            if (options.model == MODEL_FLAT24)
+            {
+               pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
+            }
+        }
+    }
+    /* so dptr know contains the address */
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+    pic16_aopOp(right,ic,FALSE);
+
+    /* if bit then unpack */
+    if (IS_BITVAR(retype)) 
+        genPackBits(retype,right,"dptr",FPOINTER);
+    else {
+        size = AOP_SIZE(right);
+        offset = 0 ;
+
+        while (size--) {
+            char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
+            MOVA(l);
+            pic16_emitcode("movx","@dptr,a");
+            if (size)
+                pic16_emitcode("inc","dptr");
+        }
+    }
+
+    pic16_freeAsmop(right,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genGenPointerSet - set value from generic pointer space         */
+/*-----------------------------------------------------------------*/
+static void genGenPointerSet (operand *right,
+                              operand *result, iCode *ic)
+{
+  int size, offset ;
+  sym_link *retype = getSpec(operandType(right));
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  pic16_aopOp(result,ic,FALSE);
+  pic16_aopOp(right,ic,FALSE);
+  size = AOP_SIZE(right);
+
+  DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
+
+  /* if the operand is already in dptr 
+     then we do nothing else we move the value to dptr */
+  if (AOP_TYPE(result) != AOP_STR) {
+    /* if this is remateriazable */
+    if (AOP_TYPE(result) == AOP_IMMD) {
+      pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
+      pic16_emitcode("mov","b,%s + 1",pic16_aopGet(AOP(result),0,TRUE,FALSE));
+    }
+    else { /* we need to get it byte by byte */
+      //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
+      size = AOP_SIZE(right);
+      offset = 0 ;
+
+      /* hack hack! see if this the FSR. If so don't load W */
+      if(AOP_TYPE(right) != AOP_ACC) {
+
+
+       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),0));
+       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
+
+       if(AOP_SIZE(result) > 1) {
+         pic16_emitpcode(POC_BCF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
+         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),1,FALSE,FALSE),0,0));
+         pic16_emitpcode(POC_BSF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
+
+       }
+
+       //if(size==2)
+       //pic16_emitpcode(POC_DECF,pic16_popCopyReg(&pic16_pc_fsr0));
+       //if(size==4) {
+       //  pic16_emitpcode(POC_MOVLW,pic16_popGetLit(0xfd));
+       //  pic16_emitpcode(POC_ADDWF,pic16_popCopyReg(&pic16_pc_fsr0));
+       //}
+
+       while(size--) {
+         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset++));
+         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
+         
+         if(size)
+           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
+       }
+
+
+       goto release;
+      } 
+
+      if(aopIdx(AOP(result),0) != 4) {
+
+       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
+       goto release;
+      }
+
+      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
+      goto release;
+
+    }
+  }
+  /* so dptr know contains the address */
+
+
+  /* if bit then unpack */
+  if (IS_BITVAR(retype)) 
+    genPackBits(retype,right,"dptr",GPOINTER);
+  else {
+    size = AOP_SIZE(right);
+    offset = 0 ;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
+
+    while (size--) {
+
+      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offset));
+      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
+
+      if (AOP_TYPE(right) == AOP_LIT) 
+       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
+      else
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
+
+      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
+
+      offset++;
+    }
+  }
+
+ release:
+  pic16_freeAsmop(right,NULL,ic,TRUE);
+  pic16_freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genPointerSet - stores the value into a pointer location        */
+/*-----------------------------------------------------------------*/
+static void genPointerSet (iCode *ic)
+{    
+    operand *right, *result ;
+    sym_link *type, *etype;
+    int p_type;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    right = IC_RIGHT(ic);
+    result = IC_RESULT(ic) ;
+
+    /* depending on the type of pointer we need to
+    move it to the correct pointer register */
+    type = operandType(result);
+    etype = getSpec(type);
+    /* if left is of type of pointer then it is simple */
+    if (IS_PTR(type) && !IS_FUNC(type->next)) {
+        p_type = DCL_TYPE(type);
+    }
+    else {
+       /* we have to go by the storage class */
+       p_type = PTR_TYPE(SPEC_OCLS(etype));
+
+/*     if (SPEC_OCLS(etype)->codesp ) { */
+/*         p_type = CPOINTER ;  */
+/*     } */
+/*     else */
+/*         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
+/*             p_type = FPOINTER ; */
+/*         else */
+/*             if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
+/*                 p_type = PPOINTER ; */
+/*             else */
+/*                 if (SPEC_OCLS(etype) == idata ) */
+/*                     p_type = IPOINTER ; */
+/*                 else */
+/*                     p_type = POINTER ; */
+    }
+
+    /* now that we have the pointer type we assign
+    the pointer values */
+    switch (p_type) {
+
+    case POINTER:
+    case IPOINTER:
+       genNearPointerSet (right,result,ic);
+       break;
+
+    case PPOINTER:
+       genPagedPointerSet (right,result,ic);
+       break;
+
+    case FPOINTER:
+       genFarPointerSet (right,result,ic);
+       break;
+
+    case GPOINTER:
+       genGenPointerSet (right,result,ic);
+       break;
+
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
+             "genPointerSet: illegal pointer type");
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genIfx - generate code for Ifx statement                        */
+/*-----------------------------------------------------------------*/
+static void genIfx (iCode *ic, iCode *popIc)
+{
+  operand *cond = IC_COND(ic);
+  int isbit =0;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  pic16_aopOp(cond,ic,FALSE);
+
+  /* get the value into acc */
+  if (AOP_TYPE(cond) != AOP_CRY)
+    pic16_toBoolean(cond);
+  else
+    isbit = 1;
+  /* the result is now in the accumulator */
+  pic16_freeAsmop(cond,NULL,ic,TRUE);
+
+  /* if there was something to be popped then do it */
+  if (popIc)
+    genIpop(popIc);
+
+  /* if the condition is  a bit variable */
+  if (isbit && IS_ITEMP(cond) && 
+      SPIL_LOC(cond)) {
+    genIfxJump(ic,SPIL_LOC(cond)->rname);
+    DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
+  }
+  else {
+    if (isbit && !IS_ITEMP(cond))
+      genIfxJump(ic,OP_SYMBOL(cond)->rname);
+    else
+      genIfxJump(ic,"a");
+  }
+  ic->generated = 1;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genAddrOf - generates code for address of                       */
+/*-----------------------------------------------------------------*/
+static void genAddrOf (iCode *ic)
+{
+  operand *right, *result, *left;
+  int size, offset ;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+
+  //pic16_aopOp(IC_RESULT(ic),ic,FALSE);
+
+  pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
+  pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
+  pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
+
+  DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
+
+  size = AOP_SIZE(IC_RESULT(ic));
+  offset = 0;
+
+  while (size--) {
+    pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),offset));
+    pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+    offset++;
+  }
+
+  pic16_freeAsmop(left,NULL,ic,FALSE);
+  pic16_freeAsmop(result,NULL,ic,TRUE);
+
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* genFarFarAssign - assignment when both are in far space         */
+/*-----------------------------------------------------------------*/
+static void genFarFarAssign (operand *result, operand *right, iCode *ic)
+{
+    int size = AOP_SIZE(right);
+    int offset = 0;
+    char *l ;
+    /* first push the right side on to the stack */
+    while (size--) {
+       l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
+       MOVA(l);
+       pic16_emitcode ("push","acc");
+    }
+    
+    pic16_freeAsmop(right,NULL,ic,FALSE);
+    /* now assign DPTR to result */
+    pic16_aopOp(result,ic,FALSE);
+    size = AOP_SIZE(result);
+    while (size--) {
+       pic16_emitcode ("pop","acc");
+       pic16_aopPut(AOP(result),"a",--offset);
+    }
+    pic16_freeAsmop(result,NULL,ic,FALSE);
+       
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* genAssign - generate code for assignment                        */
+/*-----------------------------------------------------------------*/
+static void genAssign (iCode *ic)
+{
+  operand *result, *right;
+  int size, offset,know_W;
+  unsigned long lit = 0L;
+
+  result = IC_RESULT(ic);
+  right  = IC_RIGHT(ic) ;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  /* if they are the same */
+  if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
+    return ;
+
+  pic16_aopOp(right,ic,FALSE);
+  pic16_aopOp(result,ic,TRUE);
+
+  DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
+
+  /* if they are the same registers */
+  if (pic16_sameRegs(AOP(right),AOP(result)))
+    goto release;
+
+  /* if the result is a bit */
+  if (AOP_TYPE(result) == AOP_CRY) {
+
+    /* if the right size is a literal then
+       we know what the value is */
+    if (AOP_TYPE(right) == AOP_LIT) {
+         
+      pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
+                 pic16_popGet(AOP(result),0));
+
+      if (((int) operandLitValue(right))) 
+       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
+                      AOP(result)->aopu.aop_dir,
+                      AOP(result)->aopu.aop_dir);
+      else
+       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
+                      AOP(result)->aopu.aop_dir,
+                      AOP(result)->aopu.aop_dir);
+      goto release;
+    }
+
+    /* the right is also a bit variable */
+    if (AOP_TYPE(right) == AOP_CRY) {
+      pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
+      pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
+
+      pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
+                    AOP(result)->aopu.aop_dir,
+                    AOP(result)->aopu.aop_dir);
+      pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
+                    AOP(right)->aopu.aop_dir,
+                    AOP(right)->aopu.aop_dir);
+      pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
+                    AOP(result)->aopu.aop_dir,
+                    AOP(result)->aopu.aop_dir);
+      goto release ;
+    }
+
+    /* we need to or */
+    pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
+    pic16_toBoolean(right);
+    emitSKPZ;
+    pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
+    //pic16_aopPut(AOP(result),"a",0);
+    goto release ;
+  }
+
+  /* bit variables done */
+  /* general case */
+  size = AOP_SIZE(result);
+  offset = 0 ;
+  if(AOP_TYPE(right) == AOP_LIT)
+    lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
+
+  if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if(aopIdx(AOP(result),0) == 4) {
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+      goto release;
+    } else
+      DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
+  }
+
+  know_W=-1;
+  while (size--) {
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if(AOP_TYPE(right) == AOP_LIT) {
+      if(lit&0xff) {
+       if(know_W != (lit&0xff))
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
+       know_W = lit&0xff;
+       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+      } else
+       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
+
+      lit >>= 8;
+
+    } else if (AOP_TYPE(right) == AOP_CRY) {
+      pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
+      if(offset == 0) {
+       pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
+       pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
+      }
+    } else {
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+    }
+           
+    offset++;
+  }
+
+    
+ release:
+  pic16_freeAsmop (right,NULL,ic,FALSE);
+  pic16_freeAsmop (result,NULL,ic,TRUE);
+}   
+
+/*-----------------------------------------------------------------*/
+/* genJumpTab - genrates code for jump table                       */
+/*-----------------------------------------------------------------*/
+static void genJumpTab (iCode *ic)
+{
+    symbol *jtab;
+    char *l;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
+    /* get the condition into accumulator */
+    l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
+    MOVA(l);
+    /* multiply by three */
+    pic16_emitcode("add","a,acc");
+    pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
+
+    jtab = newiTempLabel(NULL);
+    pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
+    pic16_emitcode("jmp","@a+dptr");
+    pic16_emitcode("","%05d_DS_:",jtab->key+100);
+
+    pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
+    pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
+    emitSKPNC;
+    pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
+    pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
+    pic16_emitpLabel(jtab->key);
+
+    pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
+
+    /* now generate the jump labels */
+    for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
+         jtab = setNextItem(IC_JTLABELS(ic))) {
+        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
+       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
+       
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genMixedOperation - gen code for operators between mixed types  */
+/*-----------------------------------------------------------------*/
+/*
+  TSD - Written for the PIC port - but this unfortunately is buggy.
+  This routine is good in that it is able to efficiently promote 
+  types to different (larger) sizes. Unfortunately, the temporary
+  variables that are optimized out by this routine are sometimes
+  used in other places. So until I know how to really parse the 
+  iCode tree, I'm going to not be using this routine :(.
+*/
+static int genMixedOperation (iCode *ic)
+{
+#if 0
+  operand *result = IC_RESULT(ic);
+  sym_link *ctype = operandType(IC_LEFT(ic));
+  operand *right = IC_RIGHT(ic);
+  int ret = 0;
+  int big,small;
+  int offset;
+
+  iCode *nextic;
+  operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
+
+  pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  nextic = ic->next;
+  if(!nextic)
+    return 0;
+
+  nextright = IC_RIGHT(nextic);
+  nextleft  = IC_LEFT(nextic);
+  nextresult = IC_RESULT(nextic);
+
+  pic16_aopOp(right,ic,FALSE);
+  pic16_aopOp(result,ic,FALSE);
+  pic16_aopOp(nextright,  nextic, FALSE);
+  pic16_aopOp(nextleft,   nextic, FALSE);
+  pic16_aopOp(nextresult, nextic, FALSE);
+
+  if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
+
+    operand *t = right;
+    right = nextright;
+    nextright = t; 
+
+    pic16_emitcode(";remove right +","");
+
+  } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
+/*
+    operand *t = right;
+    right = nextleft;
+    nextleft = t; 
+*/
+    pic16_emitcode(";remove left +","");
+  } else
+    return 0;
+
+  big = AOP_SIZE(nextleft);
+  small = AOP_SIZE(nextright);
+
+  switch(nextic->op) {
+
+  case '+':
+    pic16_emitcode(";optimize a +","");
+    /* if unsigned or not an integral type */
+    if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
+      pic16_emitcode(";add a bit to something","");
+    } else {
+
+      pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
+
+      if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
+       pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
+       pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
+      } else
+       pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
+
+      offset = 0;
+      while(--big) {
+
+       offset++;
+
+       if(--small) {
+         if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
+           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
+           pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
+         }
+
+         pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
+         emitSKPNC;
+         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                  AOP(IC_RIGHT(nextic))->aopu.aop_dir,
+                  AOP(IC_RIGHT(nextic))->aopu.aop_dir);
+         pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
+         pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
+
+       } else {
+         pic16_emitcode("rlf","known_zero,w");
+
+         /*
+           if right is signed
+             btfsc  right,7
+               addlw ff
+         */
+         if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
+           pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
+           pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
+         } else {
+           pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
+         }
+       }
+      }
+      ret = 1;
+    }
+  }
+  ret = 1;
+
+release:
+  pic16_freeAsmop(right,NULL,ic,TRUE);
+  pic16_freeAsmop(result,NULL,ic,TRUE);
+  pic16_freeAsmop(nextright,NULL,ic,TRUE);
+  pic16_freeAsmop(nextleft,NULL,ic,TRUE);
+  if(ret)
+    nextic->generated = 1;
+
+  return ret;
+#else
+  return 0;
+#endif
+}
+/*-----------------------------------------------------------------*/
+/* genCast - gen code for casting                                  */
+/*-----------------------------------------------------------------*/
+static void genCast (iCode *ic)
+{
+    operand *result = IC_RESULT(ic);
+    sym_link *ctype = operandType(IC_LEFT(ic));
+    sym_link *rtype = operandType(IC_RIGHT(ic));
+    operand *right = IC_RIGHT(ic);
+    int size, offset ;
+
+    DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* if they are equivalent then do nothing */
+    if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
+        return ;
+
+    pic16_aopOp(right,ic,FALSE) ;
+    pic16_aopOp(result,ic,FALSE);
+
+    DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
+
+    /* if the result is a bit */
+    if (AOP_TYPE(result) == AOP_CRY) {
+        /* if the right size is a literal then
+        we know what the value is */
+      DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
+        if (AOP_TYPE(right) == AOP_LIT) {
+
+         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
+                     pic16_popGet(AOP(result),0));
+
+            if (((int) operandLitValue(right))) 
+             pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
+                      AOP(result)->aopu.aop_dir,
+                      AOP(result)->aopu.aop_dir);
+            else
+             pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
+                      AOP(result)->aopu.aop_dir,
+                      AOP(result)->aopu.aop_dir);
+
+            goto release;
+        }
+
+        /* the right is also a bit variable */
+        if (AOP_TYPE(right) == AOP_CRY) {
+
+         emitCLRC;
+         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
+
+         pic16_emitcode("clrc","");
+         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                  AOP(right)->aopu.aop_dir,
+                  AOP(right)->aopu.aop_dir);
+            pic16_aopPut(AOP(result),"c",0);
+            goto release ;
+        }
+
+        /* we need to or */
+       if (AOP_TYPE(right) == AOP_REG) {
+         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
+         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
+       }
+       pic16_toBoolean(right);
+       pic16_aopPut(AOP(result),"a",0);
+        goto release ;
+    }
+
+    if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
+      int offset = 1;
+      size = AOP_SIZE(result);
+
+      DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+      pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
+      pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
+
+      while (size--)
+       pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
+
+      goto release;
+    }
+
+    /* if they are the same size : or less */
+    if (AOP_SIZE(result) <= AOP_SIZE(right)) {
+
+        /* if they are in the same place */
+      if (pic16_sameRegs(AOP(right),AOP(result)))
+       goto release;
+
+      DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
+      if (IS_PTR_CONST(rtype))
+       DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
+      if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
+       DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
+
+      if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
+       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
+       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
+       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
+       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
+        if(AOP_SIZE(result) <2)
+         fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
+
+      } else {
+
+        /* if they in different places then copy */
+        size = AOP_SIZE(result);
+        offset = 0 ;
+        while (size--) {
+         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
+         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+
+         //pic16_aopPut(AOP(result),
+         // pic16_aopGet(AOP(right),offset,FALSE,FALSE),
+         // offset);
+
+         offset++;
+        }
+      }
+      goto release;
+    }
+
+
+    /* if the result is of type pointer */
+    if (IS_PTR(ctype)) {
+
+       int p_type;
+       sym_link *type = operandType(right);
+       sym_link *etype = getSpec(type);
+      DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
+
+       /* pointer to generic pointer */
+       if (IS_GENPTR(ctype)) {
+           char *l = zero;
+           
+           if (IS_PTR(type)) 
+               p_type = DCL_TYPE(type);
+           else {
+               /* we have to go by the storage class */
+               p_type = PTR_TYPE(SPEC_OCLS(etype));
+
+/*             if (SPEC_OCLS(etype)->codesp )  */
+/*                 p_type = CPOINTER ;  */
+/*             else */
+/*                 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
+/*                     p_type = FPOINTER ; */
+/*                 else */
+/*                     if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
+/*                         p_type = PPOINTER; */
+/*                     else */
+/*                         if (SPEC_OCLS(etype) == idata ) */
+/*                             p_type = IPOINTER ; */
+/*                         else */
+/*                             p_type = POINTER ; */
+           }
+               
+           /* the first two bytes are known */
+      DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
+           size = GPTRSIZE - 1; 
+           offset = 0 ;
+           while (size--) {
+             if(offset < AOP_SIZE(right)) {
+      DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
+               if ((AOP_TYPE(right) == AOP_PCODE) && 
+                   AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
+                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
+                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+               } else { 
+                 pic16_aopPut(AOP(result),
+                        pic16_aopGet(AOP(right),offset,FALSE,FALSE),
+                        offset);
+               }
+             } else 
+               pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
+             offset++;
+           }
+           /* the last byte depending on type */
+           switch (p_type) {
+           case IPOINTER:
+           case POINTER:
+               pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
+               break;
+           case FPOINTER:
+             pic16_emitcode(";BUG!? ","%d",__LINE__);
+               l = one;
+               break;
+           case CPOINTER:
+             pic16_emitcode(";BUG!? ","%d",__LINE__);
+               l = "#0x02";
+               break;                          
+           case PPOINTER:
+             pic16_emitcode(";BUG!? ","%d",__LINE__);
+               l = "#0x03";
+               break;
+               
+           default:
+               /* this should never happen */
+               werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+                      "got unknown pointer type");
+               exit(1);
+           }
+           //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
+           goto release ;
+       }
+       
+       /* just copy the pointers */
+       size = AOP_SIZE(result);
+       offset = 0 ;
+       while (size--) {
+           pic16_aopPut(AOP(result),
+                  pic16_aopGet(AOP(right),offset,FALSE,FALSE),
+                  offset);
+           offset++;
+       }
+       goto release ;
+    }
+    
+
+
+    /* so we now know that the size of destination is greater
+    than the size of the source.
+    Now, if the next iCode is an operator then we might be
+    able to optimize the operation without performing a cast.
+    */
+    if(genMixedOperation(ic))
+      goto release;
+
+    DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
+    
+    /* we move to result for the size of source */
+    size = AOP_SIZE(right);
+    offset = 0 ;
+    while (size--) {
+      pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
+      pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
+      offset++;
+    }
+
+    /* now depending on the sign of the destination */
+    size = AOP_SIZE(result) - AOP_SIZE(right);
+    /* if unsigned or not an integral type */
+    if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
+      while (size--)
+       pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
+    } else {
+      /* we need to extend the sign :{ */
+
+      if(size == 1) {
+       /* Save one instruction of casting char to int */
+       pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
+       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
+       pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
+      } else {
+        pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
+
+       if(offset)
+         pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
+       else
+         pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
+       
+       pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
+
+        while (size--)
+         pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
+      }
+    }
+
+release:
+    pic16_freeAsmop(right,NULL,ic,TRUE);
+    pic16_freeAsmop(result,NULL,ic,TRUE);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genDjnz - generate decrement & jump if not zero instrucion      */
+/*-----------------------------------------------------------------*/
+static int genDjnz (iCode *ic, iCode *ifx)
+{
+    symbol *lbl, *lbl1;
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    if (!ifx)
+       return 0;
+    
+    /* if the if condition has a false label
+       then we cannot save */
+    if (IC_FALSE(ifx))
+       return 0;
+
+    /* if the minus is not of the form 
+       a = a - 1 */
+    if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
+       !IS_OP_LITERAL(IC_RIGHT(ic)))
+       return 0;
+
+    if (operandLitValue(IC_RIGHT(ic)) != 1)
+       return 0;
+
+    /* if the size of this greater than one then no
+       saving */
+    if (getSize(operandType(IC_RESULT(ic))) > 1)
+       return 0;
+
+    /* otherwise we can save BIG */
+    lbl = newiTempLabel(NULL);
+    lbl1= newiTempLabel(NULL);
+
+    pic16_aopOp(IC_RESULT(ic),ic,FALSE);
+    
+    if (IS_AOP_PREG(IC_RESULT(ic))) {
+       pic16_emitcode("dec","%s",
+                pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+       pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+       pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
+    } else {   
+
+
+      pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
+      pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
+
+      pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+      pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
+
+    }
+/*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
+/*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
+/*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
+/*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
+
+    
+    pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+    ifx->generated = 1;
+    return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genReceive - generate code for a receive iCode                  */
+/*-----------------------------------------------------------------*/
+static void genReceive (iCode *ic)
+{    
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  if (isOperandInFarSpace(IC_RESULT(ic)) && 
+      ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
+       IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
+
+    int size = getSize(operandType(IC_RESULT(ic)));
+    int offset =  pic16_fReturnSizePic - size;
+    while (size--) {
+      pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
+                                   fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
+      offset++;
+    }
+    pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
+    size = AOP_SIZE(IC_RESULT(ic));
+    offset = 0;
+    while (size--) {
+      pic16_emitcode ("pop","acc");
+      pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
+    }
+       
+  } else {
+    _G.accInUse++;
+    pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
+    _G.accInUse--;
+    assignResultValue(IC_RESULT(ic));  
+  }
+
+  pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genpic16Code - generate code for pic16 based controllers        */
+/*-----------------------------------------------------------------*/
+/*
+ * At this point, ralloc.c has gone through the iCode and attempted
+ * to optimize in a way suitable for a PIC. Now we've got to generate
+ * PIC instructions that correspond to the iCode.
+ *
+ * Once the instructions are generated, we'll pass through both the
+ * peep hole optimizer and the pCode optimizer.
+ *-----------------------------------------------------------------*/
+
+void genpic16Code (iCode *lic)
+{
+    iCode *ic;
+    int cln = 0;
+
+    lineHead = lineCurr = NULL;
+
+    pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
+    pic16_addpBlock(pb);
+
+    /* if debug information required */
+    if (options.debug && currFunc) { 
+      if (currFunc) {
+       cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
+       _G.debugLine = 1;
+       if (IS_STATIC(currFunc->etype)) {
+         pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
+         //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
+       } else {
+         pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
+         //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
+       }
+       _G.debugLine = 0;
+      }
+    }
+
+
+    for (ic = lic ; ic ; ic = ic->next ) {
+
+      DEBUGpic16_emitcode(";ic","");
+       if ( cln != ic->lineno ) {
+           if ( options.debug ) {
+               _G.debugLine = 1;
+               pic16_emitcode("",";C$%s$%d$%d$%d ==.",
+                        FileBaseName(ic->filename),ic->lineno,
+                        ic->level,ic->block);
+               _G.debugLine = 0;
+           }
+           /*
+             pic16_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
+             pic16_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
+             printCLine(ic->filename, ic->lineno));
+           */
+           pic16_addpCode2pBlock(pb,
+                           pic16_newpCodeCSource(ic->lineno, 
+                                           ic->filename, 
+                                           printCLine(ic->filename, ic->lineno)));
+
+           cln = ic->lineno ;
+       }
+       /* if the result is marked as
+          spilt and rematerializable or code for
+          this has already been generated then
+          do nothing */
+       if (resultRemat(ic) || ic->generated ) 
+           continue ;
+       
+       /* depending on the operation */
+       switch (ic->op) {
+       case '!' :
+           genNot(ic);
+           break;
+           
+       case '~' :
+           genCpl(ic);
+           break;
+           
+       case UNARYMINUS:
+           genUminus (ic);
+           break;
+           
+       case IPUSH:
+           genIpush (ic);
+           break;
+           
+       case IPOP:
+           /* IPOP happens only when trying to restore a 
+              spilt live range, if there is an ifx statement
+              following this pop then the if statement might
+              be using some of the registers being popped which
+              would destroy the contents of the register so
+              we need to check for this condition and handle it */
+           if (ic->next            && 
+               ic->next->op == IFX &&
+               regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
+               genIfx (ic->next,ic);
+           else
+               genIpop (ic);
+           break; 
+           
+       case CALL:
+           genCall (ic);
+           break;
+           
+       case PCALL:
+           genPcall (ic);
+           break;
+           
+       case FUNCTION:
+           genFunction (ic);
+           break;
+           
+       case ENDFUNCTION:
+           genEndFunction (ic);
+           break;
+           
+       case RETURN:
+           genRet (ic);
+           break;
+           
+       case LABEL:
+           genLabel (ic);
+           break;
+           
+       case GOTO:
+           genGoto (ic);
+           break;
+           
+       case '+' :
+           pic16_genPlus (ic) ;
+           break;
+           
+       case '-' :
+           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
+               pic16_genMinus (ic);
+           break;
+           
+       case '*' :
+           genMult (ic);
+           break;
+           
+       case '/' :
+           genDiv (ic) ;
+           break;
+           
+       case '%' :
+           genMod (ic);
+           break;
+           
+       case '>' :
+           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
+           break;
+           
+       case '<' :
+           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;
+           
+       case LE_OP:
+       case GE_OP:
+       case NE_OP:
+           
+           /* note these two are xlated by algebraic equivalence
+              during parsing SDCC.y */
+           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+                  "got '>=' or '<=' shouldn't have come here");
+           break;      
+           
+       case EQ_OP:
+           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;          
+           
+       case AND_OP:
+           genAndOp (ic);
+           break;
+           
+       case OR_OP:
+           genOrOp (ic);
+           break;
+           
+       case '^' :
+           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;
+           
+       case '|' :
+               genOr (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;
+           
+       case BITWISEAND:
+            genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;
+           
+       case INLINEASM:
+           genInline (ic);
+           break;
+           
+       case RRC:
+           genRRC (ic);
+           break;
+           
+       case RLC:
+           genRLC (ic);
+           break;
+           
+       case GETHBIT:
+           genGetHbit (ic);
+           break;
+           
+       case LEFT_OP:
+           genLeftShift (ic);
+           break;
+           
+       case RIGHT_OP:
+           genRightShift (ic);
+           break;
+           
+       case GET_VALUE_AT_ADDRESS:
+           genPointerGet(ic);
+           break;
+           
+       case '=' :
+           if (POINTER_SET(ic))
+               genPointerSet(ic);
+           else
+               genAssign(ic);
+           break;
+           
+       case IFX:
+           genIfx (ic,NULL);
+           break;
+           
+       case ADDRESS_OF:
+           genAddrOf (ic);
+           break;
+           
+       case JUMPTABLE:
+           genJumpTab (ic);
+           break;
+           
+       case CAST:
+           genCast (ic);
+           break;
+           
+       case RECEIVE:
+           genReceive(ic);
+           break;
+           
+       case SEND:
+           addSet(&_G.sendSet,ic);
+           break;
+
+       default :
+           ic = ic;
+        }
+    }
+    
+
+    /* now we are ready to call the 
+       peep hole optimizer */
+    if (!options.nopeep) {
+      peepHole (&lineHead);
+    }
+    /* now do the actual printing */
+    printLine (lineHead,codeOutFile);
+
+#ifdef PCODE_DEBUG
+    DFPRINTF((stderr,"printing pBlock\n\n"));
+    pic16_printpBlock(stdout,pb);
+#endif
+
+    return;
+}
diff --git a/src/pic16/gen.h b/src/pic16/gen.h
new file mode 100644 (file)
index 0000000..8b72f5d
--- /dev/null
@@ -0,0 +1,181 @@
+/*-------------------------------------------------------------------------
+  SDCCgen51.h - header file for code generation for 8051
+
+             Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+            PIC port   - T. Scott Dattalo scott@dattalo.com (2000)
+            PIC16 port   - Martin Dubuc m.dubuc@rogers.com (2000)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+
+#ifndef SDCCGENPIC14_H
+#define SDCCGENPIC14_H
+
+struct pCodeOp;
+
+enum
+  {
+    AOP_LIT = 1,
+    AOP_REG, AOP_DIR,
+    AOP_DPTR, AOP_DPTR2, AOP_R0, AOP_R1,
+    AOP_STK, AOP_IMMD, AOP_STR,
+    AOP_CRY, AOP_ACC,
+    AOP_PCODE
+
+  };
+
+/* type asmop : a homogenised type for 
+   all the different spaces an operand can be
+   in */
+typedef struct asmop
+  {
+
+    short type;                        /* can have values
+                                  AOP_LIT    -  operand is a literal value
+                                  AOP_REG    -  is in registers
+                                  AOP_DIR    -  direct just a name
+                                  AOP_DPTR   -  dptr contains address of operand
+                                  AOP_DPTR2  -  dptr2 contains address of operand (DS80C390 only).
+                                  AOP_R0/R1  -  r0/r1 contains address of operand               
+                                  AOP_STK    -  should be pushed on stack this
+                                  can happen only for the result
+                                  AOP_IMMD   -  immediate value for eg. remateriazable 
+                                  AOP_CRY    -  carry contains the value of this
+                                  AOP_STR    -  array of strings
+                                  AOP_ACC    -  result is in the acc:b pair
+                                */
+    short coff;                        /* current offset */
+    short size;                        /* total size */
+    unsigned code:1;           /* is in Code space */
+    unsigned paged:1;          /* in paged memory  */
+    unsigned freed:1;          /* already freed    */
+    union
+      {
+       value *aop_lit;         /* if literal */
+       regs *aop_reg[4];       /* array of registers */
+       char *aop_dir;          /* if direct  */
+       regs *aop_ptr;          /* either -> to r0 or r1 */
+       char *aop_immd;         /* if immediate others are implied */
+       int aop_stk;            /* stack offset when AOP_STK */
+       char *aop_str[4];       /* just a string array containing the location */
+/*     regs *aop_alloc_reg;     * points to a dynamically allocated register */
+       pCodeOp *pcop;
+      }
+    aopu;
+  }
+asmop;
+
+void genpic16Code (iCode *);
+
+//extern char *fReturnpic16[];
+//extern char *fReturn390[];
+extern unsigned pic16_fReturnSizePic;
+//extern char **fReturn;
+
+
+#define AOP(op) op->aop
+#define AOP_TYPE(op) AOP(op)->type
+#define AOP_SIZE(op) AOP(op)->size
+#define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
+                       AOP_TYPE(x) == AOP_R0))
+
+#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
+                        AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
+                         AOP(x)->paged)) 
+
+#define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
+                      (x->aopu.aop_reg[0] == pic16_regWithIdx(R0_IDX) || \
+                      x->aopu.aop_reg[0] == pic16_regWithIdx(R1_IDX) )))
+
+#define RESULTONSTACK(x) \
+                         (IC_RESULT(x) && IC_RESULT(x)->aop && \
+                         IC_RESULT(x)->aop->type == AOP_STK )
+
+#define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) pic16_emitcode(";XXX mov","a,%s  %s,%d",x,__FILE__,__LINE__);
+#define CLRC    pic16_emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
+
+#define BIT_NUMBER(x) (x & 7)
+#define BIT_REGISTER(x) (x>>3)
+
+
+#define LSB     0
+#define MSB16   1
+#define MSB24   2
+#define MSB32   3
+
+
+#define FUNCTION_LABEL_INC  40
+
+/*-----------------------------------------------------------------*/
+/* Macros for emitting skip instructions                           */
+/*-----------------------------------------------------------------*/
+
+#define emitSKPC    pic16_emitpcode(POC_BTFSS,pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_C_BIT))
+#define emitSKPNC   pic16_emitpcode(POC_BTFSC,pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_C_BIT))
+#define emitSKPZ    pic16_emitpcode(POC_BTFSS,pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_Z_BIT))
+#define emitSKPNZ   pic16_emitpcode(POC_BTFSC,pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_Z_BIT))
+#define emitSKPDC   pic16_emitpcode(POC_BTFSS,pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_DC_BIT))
+#define emitSKPNDC  pic16_emitpcode(POC_BTFSC,pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_DC_BIT))
+#define emitCLRZ    pic16_emitpcode(POC_BCF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_Z_BIT))
+#define emitCLRC    pic16_emitpcode(POC_BCF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_C_BIT))
+#define emitCLRDC   pic16_emitpcode(POC_BCF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_DC_BIT))
+#define emitSETZ    pic16_emitpcode(POC_BSF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_Z_BIT))
+#define emitSETC    pic16_emitpcode(POC_BSF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_C_BIT))
+#define emitSETDC   pic16_emitpcode(POC_BSF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_DC_BIT))
+
+int pic16_getDataSize(operand *op);
+void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop);
+void pic16_emitpLabel(int key);
+void pic16_emitcode (char *inst,char *fmt, ...);
+void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
+bool pic16_sameRegs (asmop *aop1, asmop *aop2 );
+char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname);
+
+
+bool pic16_genPlusIncr (iCode *ic);
+void pic16_outBitAcc(operand *result);
+void pic16_genPlusBits (iCode *ic);
+void pic16_genPlus (iCode *ic);
+bool pic16_genMinusDec (iCode *ic);
+void pic16_addSign(operand *result, int offset, int sign);
+void pic16_genMinusBits (iCode *ic);
+void pic16_genMinus (iCode *ic);
+
+
+pCodeOp *pic16_popGetLabel(unsigned int key);
+pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
+pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
+pCodeOp *pic16_popGetLit(unsigned int lit);
+pCodeOp *popGetWithString(char *str);
+pCodeOp *pic16_popGet (asmop *aop, int offset);//, bool bit16, bool dname);
+pCodeOp *pic16_popGetTempReg(void);
+void pic16_popReleaseTempReg(pCodeOp *pcop);
+
+
+void pic16_aopPut (asmop *aop, char *s, int offset);
+void pic16_outAcc(operand *result);
+void pic16_aopOp (operand *op, iCode *ic, bool result);
+void pic16_outBitC(operand *result);
+void pic16_toBoolean(operand *oper);
+void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop);
+const char *pic16_pCodeOpType(  pCodeOp *pcop);
+
+
+
+#endif
diff --git a/src/pic16/genarith.c b/src/pic16/genarith.c
new file mode 100644 (file)
index 0000000..0c8f6ff
--- /dev/null
@@ -0,0 +1,1971 @@
+/*-------------------------------------------------------------------------
+  genarith.c - source file for code generation - arithmetic 
+  
+  Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+         and -  Jean-Louis VERN.jlvern@writeme.com (1999)
+  Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
+  PIC port   -  Scott Dattalo scott@dattalo.com (2000)
+  PIC16 port   -  Martin Dubuc m.dubuc@rogers.com (2002)
+  
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+  
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  
+  In other words, you are welcome to use, share and improve this program.
+  You are forbidden to forbid anyone else to use, share and improve
+  what you give them.   Help stamp out software-hoarding!
+  
+  Notes:
+  000123 mlh   Moved aopLiteral to SDCCglue.c to help the split
+               Made everything static
+-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "SDCCglobl.h"
+#include "newalloc.h"
+
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+#define __FUNCTION__           __FILE__
+#endif
+
+#ifdef HAVE_SYS_ISA_DEFS_H
+#include <sys/isa_defs.h>
+#else
+#ifdef HAVE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#else
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#else
+#if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+#warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
+#warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
+#endif
+#endif
+#endif
+#endif
+
+#include "common.h"
+#include "SDCCpeeph.h"
+#include "ralloc.h"
+#include "pcode.h"
+#include "gen.h"
+
+
+#define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
+void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result);
+
+const char *pic16_AopType(short type)
+{
+  switch(type) {
+  case AOP_LIT:
+    return "AOP_LIT";
+    break;
+  case AOP_REG:
+    return "AOP_REG";
+    break;
+  case AOP_DIR:
+    return "AOP_DIR";
+    break;
+  case AOP_DPTR:
+    return "AOP_DPTR";
+    break;
+  case AOP_DPTR2:
+    return "AOP_DPTR2";
+    break;
+  case AOP_R0:
+    return "AOP_R0";
+    break;
+  case AOP_R1:
+    return "AOP_R1";
+    break;
+  case AOP_STK:
+    return "AOP_STK";
+    break;
+  case AOP_IMMD:
+    return "AOP_IMMD";
+    break;
+  case AOP_STR:
+    return "AOP_STR";
+    break;
+  case AOP_CRY:
+    return "AOP_CRY";
+    break;
+  case AOP_ACC:
+    return "AOP_ACC";
+    break;
+  case AOP_PCODE:
+    return "AOP_PCODE";
+    break;
+  }
+
+  return "BAD TYPE";
+}
+
+const char *pic16_pCodeOpType(  pCodeOp *pcop)
+{
+
+  if(pcop) {
+
+    switch(pcop->type) {
+
+    case  PO_NONE:
+      return "PO_NONE";
+    case  PO_W:
+      return  "PO_W";
+    case  PO_WREG:
+      return  "PO_WREG";
+    case  PO_STATUS:
+      return  "PO_STATUS";
+    case  PO_BSR:
+      return  "PO_BSR";
+    case  PO_FSR0:
+      return  "PO_FSR0";
+    case  PO_INDF0:
+      return  "PO_INDF0";
+    case  PO_INTCON:
+      return  "PO_INTCON";
+    case  PO_GPR_REGISTER:
+      return  "PO_GPR_REGISTER";
+    case  PO_GPR_BIT:
+      return  "PO_GPR_BIT";
+    case  PO_GPR_TEMP:
+      return  "PO_GPR_TEMP";
+    case  PO_SFR_REGISTER:
+      return  "PO_SFR_REGISTER";
+    case  PO_PCL:
+      return  "PO_PCL";
+    case  PO_PCLATH:
+      return  "PO_PCLATH";
+    case PO_LITERAL:
+      return  "PO_LITERAL";
+    case PO_REL_ADDR:
+      return "PO_REL_ADDR";
+    case  PO_IMMEDIATE:
+      return  "PO_IMMEDIATE";
+    case  PO_DIR:
+      return  "PO_DIR";
+    case  PO_CRY:
+      return  "PO_CRY";
+    case  PO_BIT:
+      return  "PO_BIT";
+    case  PO_STR:
+      return  "PO_STR";
+    case  PO_LABEL:
+      return  "PO_LABEL";
+    case  PO_WILD:
+      return  "PO_WILD";
+    }
+  }
+
+  return "BAD PO_TYPE";
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_genPlusIncr :- does addition with increment if possible         */
+/*-----------------------------------------------------------------*/
+bool pic16_genPlusIncr (iCode *ic)
+{
+    unsigned int icount ;
+    unsigned int size = pic16_getDataSize(IC_RESULT(ic));
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    DEBUGpic16_emitcode ("; ","result %s, left %s, right %s",
+                        pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
+                        pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
+                        pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
+
+    /* will try to generate an increment */
+    /* if the right side is not a literal 
+       we cannot */
+    if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
+        return FALSE ;
+    
+    DEBUGpic16_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
+    /* if the literal value of the right hand side
+       is greater than 1 then it is faster to add */
+    if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
+        return FALSE ;
+    
+    /* if increment 16 bits in register */
+    if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
+        (icount == 1)) {
+
+      int offset = MSB16;
+
+      pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),LSB));
+      //pic16_emitcode("incf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
+
+      while(--size) {
+       emitSKPNZ;
+       pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),offset++));
+       //pic16_emitcode(" incf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
+      }
+
+      return TRUE;
+    }
+    
+    DEBUGpic16_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
+    /* if left is in accumulator  - probably a bit operation*/
+    if( strcmp(pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a")  &&
+       (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
+      
+      pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
+      pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
+              AOP(IC_RESULT(ic))->aopu.aop_dir,
+              AOP(IC_RESULT(ic))->aopu.aop_dir);
+      if(icount)
+       pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
+      //pic16_emitcode("xorlw","1");
+      else
+       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
+      //pic16_emitcode("andlw","1");
+
+      emitSKPZ;
+      pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
+      pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
+              AOP(IC_RESULT(ic))->aopu.aop_dir,
+              AOP(IC_RESULT(ic))->aopu.aop_dir);
+
+      return TRUE;
+    }
+
+
+
+    /* if the sizes are greater than 1 then we cannot */
+    if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
+        AOP_SIZE(IC_LEFT(ic)) > 1   )
+        return FALSE ;
+    
+    /* If we are incrementing the same register by two: */
+
+    if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+       
+      while (icount--) 
+       pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
+      //pic16_emitcode("incf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+       
+      return TRUE ;
+    }
+    
+    DEBUGpic16_emitcode ("; ","couldn't increment ");
+
+    return FALSE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_outBitAcc - output a bit in acc                                 */
+/*-----------------------------------------------------------------*/
+void pic16_outBitAcc(operand *result)
+{
+    symbol *tlbl = newiTempLabel(NULL);
+    /* if the result is a bit */
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    if (AOP_TYPE(result) == AOP_CRY){
+        pic16_aopPut(AOP(result),"a",0);
+    }
+    else {
+        pic16_emitcode("jz","%05d_DS_",tlbl->key+100);
+        pic16_emitcode("mov","a,#01");
+        pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+        pic16_outAcc(result);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_genPlusBits - generates code for addition of two bits           */
+/*-----------------------------------------------------------------*/
+void pic16_genPlusBits (iCode *ic)
+{
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  DEBUGpic16_emitcode ("; ","result %s, left %s, right %s",
+                      pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
+                      pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
+                      pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
+  /*
+    The following block of code will add two bits. 
+    Note that it'll even work if the destination is
+    the carry (C in the status register).
+    It won't work if the 'Z' bit is a source or destination.
+  */
+
+  /* If the result is stored in the accumulator (w) */
+  //if(strcmp(pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
+  switch(AOP_TYPE(IC_RESULT(ic))) {
+  case AOP_ACC:
+    pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
+    pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
+    pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
+    pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
+    pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
+
+    pic16_emitcode("clrw","");
+    pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
+                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
+    pic16_emitcode("xorlw","1");
+    pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                  AOP(IC_LEFT(ic))->aopu.aop_dir,
+                  AOP(IC_LEFT(ic))->aopu.aop_dir);
+    pic16_emitcode("xorlw","1");
+    break;
+  case AOP_REG:
+    pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
+    pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
+    pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
+    pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
+    pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
+    pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
+    break;
+  default:
+    pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_RESULT(ic)),0));
+    pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+    pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
+    pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
+    pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
+    pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+    pic16_emitcode("movlw","(1 << (%s & 7))",
+                  AOP(IC_RESULT(ic))->aopu.aop_dir,
+                  AOP(IC_RESULT(ic))->aopu.aop_dir);
+    pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
+                  AOP(IC_RESULT(ic))->aopu.aop_dir,
+                  AOP(IC_RESULT(ic))->aopu.aop_dir);
+    pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
+                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
+    pic16_emitcode("xorwf","(%s >>3),f",
+                  AOP(IC_RESULT(ic))->aopu.aop_dir);
+    pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                  AOP(IC_LEFT(ic))->aopu.aop_dir,
+                  AOP(IC_LEFT(ic))->aopu.aop_dir);
+    pic16_emitcode("xorwf","(%s>>3),f",
+                  AOP(IC_RESULT(ic))->aopu.aop_dir);
+    break;
+  }
+
+}
+
+#if 0
+/* This is the original version of this code.
+ *
+ * This is being kept around for reference, 
+ * because I am not entirely sure I got it right...
+ */
+static void adjustArithmeticResult(iCode *ic)
+{
+    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
+       AOP_SIZE(IC_LEFT(ic)) == 3   &&
+       !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
+       pic16_aopPut(AOP(IC_RESULT(ic)),
+              pic16_aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
+              2);
+
+    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
+       AOP_SIZE(IC_RIGHT(ic)) == 3   &&
+       !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
+       pic16_aopPut(AOP(IC_RESULT(ic)),
+              pic16_aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
+              2);
+    
+    if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
+       AOP_SIZE(IC_LEFT(ic)) < 3    &&
+       AOP_SIZE(IC_RIGHT(ic)) < 3   &&
+       !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
+       !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
+       char buffer[5];
+       sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
+       pic16_aopPut(AOP(IC_RESULT(ic)),buffer,2);
+    }
+}
+//#else
+/* This is the pure and virtuous version of this code.
+ * I'm pretty certain it's right, but not enough to toss the old 
+ * code just yet...
+ */
+static void adjustArithmeticResult(iCode *ic)
+{
+    if (opIsGptr(IC_RESULT(ic)) &&
+       opIsGptr(IC_LEFT(ic))   &&
+       !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
+    {
+       pic16_aopPut(AOP(IC_RESULT(ic)),
+              pic16_aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
+              GPTRSIZE - 1);
+    }
+
+    if (opIsGptr(IC_RESULT(ic)) &&
+        opIsGptr(IC_RIGHT(ic))   &&
+       !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
+    {
+       pic16_aopPut(AOP(IC_RESULT(ic)),
+              pic16_aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
+              GPTRSIZE - 1);
+    }
+
+    if (opIsGptr(IC_RESULT(ic))           &&
+        AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
+        AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
+        !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
+        !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
+        char buffer[5];
+        sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
+        pic16_aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
+     }
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* genAddlit - generates code for addition                         */
+/*-----------------------------------------------------------------*/
+static void genAddLit2byte (operand *result, int offr, int lit)
+{
+
+  switch(lit & 0xff) {
+  case 0:
+    break;
+  case 1:
+    pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offr));
+    break;
+  case 0xff:
+    pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
+    break;
+  default:
+    pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
+    pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
+  }
+
+}
+
+static void emitMOVWF(operand *reg, int offset)
+{
+  if(!reg)
+    return;
+
+  if (AOP_TYPE(reg) == AOP_ACC) {
+    DEBUGpic16_emitcode ("; ***","%s  %d ignoring mov into W",__FUNCTION__,__LINE__);
+    return;
+  }
+
+  pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(reg),offset));
+
+}
+
+static void genAddLit (iCode *ic, int lit)
+{
+
+  int size,same;
+  int lo;
+
+  operand *result;
+  operand *left;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+
+  left = IC_LEFT(ic);
+  result = IC_RESULT(ic);
+  same = pic16_sameRegs(AOP(left), AOP(result));
+  size = pic16_getDataSize(result);
+
+  if(same) {
+
+    /* Handle special cases first */
+    if(size == 1) 
+      genAddLit2byte (result, 0, lit);
+     
+    else if(size == 2) {
+      int hi = 0xff & (lit >> 8);
+      lo = lit & 0xff;
+
+      switch(hi) {
+      case 0: 
+
+       /* lit = 0x00LL */
+       DEBUGpic16_emitcode ("; hi = 0","%s  %d",__FUNCTION__,__LINE__);
+       switch(lo) {
+       case 0:
+         break;
+       case 1:
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
+         emitSKPNZ;
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         break;
+       case 0xff:
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+
+         break;
+       default:
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
+         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
+         emitSKPNC;
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+
+
+       }
+       break;
+
+      case 1:
+       /* lit = 0x01LL */
+       DEBUGpic16_emitcode ("; hi = 1","%s  %d",__FUNCTION__,__LINE__);
+       switch(lo) {
+       case 0:  /* 0x0100 */
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         break;
+       case 1:  /* 0x0101  */
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
+         emitSKPNZ;
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         break;
+       case 0xff: /* 0x01ff */
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+       }         
+       break;
+
+      case 0xff:
+       DEBUGpic16_emitcode ("; hi = ff","%s  %d",__FUNCTION__,__LINE__);
+       /* lit = 0xffLL */
+       switch(lo) {
+       case 0:  /* 0xff00 */
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
+         break;
+       case 1:  /*0xff01 */
+         pic16_emitpcode(POC_INCFSZ, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
+         break;
+/*     case 0xff: * 0xffff *
+         pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         break;
+*/
+       default:
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
+         emitSKPC;
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
+         
+       }
+
+       break;
+       
+      default:
+       DEBUGpic16_emitcode ("; hi is generic","%d   %s  %d",hi,__FUNCTION__,__LINE__);
+
+       /* lit = 0xHHLL */
+       switch(lo) {
+       case 0:  /* 0xHH00 */
+         genAddLit2byte (result, MSB16, hi);
+         break;
+       case 1:  /* 0xHH01 */
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit((hi+1)&0xff));
+         pic16_emitpcode(POC_INCFSZ, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
+         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16));
+         break;
+/*     case 0xff: * 0xHHff *
+         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
+         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
+         break;
+*/     default:  /* 0xHHLL */
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+         pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
+         emitSKPNC;
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit((hi+1) & 0xff));
+         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16));
+         break;
+       }
+
+      }
+    } else {
+      int carry_info = 0;
+      int offset = 0;
+      /* size > 2 */
+      DEBUGpic16_emitcode (";  add lit to long","%s  %d",__FUNCTION__,__LINE__);
+
+      while(size--) {
+       lo = BYTEofLONG(lit,0);
+
+       if(carry_info) {
+         switch(lo) {
+         case 0:
+           switch(carry_info) {
+           case 1:
+             emitSKPNZ;
+             pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset));
+             break;
+           case 2:
+             pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
+             pic16_emitpcode(POC_ANDLW, pic16_popGetLit(1));
+             pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
+             break;
+           default: /* carry_info = 3  */
+             emitSKPNC;
+             pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset));
+             carry_info = 1;
+             break;
+           }
+           break;
+         case 0xff:
+           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+           if(carry_info==1) 
+             emitSKPZ;
+           else
+             emitSKPC;
+           pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
+           break;
+         default:
+           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+           if(carry_info==1) 
+             emitSKPNZ;
+           else
+             emitSKPNC;
+           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo+1));
+           pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
+           carry_info=2;
+           break;
+         }
+       }else {
+         /* no carry info from previous step */
+         /* this means this is the first time to add */
+         switch(lo) {
+         case 0:
+           break;
+         case 1:
+           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset));
+           carry_info=1;
+           break;
+         default:
+           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+           pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
+           if(lit <0x100) 
+             carry_info = 3;  /* Were adding only one byte and propogating the carry */
+           else
+             carry_info = 2;
+           break;
+         }
+       }
+       offset++;
+       lit >>= 8;
+      }
+    
+/*
+      lo = BYTEofLONG(lit,0);
+
+      if(lit < 0x100) {
+       if(lo) {
+         if(lo == 1) {
+           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+           emitSKPNZ;
+         } else {
+           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+           pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+           emitSKPNC;
+         }
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),1,FALSE,FALSE));
+         emitSKPNZ;
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),2,FALSE,FALSE));
+         emitSKPNZ;
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),3,FALSE,FALSE));
+
+       } 
+      } 
+    }
+
+*/
+    }
+  } else {
+    int offset = 1;
+    DEBUGpic16_emitcode (";  left and result aren't same","%s  %d",__FUNCTION__,__LINE__);
+
+    if(size == 1) {
+
+      if(AOP_TYPE(left) == AOP_ACC) {
+       /* left addend is already in accumulator */
+       switch(lit & 0xff) {
+       case 0:
+         //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         emitMOVWF(result,0);
+         break;
+       default:
+         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(lit & 0xff));
+         //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         emitMOVWF(result,0);
+       }
+      } else {
+       /* left addend is in a register */
+       switch(lit & 0xff) {
+       case 0:
+         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+         emitMOVWF(result, 0);
+         //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         emitMOVWF(result,0);
+         break;
+       case 1:
+         pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0));
+         //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         emitMOVWF(result,0);
+         break;
+       case 0xff:
+         pic16_emitpcode(POC_DECFW, pic16_popGet(AOP(left),0));
+         //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         emitMOVWF(result,0);
+         break;
+       default:
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+         pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
+         //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         emitMOVWF(result,0);
+       }
+      }
+
+    } else {
+      int clear_carry=0;
+
+      /* left is not the accumulator */
+      if(lit & 0xff) {
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
+      } else {
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+       /* We don't know the state of the carry bit at this point */
+       clear_carry = 1;
+      }
+      //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+      emitMOVWF(result,0);
+      while(--size) {
+      
+       lit >>= 8;
+       if(lit & 0xff) {
+         if(clear_carry) {
+           /* The ls byte of the lit must've been zero - that 
+              means we don't have to deal with carry */
+
+           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+           pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(left),offset));
+           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(left),offset));
+
+           clear_carry = 0;
+
+         } else {
+           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset,FALSE,FALSE));
+           emitMOVWF(result,offset);
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
+           emitSKPNC;
+           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
+           pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),offset));
+         }
+
+       } else {
+         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offset));
+         pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offset));
+         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
+         pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
+       }
+       offset++;
+      }
+    }
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_genPlus - generates code for addition                           */
+/*-----------------------------------------------------------------*/
+void pic16_genPlus (iCode *ic)
+{
+  int size, offset = 0;
+
+  /* special cases :- */
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  pic16_aopOp (IC_LEFT(ic),ic,FALSE);
+  pic16_aopOp (IC_RIGHT(ic),ic,FALSE);
+  pic16_aopOp (IC_RESULT(ic),ic,TRUE);
+
+  DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),IC_RIGHT(ic),IC_RESULT(ic));
+
+  /* if literal, literal on the right or
+     if left requires ACC or right is already
+     in ACC */
+
+  if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
+    operand *t = IC_RIGHT(ic);
+    IC_RIGHT(ic) = IC_LEFT(ic);
+    IC_LEFT(ic) = t;
+  }
+
+  /* if both left & right are in bit space */
+  if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
+      AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
+    pic16_genPlusBits (ic);
+    goto release ;
+  }
+
+  /* if left in bit space & right literal */
+  if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
+      AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
+    /* if result in bit space */
+    if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
+      if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
+       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_RESULT(ic)),0));
+       if (!pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
+         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
+       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
+      }
+    } else {
+      size = pic16_getDataSize(IC_RESULT(ic));
+      while (size--) {
+       MOVA(pic16_aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
+       pic16_emitcode("addc","a,#00  ;%d",__LINE__);
+       pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+      }
+    }
+    goto release ;
+  }
+
+  /* if I can do an increment instead
+     of add then GOOD for ME */
+  if (pic16_genPlusIncr (ic) == TRUE)
+    goto release;   
+
+  size = pic16_getDataSize(IC_RESULT(ic));
+
+  if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
+    /* Add a literal to something else */
+    //bool know_W=0;
+    unsigned lit = (unsigned) floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+    //      unsigned l1=0;
+
+    //      offset = 0;
+    DEBUGpic16_emitcode(";","adding lit to something. size %d",size);
+
+    genAddLit (ic,  lit);
+    goto release;
+
+  } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
+
+    pic16_emitcode(";bitadd","right is bit: %s",pic16_aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
+    pic16_emitcode(";bitadd","left is bit: %s",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+    pic16_emitcode(";bitadd","result is bit: %s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+
+    /* here we are adding a bit to a char or int */
+    if(size == 1) {
+      if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+
+       pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+       pic16_emitpcode(POC_INCF ,  pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
+                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
+       pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+      } else {
+
+       if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
+         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+         pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
+
+         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                        AOP(IC_RIGHT(ic))->aopu.aop_dir,
+                        AOP(IC_RIGHT(ic))->aopu.aop_dir);
+         pic16_emitcode(" xorlw","1");
+       } else {
+         pic16_emitpcode(POC_MOVFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
+         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+         pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
+
+         pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                        AOP(IC_RIGHT(ic))->aopu.aop_dir,
+                        AOP(IC_RIGHT(ic))->aopu.aop_dir);
+         pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+       }
+         
+       if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
+           
+         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
+           pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
+           pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+           emitSKPZ;
+           pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+         } else {
+           pic16_emitpcode(POC_MOVWF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+         }
+       }
+      }
+
+    } else {
+      int offset = 1;
+      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+      if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+       emitCLRZ;
+       pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
+       pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+       pic16_emitcode("clrz","");
+
+       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
+                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
+       pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+
+      } else {
+
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
+       pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
+       pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
+       //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
+       emitMOVWF(IC_RIGHT(ic),0);
+
+       pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
+                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
+       pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+       pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+
+      }
+
+      while(--size){
+       emitSKPZ;
+       pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),offset++));
+       //pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
+      }
+
+    }
+      
+  } else {
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
+
+    /* Add the first bytes */
+
+    if(strcmp(pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+    } else {
+
+      if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
+       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
+       if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
+         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+      } else {
+
+       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(IC_RIGHT(ic)),0));
+
+       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
+         pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(IC_LEFT(ic)),0));
+       else {
+         PIC_OPCODE poc = POC_ADDFW;
+
+         if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && (
+             (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) || 
+             (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE)))
+           poc = POC_ADDLW;
+         pic16_emitpcode(poc, pic16_popGet(AOP(IC_LEFT(ic)),0));
+         if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
+           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+       }
+      }
+    }
+
+    size = min( AOP_SIZE(IC_RESULT(ic)), AOP_SIZE(IC_RIGHT(ic))) - 1;
+    offset = 1;
+
+
+    while(size--){
+      if (!pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
+       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+
+       pic16_emitcode("movf","%s,w",  pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
+       pic16_emitcode("movwf","%s",  pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
+      }
+
+      pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(IC_RIGHT(ic)),offset));
+      emitSKPNC;
+      pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(IC_RIGHT(ic)),offset));
+      pic16_emitpcode(POC_ADDWF,   pic16_popGet(AOP(IC_RESULT(ic)),offset));
+
+      /*
+       pic16_emitcode("movf","%s,w",  pic16_aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
+       emitSKPNC;
+       pic16_emitcode("incfsz","%s,w",pic16_aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
+       pic16_emitcode("addwf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
+      */
+
+      offset++;
+    }
+
+  }
+
+  if (AOP_SIZE(IC_RESULT(ic)) > AOP_SIZE(IC_RIGHT(ic))) {
+    int sign =  !(SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))) |
+                 SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))) );
+
+
+    /* Need to extend result to higher bytes */
+    size = AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_RIGHT(ic)) - 1;
+
+    /* First grab the carry from the lower bytes */
+    pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+    pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+
+
+    if(sign) {
+      /* Now this is really horrid. Gotta check the sign of the addends and propogate
+       * to the result */
+
+      pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_LEFT(ic)),offset-1,FALSE,FALSE),7,0));
+      pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+      pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RIGHT(ic)),offset-1,FALSE,FALSE),7,0));
+      pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+
+      /* if chars or ints or being signed extended to longs: */
+      if(size) {
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE),7,0));
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
+      }
+    }
+
+    offset++;
+    while(size--) {
+      
+      if(sign)
+       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+      else
+       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+
+      offset++;
+    }
+  }
+
+
+  //adjustArithmeticResult(ic);
+
+ release:
+  pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+  pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+  pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_genMinusDec :- does subtraction with decrement if possible     */
+/*-----------------------------------------------------------------*/
+bool pic16_genMinusDec (iCode *ic)
+{
+    unsigned int icount ;
+    unsigned int size = pic16_getDataSize(IC_RESULT(ic));
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* will try to generate an increment */
+    /* if the right side is not a literal 
+    we cannot */
+    if ((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) || 
+       (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) || 
+       (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) )
+        return FALSE ;
+
+    DEBUGpic16_emitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
+
+    /* if the literal value of the right hand side
+    is greater than 4 then it is not worth it */
+    if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
+        return FALSE ;
+
+    /* if decrement 16 bits in register */
+    if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
+        (size > 1) &&
+        (icount == 1)) {
+
+      if(size == 2) { 
+       pic16_emitpcode(POC_DECF,    pic16_popGet(AOP(IC_RESULT(ic)),LSB));
+       pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(IC_RESULT(ic)),LSB));
+       pic16_emitpcode(POC_INCF,    pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
+       pic16_emitpcode(POC_DECF,    pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
+
+       pic16_emitcode("decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
+       pic16_emitcode("incfsz","%s,w",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
+       pic16_emitcode(" decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
+      } else {
+       /* size is 3 or 4 */
+       pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(0xff));
+       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_RESULT(ic)),LSB));
+       emitSKPNC;
+       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
+       emitSKPNC;
+       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_RESULT(ic)),MSB24));
+
+       pic16_emitcode("movlw","0xff");
+       pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
+
+       emitSKPNC;
+       pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
+       emitSKPNC;
+       pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
+
+       if(size > 3) {
+         emitSKPNC;
+         pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_RESULT(ic)),MSB32));
+
+         pic16_emitcode("skpnc","");
+         emitSKPNC;
+         pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
+       }
+
+      }
+
+      return TRUE;
+
+    }
+
+    /* if the sizes are greater than 1 then we cannot */
+    if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
+        AOP_SIZE(IC_LEFT(ic)) > 1   )
+        return FALSE ;
+
+    /* we can if the aops of the left & result match or
+    if they are in registers and the registers are the
+    same */
+    if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
+
+      while (icount--) 
+       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+       //pic16_emitcode ("decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+
+        return TRUE ;
+    }
+
+    DEBUGpic16_emitcode ("; returning"," result=%s, left=%s",
+                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
+                  pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+    if(size==1) {
+
+      pic16_emitcode("decf","%s,w",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+      pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+
+      pic16_emitpcode(POC_DECFW,  pic16_popGet(AOP(IC_LEFT(ic)),0));
+      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+      return TRUE;
+    }
+
+    return FALSE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_addSign - propogate sign bit to higher bytes                    */
+/*-----------------------------------------------------------------*/
+void pic16_addSign(operand *result, int offset, int sign)
+{
+  int size = (pic16_getDataSize(result) - offset);
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  if(size > 0){
+    if(sign && offset) {
+
+      if(size == 1) {
+       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
+       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
+       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
+      } else {
+
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
+       while(size--)
+         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),size));
+
+      }
+    } else
+      while(size--)
+       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_genMinusBits - generates code for subtraction  of two bits      */
+/*-----------------------------------------------------------------*/
+void pic16_genMinusBits (iCode *ic)
+{
+    symbol *lbl = newiTempLabel(NULL);
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
+        pic16_emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
+        pic16_emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
+        pic16_emitcode("cpl","c");
+        pic16_emitcode("","%05d_DS_:",(lbl->key+100));
+        pic16_outBitC(IC_RESULT(ic));
+    }
+    else{
+        pic16_emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
+        pic16_emitcode("subb","a,acc");
+        pic16_emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
+        pic16_emitcode("inc","a");
+        pic16_emitcode("","%05d_DS_:",(lbl->key+100));
+        pic16_aopPut(AOP(IC_RESULT(ic)),"a",0);
+        pic16_addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_genMinus - generates code for subtraction                       */
+/*-----------------------------------------------------------------*/
+void pic16_genMinus (iCode *ic)
+{
+  int size, offset = 0, same=0;
+  unsigned long lit = 0L;
+
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  pic16_aopOp (IC_LEFT(ic),ic,FALSE);
+  pic16_aopOp (IC_RIGHT(ic),ic,FALSE);
+  pic16_aopOp (IC_RESULT(ic),ic,TRUE);
+
+  if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY  &&
+      AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
+    operand *t = IC_RIGHT(ic);
+    IC_RIGHT(ic) = IC_LEFT(ic);
+    IC_LEFT(ic) = t;
+  }
+
+  DEBUGpic16_emitcode ("; ","result %s, left %s, right %s",
+                  pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
+                  pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
+                  pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
+
+  /* special cases :- */
+  /* if both left & right are in bit space */
+  if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
+      AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
+    pic16_genPlusBits (ic);
+    goto release ;
+  }
+
+  /* if I can do an decrement instead
+     of subtract then GOOD for ME */
+  //  if (pic16_genMinusDec (ic) == TRUE)
+  //    goto release;   
+
+  size = pic16_getDataSize(IC_RESULT(ic));   
+  same = pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)));
+
+  if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
+    /* Add a literal to something else */
+
+    lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+    lit = - (long)lit;
+
+    genAddLit ( ic,  lit);
+    
+#if 0
+    /* add the first byte: */
+    pic16_emitcode("movlw","0x%x", lit & 0xff);
+    pic16_emitcode("addwf","%s,f", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+    pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(lit & 0xff));
+    pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_LEFT(ic)),0));
+
+
+    offset = 1;
+    size--;
+
+    while(size-- > 0) {
+
+      lit >>= 8;
+
+      if(lit & 0xff) {
+
+       if((lit & 0xff) == 0xff) {
+         pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(0xff));
+         emitSKPC;
+         pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
+       } else {
+         pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(lit & 0xff));
+         emitSKPNC;
+         pic16_emitpcode(POC_MOVLW,  pic16_popGetLit((lit+1) & 0xff));
+         pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
+       }
+
+      } else {
+       /* do the rlf known zero trick here */
+       pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(1));
+       emitSKPNC;
+       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
+      }
+      offset++;
+    }
+#endif
+  } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
+    // bit subtraction
+
+    pic16_emitcode(";bitsub","right is bit: %s",pic16_aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
+    pic16_emitcode(";bitsub","left is bit: %s",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+    pic16_emitcode(";bitsub","result is bit: %s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+
+    /* here we are subtracting a bit from a char or int */
+    if(size == 1) {
+      if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+
+       pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+       pic16_emitpcode(POC_DECF ,  pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                AOP(IC_RIGHT(ic))->aopu.aop_dir,
+                AOP(IC_RIGHT(ic))->aopu.aop_dir);
+       pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+      } else {
+
+       if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
+         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+         pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
+       }else  if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
+             (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
+
+         lit = (unsigned long)floatFromVal(AOP(IC_LEFT(ic))->aopu.aop_lit);
+
+         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
+           if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
+             if(lit & 1) {
+               pic16_emitpcode(POC_MOVLW , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+               pic16_emitpcode(POC_XORWF , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+             }
+           }else{
+             pic16_emitpcode(POC_BCF ,     pic16_popGet(AOP(IC_RESULT(ic)),0));
+             if(lit & 1) 
+               pic16_emitpcode(POC_BTFSS , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+             else
+               pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+             pic16_emitpcode(POC_BSF ,     pic16_popGet(AOP(IC_RESULT(ic)),0));
+           }
+           goto release;
+         } else {
+           pic16_emitpcode(POC_MOVLW , pic16_popGetLit(lit & 0xff));
+           pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+           pic16_emitpcode(POC_MOVLW , pic16_popGetLit((lit-1) & 0xff));
+           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+         }
+
+       } else {
+         pic16_emitpcode(POC_MOVFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
+         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+         pic16_emitpcode(POC_DECFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
+       }
+         
+       if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
+           
+         pic16_emitpcode(POC_MOVWF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+       } else  {
+         pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
+/*
+         pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+         emitSKPZ;
+         pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+*/
+       }
+
+      }
+
+    }
+  } else   if(// (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) || 
+             (AOP(IC_LEFT(ic))->type == AOP_LIT) &&
+             (AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC)) {
+
+    lit = (unsigned long)floatFromVal(AOP(IC_LEFT(ic))->aopu.aop_lit);
+    DEBUGpic16_emitcode ("; left is lit","line %d result %s, left %s, right %s",__LINE__,
+                  pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
+                  pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
+                  pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
+
+
+    if( (size == 1) && ((lit & 0xff) == 0) ) {
+      /* res = 0 - right */
+      if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
+       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
+       pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
+      } else { 
+       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
+       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
+       pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+      }
+      goto release;
+    }
+
+    pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
+    pic16_emitpcode(POC_SUBLW, pic16_popGetLit(lit & 0xff));    
+    pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+
+    offset = 1;
+    while(--size) {
+      lit >>= 8;
+
+      if(size == 1) {
+       /* This is the last byte in a multibyte subtraction 
+        * There are a couple of tricks we can do by not worrying about 
+        * propogating the carry */
+       if(lit == 0xff) {
+         /* 0xff - x == ~x */
+         if(same) {
+           pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+           emitSKPC;
+           pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+         } else {
+           pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset));
+           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+           emitSKPC;
+           pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+         }
+       } else {
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset));
+           emitSKPC;
+           pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset));
+           pic16_emitpcode(POC_SUBLW, pic16_popGetLit(lit & 0xff));
+           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+       }
+
+       goto release;
+      }
+
+      if(same) {
+
+       if(lit & 0xff) {
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+         emitSKPC;
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & 0xff)-1));
+         pic16_emitpcode(POC_SUBWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+       } else {
+         emitSKPNC;
+         pic16_emitpcode(POC_SUBWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+
+       }
+      } else {
+
+       if(lit & 0xff) {
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+       } else
+         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+
+       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(IC_RIGHT(ic)),offset));
+       emitSKPC;
+       pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(IC_RIGHT(ic)),offset));
+       pic16_emitpcode(POC_SUBWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+      }
+    }
+  
+
+  } else {
+
+    DEBUGpic16_emitcode ("; ","line %d result %s, left %s, right %s",__LINE__,
+                  pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
+                  pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
+                  pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
+
+    if(strcmp(pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
+      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+      pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
+      pic16_emitpcode(POC_SUBLW, pic16_popGetLit(0));
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+    } else {
+
+      if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
+       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
+       pic16_emitpcode(POC_SUBLW, pic16_popGetLit(0));
+       if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
+         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+      } else {
+
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+       if(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC) 
+         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(IC_RIGHT(ic)),0));
+
+       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
+         pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(IC_LEFT(ic)),0));
+       else {
+         if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
+             (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
+           pic16_emitpcode(POC_SUBLW, pic16_popGet(AOP(IC_LEFT(ic)),0));
+         } else {
+           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
+         }
+         if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
+           if ( AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
+             pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+             emitSKPZ;
+             pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+           }else
+             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+         }
+       }
+      }
+    }
+
+    /*
+      pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
+
+      if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+      pic16_emitpcode(POC_SUBFW,  pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+      } else {
+      pic16_emitpcode(POC_SUBFW,  pic16_popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+      }
+    */
+    offset = 1;
+    size--;
+
+    while(size--){
+      if (!pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
+       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+      }
+      pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(IC_RIGHT(ic)),offset));
+      emitSKPC;
+      pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(IC_RIGHT(ic)),offset));
+      pic16_emitpcode(POC_SUBWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+
+      offset++;
+    }
+
+  }
+
+
+  //    adjustArithmeticResult(ic);
+        
+ release:
+  pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+  pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+  pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+}
+/*-----------------------------------------------------------------*
+ * pic_genUMult8XLit_16 - unsigned multiplication of two 8-bit numbers.
+ * 
+ * 
+ *-----------------------------------------------------------------*/
+void pic16_genUMult8XLit_16 (operand *left,
+                            operand *right,
+                            operand *result,
+                            pCodeOpReg *result_hi)
+
+{
+
+  unsigned int lit;
+  unsigned int i,have_first_bit;
+  int same;
+  pCodeOp *temp;
+
+  if (AOP_TYPE(right) != AOP_LIT){
+    fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
+    exit(1);
+  }
+
+
+  if(!result_hi) {
+    result_hi = PCOR(pic16_popGet(AOP(result),1));
+  }
+
+  lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
+  lit &= 0xff;
+  pic16_emitcode(";","Unrolled 8 X 8 multiplication");
+
+  same = pic16_sameRegs(AOP(left), AOP(result));
+
+  if(same) {
+    switch(lit) {
+    case 0:
+      pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(left),0));
+      return;
+    case 2:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      return;
+    case 3:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      return;
+    case 4:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      return;
+    case 5:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 5*F
+      return;
+    case 6:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      return;
+    case 7:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 5*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 7*F
+      return;
+    case 8:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 5*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 8*F
+      return;
+    case 9:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      return;
+    case 10:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 5*F
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      return;
+    case 11:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 5*F
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 8*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 11*F
+      return;
+    case 12:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
+      return;
+    case 13:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 5*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 8*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 13*F
+      return;
+    case 14:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 5*F
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 8*F
+      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 11*F
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 14*F
+      return;
+    case 15:
+      temp = pic16_popGetTempReg();
+      if(!temp) {
+       fprintf(stderr,"ERROR: unable to allocate register. %s:%d\n",__FUNCTION__,__LINE__);
+       exit(1);
+      }
+      pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_MOVWF,  temp);
+      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
+      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_SWAPFW, temp);
+      pic16_emitpcode(POC_SUBWF,  pic16_popGet(AOP(left),0));
+      pic16_popReleaseTempReg(temp);
+      return;
+    case 16:
+      pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
+      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(left),0));
+      return;
+    case 17:
+      pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
+      pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(left),0));
+      return;
+    case 32:
+      pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xe0));
+      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(left),0));
+      return;
+    case 64:
+      pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xc0));
+      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(left),0));
+      return;
+    case 128:
+      pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(left),0));
+      return;
+
+    }
+  } else {
+
+    switch(lit) {
+    case 0:
+      pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
+      return;
+    case 2:
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
+      pic16_emitpcode(POC_RLCF,  pic16_popCopyReg(result_hi));
+      return;
+    }
+
+  }
+
+  pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+  pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
+  pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
+
+  have_first_bit = 0;
+  for(i=0; i<8; i++) {
+
+    if(lit & 1) {
+      pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
+      have_first_bit = 1;
+    }
+
+    if(have_first_bit) {
+      pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(result_hi));
+      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),0));
+    }
+
+    lit >>= 1;
+  }
+
+}
+
+/*-----------------------------------------------------------------*
+ * genUMult8X8_16 - unsigned multiplication of two 8-bit numbers.
+ * 
+ * 
+ *-----------------------------------------------------------------*/
+void pic16_genUMult8X8_16 (operand *left,
+                          operand *right,
+                          operand *result,
+                          pCodeOpReg *result_hi)
+
+{
+
+  int i;
+  int looped = 1;
+
+  if(!result_hi) {
+    result_hi = PCOR(pic16_popGet(AOP(result),1));
+  }
+
+  if (AOP_TYPE(right) == AOP_LIT) {
+    pic16_genUMult8XLit_16(left,right,result,result_hi);
+    return;
+  }
+
+  if(!looped) {
+    pic16_emitcode(";","Unrolled 8 X 8 multiplication");
+
+    pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+    pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
+    pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
+    emitCLRC;
+
+    for(i=0; i<8; i++) {
+      pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),i,0));
+      pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
+      pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(result_hi));
+      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),0));
+    }
+
+
+    /*
+      Here's another version that does the same thing and takes the 
+      same number of instructions. The one above is slightly better
+      because the entry instructions have a higher probability of
+      being optimized out.
+    */
+    /*
+      pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+
+      for(i=0; i<8; i++) {
+      emitSKPNC;
+      pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
+      pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(result_hi));
+      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),0));
+      }
+    */
+
+  } else {
+    symbol  *tlbl = newiTempLabel(NULL);
+    pCodeOp *temp;
+
+
+    pic16_emitcode(";","Looped 8 X 8 multiplication");
+
+    pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
+    pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
+
+    pic16_emitpcode(POC_BSF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),0,FALSE,FALSE),7,0));
+
+    pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+
+    temp = pic16_popGetTempReg();
+    pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(PCOR(temp)));
+
+    pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+
+    pic16_emitpLabel(tlbl->key);
+
+    pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(PCOR(temp)));
+    emitSKPNC;
+    pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
+
+    pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(result_hi));
+    pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),0));
+
+    emitSKPC;
+    pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl->key));
+
+    pic16_popReleaseTempReg(temp);
+
+  }
+}
+
+/*-----------------------------------------------------------------*
+ * pic16_genSMult8X8_16 - signed multiplication of two 8-bit numbers
+ *
+ *  this routine will call the unsigned multiply routine and then
+ * post-fix the sign bit.
+ *-----------------------------------------------------------------*/
+void pic16_genSMult8X8_16 (operand *left,
+                          operand *right,
+                          operand *result,
+                          pCodeOpReg *result_hi)
+{
+
+  if(!result_hi) {
+    result_hi = PCOR(pic16_popGet(AOP(result),1));
+  }
+
+  pic16_genUMult8X8_16(left,right,result,result_hi);
+
+  pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),7,0));
+  pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(result_hi));
+  pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+  pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),7,0));
+  pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(result),1));
+  
+}
+
+/*-----------------------------------------------------------------*
+ * pic16_genMult8X8_8 - multiplication of two 8-bit numbers
+ *
+ *  this routine will call the unsigned multiply 8X8=>16 routine and
+ * then throw away the high byte of the result.
+ *
+ *-----------------------------------------------------------------*/
+void pic16_genMult8X8_8 (operand *left,
+                        operand *right,
+                        operand *result)
+{
+  pCodeOp *result_hi = pic16_popGetTempReg();
+
+  if (AOP_TYPE(right) == AOP_LIT)
+    pic16_genUMult8XLit_16(left,right,result,PCOR(result_hi));
+  else
+    pic16_genUMult8X8_16(left,right,result,PCOR(result_hi));
+
+  pic16_popReleaseTempReg(result_hi);
+}
+#if 0
+/*-----------------------------------------------------------------*/
+/* constMult - generates code for multiplication by a constant     */
+/*-----------------------------------------------------------------*/
+void genMultConst(unsigned C)
+{
+
+  unsigned lit;
+  unsigned sr3; // Shift right 3
+  unsigned mask;
+
+  int size = 1;
+
+  /*
+    Convert a string of 3 binary 1's in the lit into
+    0111 = 1000 - 1;
+  */
+
+  mask = 7 << ( (size*8) - 3);
+  lit = C;
+  sr3 = 0;
+
+  while(mask < (1<<size*8)) {
+
+    if( (mask & lit) == lit) {
+      unsigned lsb;
+
+      /* We found 3 (or more) consecutive 1's */
+
+      lsb = mask & ~(mask & (mask-1));  // lsb of mask.
+
+      consecutive_bits = ((lit + lsb) & lit) ^ lit;
+
+      lit ^= consecutive_bits;
+
+      mask <<= 3;
+
+      sr3 |= (consecutive + lsb);
+
+    }
+
+    mask >>= 1;
+
+  }
+
+}
+
+#endif
diff --git a/src/pic16/glue.c b/src/pic16/glue.c
new file mode 100644 (file)
index 0000000..9c79d34
--- /dev/null
@@ -0,0 +1,966 @@
+/*-------------------------------------------------------------------------
+
+  SDCCglue.c - glues everything we have done together into one file.
+                Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!
+-------------------------------------------------------------------------*/
+
+#include "../common.h"
+#include <time.h>
+#include "ralloc.h"
+#include "pcode.h"
+#include "newalloc.h"
+
+
+#ifdef _BIG_ENDIAN
+  #define _ENDIAN(x)  (3-x)
+#else
+  #define _ENDIAN(x)  (x)
+#endif
+
+#define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
+
+extern symbol *interrupts[256];
+static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
+extern int noAlloc;
+extern set *publics;
+extern unsigned maxInterrupts;
+extern int maxRegBank;
+extern symbol *mainf;
+extern char *VersionString;
+extern FILE *codeOutFile;
+extern set *tmpfileSet;
+extern set *tmpfileNameSet;
+extern char *iComments1;
+extern char *iComments2;
+//extern void emitStaticSeg (memmap * map);
+
+extern DEFSETFUNC (closeTmpFiles);
+extern DEFSETFUNC (rmTmpFiles);
+
+extern void pic16_AnalyzeBanking (void);
+extern void copyFile (FILE * dest, FILE * src);
+extern void pic16_InlinepCode(void);
+extern void pic16_writeUsedRegs(FILE *);
+
+extern void initialComments (FILE * afile);
+extern void printPublics (FILE * afile);
+
+extern void printChar (FILE * ofile, char *s, int plen);
+void  pic16_pCodeInitRegisters(void);
+
+/*-----------------------------------------------------------------*/
+/* aopLiteral - string from a literal value                        */
+/*-----------------------------------------------------------------*/
+int pic16aopLiteral (value *val, int offset)
+{
+  union {
+    float f;
+    unsigned char c[4];
+  } fl;
+
+  /* if it is a float then it gets tricky */
+  /* otherwise it is fairly simple */
+  if (!IS_FLOAT(val->type)) {
+    unsigned long v = (unsigned long) floatFromVal(val);
+
+    return ( (v >> (offset * 8)) & 0xff);
+  }
+
+  /* it is type float */
+  fl.f = (float) floatFromVal(val);
+#ifdef _BIG_ENDIAN    
+  return fl.c[3-offset];
+#else
+  return fl.c[offset];
+#endif
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/* emitRegularMap - emit code for maps with no special cases       */
+/*-----------------------------------------------------------------*/
+static void
+pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
+{
+  symbol *sym;
+  int i, size, bitvars = 0;;
+
+  if (addPublics)
+    fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
+
+  /* print the area name */
+  for (sym = setFirstItem (map->syms); sym;
+       sym = setNextItem (map->syms))
+    {
+
+      /* if extern then do nothing */
+      if (IS_EXTERN (sym->etype))
+       continue;
+
+      /* if allocation required check is needed
+         then check if the symbol really requires
+         allocation only for local variables */
+      if (arFlag && !IS_AGGREGATE (sym->type) &&
+         !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
+         !sym->allocreq && sym->level)
+       continue;
+
+      /* if global variable & not static or extern
+         and addPublics allowed then add it to the public set */
+      if ((sym->level == 0 ||
+          (sym->_isparm && !IS_REGPARM (sym->etype))) &&
+         addPublics &&
+         !IS_STATIC (sym->etype))
+       addSetHead (&publics, sym);
+
+      /* if extern then do nothing or is a function
+         then do nothing */
+      if (IS_FUNC (sym->type))
+       continue;
+#if 0
+      /* print extra debug info if required */
+      if (options.debug || sym->level == 0)
+       {
+
+         cdbSymbol (sym, cdbFile, FALSE, FALSE);
+
+         if (!sym->level)      /* global */
+           if (IS_STATIC (sym->etype))
+             fprintf (map->oFile, "F%s_", moduleName);         /* scope is file */
+           else
+             fprintf (map->oFile, "G_");       /* scope is global */
+         else
+           /* symbol is local */
+           fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
+         fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
+       }
+#endif
+
+      /* if is has an absolute address then generate
+         an equate for this no need to allocate space */
+      if (SPEC_ABSA (sym->etype))
+       {
+         //if (options.debug || sym->level == 0)
+         //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
+
+         fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
+                  sym->rname,
+                  SPEC_ADDR (sym->etype));
+       }
+      else
+       {
+         /* allocate space */
+
+         /* If this is a bit variable, then allocate storage after 8 bits have been declared */
+         /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
+         /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
+         if (IS_BITVAR (sym->etype))
+           {
+             bitvars++;
+           }
+         else
+           {
+             fprintf (map->oFile, "\t%s\n", sym->rname);
+             if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
+               {
+                 for (i = 1; i < size; i++)
+                   fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
+               }
+           }
+         //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
+       }
+       
+       /* if it has a initial value then do it only if
+          it is a global variable */
+       if (sym->ival && sym->level == 0) {
+           ast *ival = NULL;
+           
+           if (IS_AGGREGATE (sym->type))
+               ival = initAggregates (sym, sym->ival, NULL);
+           else
+               ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
+                               decorateType (resolveSymbols (list2expr (sym->ival))));
+           codeOutFile = statsg->oFile;
+           GcurMemmap = statsg;
+           eBBlockFromiCode (iCodeFromAst (ival));
+           sym->ival = NULL;
+       }
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* printIvalType - generates ival for int/char                     */
+/*-----------------------------------------------------------------*/
+static void 
+printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
+{
+  value *val;
+  unsigned long ulval;
+
+  //fprintf(stderr, "%s\n",__FUNCTION__);
+
+  /* if initList is deep */
+  if (ilist->type == INIT_DEEP)
+    ilist = ilist->init.deep;
+
+  if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
+    werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
+  }
+
+  if (!(val = list2val (ilist))) {
+    // assuming a warning has been thrown
+    val=constVal("0");
+  }
+
+  if (val->type != type) {
+    val = valCastLiteral(type, floatFromVal(val));
+  }
+
+  if(val) 
+    ulval = (unsigned long) floatFromVal (val);
+  else
+    ulval =0;
+
+  switch (getSize (type)) {
+  case 1:
+    pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
+    break;
+
+  case 2:
+    pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
+    pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
+    break;
+
+  case 4:
+    pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
+    pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
+    pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
+    pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
+    break;
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* printIvalChar - generates initital value for character array    */
+/*-----------------------------------------------------------------*/
+static int 
+printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
+{
+  value *val;
+  int remain;
+
+  if(!pb)
+    return 0;
+
+  fprintf(stderr, "%s\n",__FUNCTION__);
+  if (!s)
+    {
+
+      val = list2val (ilist);
+      /* if the value is a character string  */
+      if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
+       {
+         if (!DCL_ELEM (type))
+           DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
+
+         //printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
+         //fprintf(stderr, "%s omitting call to printChar\n",__FUNCTION__);
+         pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";omitting call to printChar"));
+
+         if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
+           while (remain--)
+             //tfprintf (oFile, "\t!db !constbyte\n", 0);
+             pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(0)));
+         return 1;
+       }
+      else
+       return 0;
+    }
+  else {
+    //printChar (oFile, s, strlen (s) + 1);
+
+    for(remain=0; remain<strlen(s); remain++) {
+      pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(s[remain])));
+      //fprintf(stderr,"0x%02x ",s[remain]);
+    }
+    //fprintf(stderr,"\n");
+  }
+  return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* printIvalArray - generates code for array initialization        */
+/*-----------------------------------------------------------------*/
+static void 
+printIvalArray (symbol * sym, sym_link * type, initList * ilist,
+               pBlock *pb)
+{
+  initList *iloop;
+  int lcnt = 0, size = 0;
+
+  if(!pb)
+    return;
+
+  /* take care of the special   case  */
+  /* array of characters can be init  */
+  /* by a string                      */
+  if (IS_CHAR (type->next)) {
+    //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
+    if (!IS_LITERAL(list2val(ilist)->etype)) {
+      werror (W_INIT_WRONG);
+      return;
+    }
+    if (printIvalChar (type,
+                      (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
+                      pb, SPEC_CVAL (sym->etype).v_char))
+      return;
+  }
+  /* not the special case             */
+  if (ilist->type != INIT_DEEP)
+    {
+      werror (E_INIT_STRUCT, sym->name);
+      return;
+    }
+
+  iloop = ilist->init.deep;
+  lcnt = DCL_ELEM (type);
+
+  for (;;)
+    {
+      //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
+      size++;
+      printIval (sym, type->next, iloop, pb);
+      iloop = (iloop ? iloop->next : NULL);
+
+
+      /* if not array limits given & we */
+      /* are out of initialisers then   */
+      if (!DCL_ELEM (type) && !iloop)
+       break;
+
+      /* no of elements given and we    */
+      /* have generated for all of them */
+      if (!--lcnt) {
+       /* if initializers left */
+       if (iloop) {
+         werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
+       }
+       break;
+      }
+    }
+
+  /* if we have not been given a size  */
+  if (!DCL_ELEM (type))
+    DCL_ELEM (type) = size;
+
+  return;
+}
+
+/*-----------------------------------------------------------------*/
+/* printIval - generates code for initial value                    */
+/*-----------------------------------------------------------------*/
+static void 
+printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
+{
+  if (!ilist || !pb)
+    return;
+
+  /* if structure then    */
+  if (IS_STRUCT (type))
+    {
+      //fprintf(stderr,"%s struct\n",__FUNCTION__);
+      //printIvalStruct (sym, type, ilist, oFile);
+      return;
+    }
+
+  /* if this is a pointer */
+  if (IS_PTR (type))
+    {
+      //fprintf(stderr,"%s pointer\n",__FUNCTION__);
+      //printIvalPtr (sym, type, ilist, oFile);
+      return;
+    }
+
+  /* if this is an array   */
+  if (IS_ARRAY (type))
+    {
+      //fprintf(stderr,"%s array\n",__FUNCTION__);
+      printIvalArray (sym, type, ilist, pb);
+      return;
+    }
+
+  /* if type is SPECIFIER */
+  if (IS_SPEC (type))
+    {
+      //fprintf(stderr,"%s spec\n",__FUNCTION__);
+      printIvalType (sym, type, ilist, pb);
+      return;
+    }
+}
+
+extern void pic16_pCodeConstString(char *name, char *value);
+/*-----------------------------------------------------------------*/
+/* emitStaticSeg - emitcode for the static segment                 */
+/*-----------------------------------------------------------------*/
+static void
+pic16emitStaticSeg (memmap * map)
+{
+  symbol *sym;
+
+  fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
+
+  //fprintf(stderr, "%s\n",__FUNCTION__);
+
+  /* for all variables in this segment do */
+  for (sym = setFirstItem (map->syms); sym;
+       sym = setNextItem (map->syms))
+    {
+      /* if it is "extern" then do nothing */
+      if (IS_EXTERN (sym->etype))
+       continue;
+
+      /* if it is not static add it to the public
+         table */
+      if (!IS_STATIC (sym->etype))
+       addSetHead (&publics, sym);
+
+      /* print extra debug info if required */
+      if (options.debug || sym->level == 0)
+       {
+         /* NOTE to me - cdbFile may be null in which case,
+          * the sym name will be printed to stdout. oh well */
+         if(cdbFile)
+           cdbSymbol (sym, cdbFile, FALSE, FALSE);
+
+         if (!sym->level)
+           {                   /* global */
+             if (IS_STATIC (sym->etype))
+               fprintf (code->oFile, "F%s_", moduleName);      /* scope is file */
+             else
+               fprintf (code->oFile, "G_");    /* scope is global */
+           }
+         else
+           /* symbol is local */
+           fprintf (code->oFile, "L%s_",
+                    (sym->localof ? sym->localof->name : "-null-"));
+         fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
+
+       }
+
+      /* if it has an absolute address */
+      if (SPEC_ABSA (sym->etype))
+       {
+         if (options.debug || sym->level == 0)
+           fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
+
+         fprintf (code->oFile, "%s\t=\t0x%04x\n",
+                  sym->rname,
+                  SPEC_ADDR (sym->etype));
+       }
+      else
+       {
+         if (options.debug || sym->level == 0)
+           fprintf (code->oFile, " == .\n");
+
+         /* if it has an initial value */
+         if (sym->ival)
+           {
+             pBlock *pb;
+
+             fprintf (code->oFile, "%s:\n", sym->rname);
+             noAlloc++;
+             resolveIvalSym (sym->ival);
+             //printIval (sym, sym->type, sym->ival, code->oFile);
+             pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
+             pic16_addpBlock(pb);
+             pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
+
+             printIval (sym, sym->type, sym->ival, pb);
+             noAlloc--;
+           }
+         else
+           {
+
+             /* allocate space */
+             fprintf (code->oFile, "%s:\n", sym->rname);
+             /* special case for character strings */
+             if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
+                 SPEC_CVAL (sym->etype).v_char)
+               pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
+               /*printChar (code->oFile,
+                          SPEC_CVAL (sym->etype).v_char,
+                          strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
+             else
+               fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
+           }
+       }
+    }
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/* emitMaps - emits the code for the data portion the code         */
+/*-----------------------------------------------------------------*/
+static void
+pic16emitMaps ()
+{
+  /* no special considerations for the following
+     data, idata & bit & xdata */
+  pic16emitRegularMap (data, TRUE, TRUE);
+  pic16emitRegularMap (idata, TRUE, TRUE);
+  pic16emitRegularMap (bit, TRUE, FALSE);
+  pic16emitRegularMap (xdata, TRUE, TRUE);
+  pic16emitRegularMap (sfr, FALSE, FALSE);
+  pic16emitRegularMap (sfrbit, FALSE, FALSE);
+  pic16emitRegularMap (code, TRUE, FALSE);
+  pic16emitStaticSeg (statsg);
+}
+
+/*-----------------------------------------------------------------*/
+/* createInterruptVect - creates the interrupt vector              */
+/*-----------------------------------------------------------------*/
+static void
+pic16createInterruptVect (FILE * vFile)
+{
+  unsigned i = 0;
+  mainf = newSymbol ("main", 0);
+  mainf->block = 0;
+
+  /* only if the main function exists */
+  if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
+    {
+      if (!options.cc_only)
+       werror (E_NO_MAIN);
+      return;
+    }
+
+  /* if the main is only a prototype ie. no body then do nothing */
+  if (!IFFUNC_HASBODY(mainf->type))
+    {
+      /* if ! compile only then main function should be present */
+      if (!options.cc_only)
+       werror (E_NO_MAIN);
+      return;
+    }
+
+  fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
+  fprintf (vFile, ";__interrupt_vect:\n");
+
+
+  if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
+    {
+      /* "generic" interrupt table header (if port doesn't specify one).
+
+       * Look suspiciously like 8051 code to me...
+       */
+
+      fprintf (vFile, ";\tljmp\t__sdcc_gsinit_startup\n");
+
+
+      /* now for the other interrupts */
+      for (; i < maxInterrupts; i++)
+       {
+         if (interrupts[i])
+           fprintf (vFile, ";\tljmp\t%s\n;\t.ds\t5\n", interrupts[i]->rname);
+         else
+           fprintf (vFile, ";\treti\n;\t.ds\t7\n");
+       }
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* initialComments - puts in some initial comments                 */
+/*-----------------------------------------------------------------*/
+static void
+pic16initialComments (FILE * afile)
+{
+  initialComments (afile);
+  fprintf (afile, "; PIC port for the 16-bit core\n");
+  fprintf (afile, iComments2);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* printPublics - generates .global for publics                    */
+/*-----------------------------------------------------------------*/
+static void
+pic16printPublics (FILE * afile)
+{
+  symbol *sym;
+
+  fprintf (afile, "%s", iComments2);
+  fprintf (afile, "; publics variables in this module\n");
+  fprintf (afile, "%s", iComments2);
+
+  for (sym = setFirstItem (publics); sym;
+       sym = setNextItem (publics))
+    fprintf (afile, ";\t.globl %s\n", sym->rname);
+}
+
+
+
+/*-----------------------------------------------------------------*/
+/* emitOverlay - will emit code for the overlay stuff              */
+/*-----------------------------------------------------------------*/
+static void
+pic16emitOverlay (FILE * afile)
+{
+  set *ovrset;
+
+  if (!elementsInSet (ovrSetSets))
+    fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
+
+  /* for each of the sets in the overlay segment do */
+  for (ovrset = setFirstItem (ovrSetSets); ovrset;
+       ovrset = setNextItem (ovrSetSets))
+    {
+
+      symbol *sym;
+
+      if (elementsInSet (ovrset))
+       {
+         /* this dummy area is used to fool the assembler
+            otherwise the assembler will append each of these
+            declarations into one chunk and will not overlay
+            sad but true */
+         fprintf (afile, ";\t.area _DUMMY\n");
+         /* output the area informtion */
+         fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);    /* MOF */
+       }
+
+      for (sym = setFirstItem (ovrset); sym;
+          sym = setNextItem (ovrset))
+       {
+
+         /* if extern then do nothing */
+         if (IS_EXTERN (sym->etype))
+           continue;
+
+         /* if allocation required check is needed
+            then check if the symbol really requires
+            allocation only for local variables */
+         if (!IS_AGGREGATE (sym->type) &&
+             !(sym->_isparm && !IS_REGPARM (sym->etype))
+             && !sym->allocreq && sym->level)
+           continue;
+
+         /* if global variable & not static or extern
+            and addPublics allowed then add it to the public set */
+         if ((sym->_isparm && !IS_REGPARM (sym->etype))
+             && !IS_STATIC (sym->etype))
+           addSetHead (&publics, sym);
+
+         /* if extern then do nothing or is a function
+            then do nothing */
+         if (IS_FUNC (sym->type))
+           continue;
+
+         /* print extra debug info if required */
+         if (options.debug || sym->level == 0)
+           {
+
+             cdbSymbol (sym, cdbFile, FALSE, FALSE);
+
+             if (!sym->level)
+               {               /* global */
+                 if (IS_STATIC (sym->etype))
+                   fprintf (afile, "F%s_", moduleName);        /* scope is file */
+                 else
+                   fprintf (afile, "G_");      /* scope is global */
+               }
+             else
+               /* symbol is local */
+               fprintf (afile, "L%s_",
+                        (sym->localof ? sym->localof->name : "-null-"));
+             fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
+           }
+
+         /* if is has an absolute address then generate
+            an equate for this no need to allocate space */
+         if (SPEC_ABSA (sym->etype))
+           {
+
+             if (options.debug || sym->level == 0)
+               fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
+
+             fprintf (afile, "%s\t=\t0x%04x\n",
+                      sym->rname,
+                      SPEC_ADDR (sym->etype));
+           }
+         else
+           {
+             if (options.debug || sym->level == 0)
+               fprintf (afile, "==.\n");
+
+             /* allocate space */
+             fprintf (afile, "%s:\n", sym->rname);
+             fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
+           }
+
+       }
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* glue - the final glue that hold the whole thing together        */
+/*-----------------------------------------------------------------*/
+void
+pic16glue ()
+{
+
+  FILE *vFile;
+  FILE *asmFile;
+  FILE *ovrFile = tempfile();
+
+  addSetHead(&tmpfileSet,ovrFile);
+  pic16_pCodeInitRegisters();
+
+  if (mainf && IFFUNC_HASBODY(mainf->type)) {
+
+    pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
+    pic16_addpBlock(pb);
+
+    /* entry point @ start of CSEG */
+    pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
+    /* put in the call to main */
+    pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
+
+    if (options.mainreturn) {
+
+      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
+      pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
+
+    } else {
+
+      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
+      pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
+
+    }
+  }
+
+
+  /* At this point we've got all the code in the form of pCode structures */
+  /* Now it needs to be rearranged into the order it should be placed in the */
+  /* code space */
+
+  pic16_movepBlock2Head('P');              // Last
+  pic16_movepBlock2Head(code->dbName);
+  pic16_movepBlock2Head('X');
+  pic16_movepBlock2Head(statsg->dbName);   // First
+
+
+  /* print the global struct definitions */
+  if (options.debug)
+    cdbStructBlock (0,cdbFile);
+
+  vFile = tempfile();
+  /* PENDING: this isnt the best place but it will do */
+  if (port->general.glue_up_main) {
+    /* create the interrupt vector table */
+    pic16createInterruptVect (vFile);
+  }
+
+  addSetHead(&tmpfileSet,vFile);
+    
+  /* emit code for the all the variables declared */
+  pic16emitMaps ();
+  /* do the overlay segments */
+  pic16emitOverlay(ovrFile);
+
+
+  pic16_AnalyzepCode('*');
+
+  //#ifdef PCODE_DEBUG
+  //pic16_printCallTree(stderr);
+  //#endif
+
+  pic16_InlinepCode();
+
+  pic16_AnalyzepCode('*');
+
+  pic16_pcode_test();
+
+
+  /* now put it all together into the assembler file */
+  /* create the assembler file name */
+    
+  if (!options.c1mode) {
+    sprintf (buffer, srcFileName);
+    strcat (buffer, ".asm");
+  }
+  else {
+    strcpy(buffer, options.out_name);
+  }
+
+  if (!(asmFile = fopen (buffer, "w"))) {
+    werror (E_FILE_OPEN_ERR, buffer);
+    exit (1);
+  }
+    
+  /* initial comments */
+  pic16initialComments (asmFile);
+    
+  /* print module name */
+  fprintf (asmFile, ";\t.module %s\n", moduleName);
+    
+  /* Let the port generate any global directives, etc. */
+  if (port->genAssemblerPreamble)
+    {
+      port->genAssemblerPreamble(asmFile);
+    }
+    
+  /* print the global variables in this module */
+  pic16printPublics (asmFile);
+    
+
+  /* copy the sfr segment */
+  fprintf (asmFile, "%s", iComments2);
+  fprintf (asmFile, "; special function registers\n");
+  fprintf (asmFile, "%s", iComments2);
+  copyFile (asmFile, sfr->oFile);
+    
+
+  /* Put all variables into a cblock */
+  pic16_AnalyzeBanking();
+  pic16_writeUsedRegs(asmFile);
+
+  /* create the overlay segments */
+  fprintf (asmFile, "%s", iComments2);
+  fprintf (asmFile, "; overlayable items in internal ram \n");
+  fprintf (asmFile, "%s", iComments2);    
+  copyFile (asmFile, ovrFile);
+
+  /* create the stack segment MOF */
+  if (mainf && IFFUNC_HASBODY(mainf->type)) {
+    fprintf (asmFile, "%s", iComments2);
+    fprintf (asmFile, "; Stack segment in internal ram \n");
+    fprintf (asmFile, "%s", iComments2);    
+    fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
+            ";__start__stack:\n;\t.ds\t1\n\n");
+  }
+
+  /* create the idata segment */
+  fprintf (asmFile, "%s", iComments2);
+  fprintf (asmFile, "; indirectly addressable internal ram data\n");
+  fprintf (asmFile, "%s", iComments2);
+  copyFile (asmFile, idata->oFile);
+    
+  /* if external stack then reserve space of it */
+  if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
+    fprintf (asmFile, "%s", iComments2);
+    fprintf (asmFile, "; external stack \n");
+    fprintf (asmFile, "%s", iComments2);
+    fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
+    fprintf (asmFile,";\t.ds 256\n");
+  }
+       
+       
+  /* copy xtern ram data */
+  fprintf (asmFile, "%s", iComments2);
+  fprintf (asmFile, "; external ram data\n");
+  fprintf (asmFile, "%s", iComments2);
+  copyFile (asmFile, xdata->oFile);
+    
+
+  /* copy the bit segment */
+  fprintf (asmFile, "%s", iComments2);
+  fprintf (asmFile, "; bit data\n");
+  fprintf (asmFile, "%s", iComments2);
+  copyFile (asmFile, bit->oFile);
+
+
+  fprintf (asmFile, "\tORG 0\n");
+
+  /* copy the interrupt vector table */
+  if (mainf && IFFUNC_HASBODY(mainf->type)) {
+    fprintf (asmFile, "%s", iComments2);
+    fprintf (asmFile, "; interrupt vector \n");
+    fprintf (asmFile, "%s", iComments2);
+    copyFile (asmFile, vFile);
+  }
+    
+  /* copy global & static initialisations */
+  fprintf (asmFile, "%s", iComments2);
+  fprintf (asmFile, "; global & static initialisations\n");
+  fprintf (asmFile, "%s", iComments2);
+    
+  /* Everywhere we generate a reference to the static_name area, 
+   * (which is currently only here), we immediately follow it with a 
+   * definition of the post_static_name area. This guarantees that
+   * the post_static_name area will immediately follow the static_name
+   * area.
+   */
+  fprintf (asmFile, ";\t.area %s\n", port->mem.static_name); /* MOF */
+  fprintf (asmFile, ";\t.area %s\n", port->mem.post_static_name);
+  fprintf (asmFile, ";\t.area %s\n", port->mem.static_name);
+    
+  if (mainf && IFFUNC_HASBODY(mainf->type)) {
+    fprintf (asmFile,"__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(asmFile,";\tmov\tP2,#0x%02x\n",
+             (((unsigned int)options.xdata_loc) >> 8) & 0xff);
+      fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
+             (unsigned int)options.xdata_loc & 0xff);
+    }
+
+  }
+
+  if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
+    {
+      /* This code is generated in the post-static area.
+       * This area is guaranteed to follow the static area
+       * by the ugly shucking and jiving about 20 lines ago.
+       */
+      fprintf(asmFile, ";\t.area %s\n", port->mem.post_static_name);
+      fprintf (asmFile,";\tljmp\t__sdcc_program_startup\n");
+    }
+       
+  /* copy over code */
+  fprintf (asmFile, "%s", iComments2);
+  fprintf (asmFile, "; code\n");
+  fprintf (asmFile, "%s", iComments2);
+  fprintf (asmFile, ";\t.area %s\n", port->mem.code_name);
+
+  //copyFile (stderr, code->oFile);
+
+  pic16_copypCode(asmFile, 'I');
+  pic16_copypCode(asmFile, statsg->dbName);
+  pic16_copypCode(asmFile, 'X');
+  pic16_copypCode(asmFile, 'M');
+  pic16_copypCode(asmFile, code->dbName);
+  pic16_copypCode(asmFile, 'P');
+
+
+  fprintf (asmFile,"\tend\n");
+
+  fclose (asmFile);
+
+  rm_tmpfiles();
+}
diff --git a/src/pic16/glue.h b/src/pic16/glue.h
new file mode 100644 (file)
index 0000000..30e54dd
--- /dev/null
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+
+  SDCCglue.h - glues everything we have done together into one file.                 
+                Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+               
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+#include "SDCCglobl.h"
+#include "SDCCmem.h"
+
+#ifndef SDCCGLUE_H
+#define SDCCGLUE_H 1
+
+void glue ();
+/* drdani Jan 30 2000
+   This is needed in gen.c of z80 port */
+char *aopLiteral (value *, int);
+
+#endif
diff --git a/src/pic16/main.c b/src/pic16/main.c
new file mode 100644 (file)
index 0000000..8b3f3ae
--- /dev/null
@@ -0,0 +1,450 @@
+/** @file main.c
+    pic16 specific general functions.
+
+    Note that mlh prepended _pic16_ on the static functions.  Makes
+    it easier to set a breakpoint using the debugger.
+*/
+#include "common.h"
+#include "main.h"
+#include "ralloc.h"
+#include "device.h"
+#include "SDCCutil.h"
+//#include "gen.h"
+
+
+static char _defaultRules[] =
+{
+#include "peeph.rul"
+};
+
+/* list of key words used by msc51 */
+static char *_pic16_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  pic16_pCodeInitRegisters(void);
+
+void pic16_assignRegisters (eBBlock ** ebbs, int count);
+
+static int regParmFlg = 0;     /* determine if we can register a parameter */
+
+static void
+_pic16_init (void)
+{
+  asm_addTree (&asm_asxxxx_mapping);
+  pic16_pCodeInitRegisters();
+}
+
+static void
+_pic16_reset_regparm ()
+{
+  regParmFlg = 0;
+}
+
+static int
+_pic16_regparm (sym_link * l)
+{
+  /* for this processor it is simple
+     can pass only the first parameter in a register */
+  //if (regParmFlg)
+  //  return 0;
+
+  regParmFlg++;// = 1;
+  return 1;
+}
+
+static int
+_process_pragma(const char *sz)
+{
+  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) & 0xf;
+
+       if (strcmp(type, "RAM") == 0) {
+         pic16_addMemRange(&r, 0);
+       } else if (strcmp(type, "SFR") == 0) {
+         pic16_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);
+       pic16_setMaxRAM(maxRAMaddress);
+      }
+       
+      return 0;
+    }
+  return 1;
+}
+
+static bool
+_pic16_parseOptions (int *pargc, char **argv, int *i)
+{
+  /* TODO: allow port-specific command line options to specify
+   * segment names here.
+   */
+  return FALSE;
+}
+
+static void
+_pic16_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;
+    }
+
+  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;
+       }
+    }
+#endif
+}
+
+static void
+_pic16_setDefaultOptions (void)
+{
+}
+
+static const char *
+_pic16_getRegName (struct regs *reg)
+{
+  if (reg)
+    return reg->name;
+  return "err";
+}
+
+extern char *pic16_processor_base_name(void);
+
+static void
+_pic16_genAssemblerPreamble (FILE * of)
+{
+  char * name = pic16_processor_base_name();
+
+  if(!name) {
+
+    name = "p18f452";
+    fprintf(stderr,"WARNING: No Pic has been selected, defaulting to %s\n",name);
+  }
+
+  fprintf (of, "\tlist\tp=%s\n",&name[1]);
+  fprintf (of, "\tinclude \"%s.inc\"\n",name);
+  fprintf (of, "\t__config _CONFIG1H,0x%x\n",pic16_getConfigWord(0x300001));
+  fprintf (of, "\t__config _CONFIG2L,0x%x\n",pic16_getConfigWord(0x300002));
+  fprintf (of, "\t__config _CONFIG2H,0x%x\n",pic16_getConfigWord(0x300003));
+  fprintf (of, "\t__config _CONFIG3H,0x%x\n",pic16_getConfigWord(0x300005));
+  fprintf (of, "\t__config _CONFIG4L,0x%x\n",pic16_getConfigWord(0x300006));
+  fprintf (of, "\t__config _CONFIG5L,0x%x\n",pic16_getConfigWord(0x300008));
+  fprintf (of, "\t__config _CONFIG5H,0x%x\n",pic16_getConfigWord(0x300009));
+  fprintf (of, "\t__config _CONFIG6L,0x%x\n",pic16_getConfigWord(0x30000a));
+  fprintf (of, "\t__config _CONFIG6H,0x%x\n",pic16_getConfigWord(0x30000b));
+  fprintf (of, "\t__config _CONFIG7L,0x%x\n",pic16_getConfigWord(0x30000c));
+  fprintf (of, "\t__config _CONFIG7H,0x%x\n",pic16_getConfigWord(0x30000d));
+  fprintf (of, "\tradix dec\n");
+}
+
+/* Generate interrupt vector table. */
+static int
+_pic16_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
+{
+  int i;
+
+  if (options.model != MODEL_FLAT24)
+    {
+      /* 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++)
+    {
+      if (interrupts[i])
+       {
+         fprintf (of, "\t;ljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
+       }
+      else
+       {
+         fprintf (of, "\t;reti\n\t.ds\t7\n");
+       }
+    }
+
+  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.
+    $2 is always the output file.
+    $3 varies
+    $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
+};
+
+/* Sigh. This really is not good. For now, I recommend:
+ * sdcc -S -mpic16 file.c
+ * the -S option does not compile or link
+ */
+static const char *_asmCmd[] =
+{
+  "gpasm", "-c  -I /usr/local/share/gpasm/header", "$1.asm", NULL
+
+};
+
+/* Globals */
+PORT pic16_port =
+{
+  TARGET_ID_PIC16,
+  "pic16",
+  "MCU PIC16",                 /* Target name */
+  "p18f452",                    /* 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,
+    ".rel"
+  },
+  {
+    _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, // xidata
+    NULL, // xinit
+    NULL,
+    NULL,
+    1        // code is read only
+  },
+  {
+    +1, 1, 4, 1, 1, 0
+  },
+    /* pic16 has an 8 bit mul */
+  {
+    1, -1
+  },
+  "_",
+  _pic16_init,
+  _pic16_parseOptions,
+  NULL,
+  _pic16_finaliseOptions,
+  _pic16_setDefaultOptions,
+  pic16_assignRegisters,
+  _pic16_getRegName,
+  _pic16_keywords,
+  _pic16_genAssemblerPreamble,
+  NULL,                                /* no genAssemblerEnd */
+  _pic16_genIVT,
+  NULL, // _pic16_genXINIT
+  _pic16_reset_regparm,
+  _pic16_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
+};
diff --git a/src/pic16/main.h b/src/pic16/main.h
new file mode 100644 (file)
index 0000000..6555225
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef MAIN_INCLUDE
+#define MAIN_INCLUDE
+
+bool x_parseOptions (char **argv, int *pargc);
+void x_setDefaultOptions (void);
+void x_finaliseOptions (void);
+
+#endif
diff --git a/src/pic16/pcode.c b/src/pic16/pcode.c
new file mode 100644 (file)
index 0000000..12fed71
--- /dev/null
@@ -0,0 +1,6547 @@
+/*-------------------------------------------------------------------------
+
+   pcode.c - post code generation
+   Written By -  Scott Dattalo scott@dattalo.com
+   Ported to PIC16 By -  Martin Dubuc m.dubuc@rogers.com
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-------------------------------------------------------------------------*/
+
+
+#include <stdio.h>
+
+#include "common.h"   // Include everything in the SDCC src directory
+#include "newalloc.h"
+
+
+#include "pcode.h"
+#include "pcodeflow.h"
+#include "ralloc.h"
+#include "device.h"
+
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
+#endif
+
+/****************************************************************/
+/****************************************************************/
+
+static peepCommand peepCommands[] = {
+
+  {NOTBITSKIP, "_NOTBITSKIP_"},
+  {BITSKIP, "_BITSKIP_"},
+  {INVERTBITSKIP, "_INVERTBITSKIP_"},
+
+  {-1, NULL}
+};
+
+
+
+// Eventually this will go into device dependent files:
+pCodeOpReg pic16_pc_status    = {{PO_STATUS,  "_STATUS"}, -1, NULL,0,NULL};
+pCodeOpReg pic16_pc_indf0     = {{PO_INDF0,   "INDF0"}, -1, NULL,0,NULL};
+pCodeOpReg pic16_pc_fsr0      = {{PO_FSR0,    "FSR0"}, -1, NULL,0,NULL};
+pCodeOpReg pic16_pc_intcon    = {{PO_INTCON,  ""}, -1, NULL,0,NULL};
+pCodeOpReg pic16_pc_pcl       = {{PO_PCL,     "PCL"}, -1, NULL,0,NULL};
+pCodeOpReg pic16_pc_pclath    = {{PO_PCLATH,  "_PCLATH"}, -1, NULL,0,NULL};
+pCodeOpReg pic16_pc_wreg      = {{PO_WREG,    "WREG"}, -1, NULL,0,NULL};
+pCodeOpReg pic16_pc_bsr       = {{PO_BSR,     "BSR"}, -1, NULL,0,NULL};
+
+pCodeOpReg pic16_pc_kzero     = {{PO_GPR_REGISTER,  "KZ"}, -1, NULL,0,NULL};
+pCodeOpReg pic16_pc_wsave     = {{PO_GPR_REGISTER,  "WSAVE"}, -1, NULL,0,NULL};
+pCodeOpReg pic16_pc_ssave     = {{PO_GPR_REGISTER,  "SSAVE"}, -1, NULL,0,NULL};
+
+static int mnemonics_initialized = 0;
+
+
+static hTab *pic16MnemonicsHash = NULL;
+static hTab *pic16pCodePeepCommandsHash = NULL;
+
+
+
+static pFile *the_pFile = NULL;
+static pBlock *pb_dead_pcodes = NULL;
+
+/* Hardcoded flags to change the behavior of the PIC port */
+static int peepOptimizing = 1;        /* run the peephole optimizer if nonzero */
+static int functionInlining = 1;      /* inline functions if nonzero */
+int pic16_debug_verbose = 0;                /* Set true to inundate .asm file */
+
+static int GpCodeSequenceNumber = 1;
+static int GpcFlowSeq = 1;
+
+extern void pic16_RemoveUnusedRegisters(void);
+extern void pic16_RegsUnMapLiveRanges(void);
+extern void pic16_BuildFlowTree(pBlock *pb);
+extern void pic16_pCodeRegOptimizeRegUsage(int level);
+extern int pic16_picIsInitialized(void);
+#if !OPT_DISABLE_PIC
+// From pic/pcode.c:
+extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
+extern int mnem2key(char const *mnem);
+#endif // OPT_DISABLE_PIC
+
+/****************************************************************/
+/*                      Forward declarations                    */
+/****************************************************************/
+
+void pic16_unlinkpCode(pCode *pc);
+#if 0
+static void genericAnalyze(pCode *pc);
+static void AnalyzeGOTO(pCode *pc);
+static void AnalyzeSKIP(pCode *pc);
+static void AnalyzeRETURN(pCode *pc);
+#endif
+
+static void genericDestruct(pCode *pc);
+static void genericPrint(FILE *of,pCode *pc);
+
+static void pCodePrintLabel(FILE *of, pCode *pc);
+static void pCodePrintFunction(FILE *of, pCode *pc);
+static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
+static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
+char *pic16_get_op( pCodeOp *pcop,char *buff,int buf_size);
+int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
+int pic16_pCodePeepMatchRule(pCode *pc);
+static void pBlockStats(FILE *of, pBlock *pb);
+static pBlock *newpBlock(void);
+extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
+extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
+pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
+void pic16_pCodeRegMapLiveRanges(pBlock *pb);
+
+
+/****************************************************************/
+/*                    PIC Instructions                          */
+/****************************************************************/
+
+pCodeInstruction pic16_pciADDWF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_ADDWF,
+  "ADDWF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER),   // inCond
+  (PCC_REGISTER | PCC_Z) // outCond
+};
+
+pCodeInstruction pic16_pciADDFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_ADDFW,
+  "ADDWF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER),   // inCond
+  (PCC_W | PCC_Z) // outCond
+};
+
+pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_ADDWFC,
+  "ADDWFC",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER | PCC_C),   // inCond
+  (PCC_REGISTER | PCC_Z) // outCond
+};
+
+pCodeInstruction pic16_pciADDFWC = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_ADDFWC,
+  "ADDWFC",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER | PCC_C),   // inCond
+  (PCC_W | PCC_Z) // outCond
+};
+
+pCodeInstruction pic16_pciADDLW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_ADDLW,
+  "ADDLW",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  1,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_LITERAL),   // inCond
+  (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciANDLW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_ANDLW,
+  "ANDLW",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  1,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_LITERAL),   // inCond
+  (PCC_W | PCC_Z | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciANDWF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_ANDWF,
+  "ANDWF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER),   // inCond
+  (PCC_REGISTER | PCC_Z | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciANDFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_ANDFW,
+  "ANDWF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER),   // inCond
+  (PCC_W | PCC_Z) // outCond
+};
+
+pCodeInstruction pic16_pciBC = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_BC,
+  "BC",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_REL_ADDR | PCC_C),   // inCond
+  PCC_NONE    // outCond
+};
+
+pCodeInstruction pic16_pciBCF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_BCF,
+  "BCF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,1,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_BSF,
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  PCC_REGISTER // outCond
+};
+
+pCodeInstruction pic16_pciBN = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_BN,
+  "BN",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_REL_ADDR | PCC_N),   // inCond
+  PCC_NONE    // outCond
+};
+
+pCodeInstruction pic16_pciBNC = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_BNC,
+  "BNC",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_REL_ADDR | PCC_C),   // inCond
+  PCC_NONE    // outCond
+};
+
+pCodeInstruction pic16_pciBNN = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_BNN,
+  "BNN",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_REL_ADDR | PCC_N),   // inCond
+  PCC_NONE    // outCond
+};
+
+pCodeInstruction pic16_pciBNOV = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_BNOV,
+  "BNOV",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_REL_ADDR | PCC_OV),   // inCond
+  PCC_NONE    // outCond
+};
+
+pCodeInstruction pic16_pciBNZ = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_BNZ,
+  "BNZ",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_REL_ADDR | PCC_Z),   // inCond
+  PCC_NONE    // outCond
+};
+
+pCodeInstruction pic16_pciBOV = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_BOV,
+  "BOV",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_REL_ADDR | PCC_OV),   // inCond
+  PCC_NONE  // outCond
+};
+
+pCodeInstruction pic16_pciBRA = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_BRA,
+  "BRA",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REL_ADDR,   // inCond
+  PCC_NONE    // outCond
+};
+
+pCodeInstruction pic16_pciBSF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_BSF,
+  "BSF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,1,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_BCF,
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
+};
+
+pCodeInstruction pic16_pciBTFSC = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   AnalyzeSKIP,
+   genericDestruct,
+   genericPrint},
+  POC_BTFSC,
+  "BTFSC",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,1,  // dest, bit instruction
+  1,1,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_BTFSS,
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  PCC_EXAMINE_PCOP // outCond
+};
+
+pCodeInstruction pic16_pciBTFSS = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   AnalyzeSKIP,
+   genericDestruct,
+   genericPrint},
+  POC_BTFSS,
+  "BTFSS",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,1,  // dest, bit instruction
+  1,1,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_BTFSC,
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  PCC_EXAMINE_PCOP // outCond
+};
+
+pCodeInstruction pic16_pciBTG = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_BTG,
+  "BTG",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,1,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
+};
+
+pCodeInstruction pic16_pciBZ = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_BZ,
+  "BZ",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_Z,   // inCond
+  PCC_NONE // outCond
+};
+
+pCodeInstruction pic16_pciCALL = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_CALL,
+  "CALL",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  1,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_NONE, // inCond
+  PCC_NONE  // outCond
+};
+
+pCodeInstruction pic16_pciCOMF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_COMF,
+  "COMF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,  // inCond
+  PCC_REGISTER   // outCond
+};
+
+pCodeInstruction pic16_pciCOMFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_COMFW,
+  "COMF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,  // inCond
+  PCC_W   // outCond
+};
+
+pCodeInstruction pic16_pciCLRF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_CLRF,
+  "CLRF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER, // inCond
+  PCC_REGISTER  // outCond
+};
+
+pCodeInstruction pic16_pciCLRWDT = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_CLRWDT,
+  "CLRWDT",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  0,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_NONE, // inCond
+  PCC_NONE  // outCond
+};
+
+pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_CPFSEQ,
+  "CPFSEQ",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  1,1,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER), // inCond
+  PCC_NONE  // outCond
+};
+
+pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_CPFSGT,
+  "CPFSGT",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  1,1,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER), // inCond
+  PCC_NONE  // outCond
+};
+
+pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_CPFSLT,
+  "CPFSLT",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  2,    // num ops
+  1,0,  // dest, bit instruction
+  1,1,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER), // inCond
+  PCC_NONE  // outCond
+};
+
+pCodeInstruction pic16_pciDAW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_DAW,
+  "DAW",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  0,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_W, // inCond
+  (PCC_W | PCC_C) // outCond
+};
+
+pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_DCFSNZ,
+  "DCFSNZ",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  1,1,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER, // inCond
+  PCC_REGISTER  // outCond
+};
+
+pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_DCFSNZW,
+  "DCFSNZ",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  1,1,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER, // inCond
+  PCC_W  // outCond
+};
+
+pCodeInstruction pic16_pciDECF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_DECF,
+  "DECF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  PCC_REGISTER    // outCond
+};
+
+pCodeInstruction pic16_pciDECFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_DECFW,
+  "DECF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  PCC_W    // outCond
+};
+
+pCodeInstruction pic16_pciDECFSZ = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   AnalyzeSKIP,
+   genericDestruct,
+   genericPrint},
+  POC_DECFSZ,
+  "DECFSZ",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  1,1,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  PCC_REGISTER    // outCond
+};
+
+pCodeInstruction pic16_pciDECFSZW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   AnalyzeSKIP,
+   genericDestruct,
+   genericPrint},
+  POC_DECFSZW,
+  "DECFSZ",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  1,1,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  PCC_W           // outCond
+};
+
+pCodeInstruction pic16_pciGOTO = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   AnalyzeGOTO,
+   genericDestruct,
+   genericPrint},
+  POC_GOTO,
+  "GOTO",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REL_ADDR,   // inCond
+  PCC_NONE    // outCond
+};
+
+pCodeInstruction pic16_pciINCF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_INCF,
+  "INCF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciINCFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_INCFW,
+  "INCF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  PCC_W    // outCond
+};
+
+pCodeInstruction pic16_pciINCFSZ = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   AnalyzeSKIP,
+   genericDestruct,
+   genericPrint},
+  POC_INCFSZ,
+  "INCFSZ",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  1,1,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  PCC_REGISTER    // outCond
+};
+
+pCodeInstruction pic16_pciINCFSZW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   AnalyzeSKIP,
+   genericDestruct,
+   genericPrint},
+  POC_INCFSZW,
+  "INCFSZ",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  1,1,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  PCC_W           // outCond
+};
+
+pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   AnalyzeSKIP,
+   genericDestruct,
+   genericPrint},
+  POC_INFSNZ,
+  "INCFSNZ",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  1,1,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  PCC_REGISTER    // outCond
+};
+
+pCodeInstruction pic16_pciIORWF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_IORWF,
+  "IORWF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER),   // inCond
+  (PCC_REGISTER | PCC_Z | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciIORFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_IORFW,
+  "IORWF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER),   // inCond
+  (PCC_W | PCC_Z | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciIORLW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_IORLW,
+  "IORLW",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  1,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_LITERAL),   // inCond
+  (PCC_W | PCC_Z | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciLFSR = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_LFSR,
+  "LFSR",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  1,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_REGISTER | PCC_LITERAL), // mdubuc - Should we use a special syntax for
+                                // f (identifies FSRx)?
+  PCC_REGISTER // outCond
+};
+
+pCodeInstruction pic16_pciMOVF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_MOVF,
+  "MOVF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  (PCC_Z | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciMOVFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_MOVFW,
+  "MOVF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  (PCC_W | PCC_Z) // outCond
+};
+
+pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_MOVFF,
+  "MOVFF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  PCC_REGISTER2 // outCond
+};
+
+pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   genericDestruct,
+   genericPrint},
+  POC_MOVLB,
+  "MOVLB",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  1,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_NONE | PCC_LITERAL),   // inCond
+  PCC_REGISTER // outCond - BSR
+};
+
+pCodeInstruction pic16_pciMOVLW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   genericDestruct,
+   genericPrint},
+  POC_MOVLW,
+  "MOVLW",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  1,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_NONE | PCC_LITERAL),   // inCond
+  PCC_W // outCond
+};
+
+pCodeInstruction pic16_pciMOVWF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_MOVWF,
+  "MOVWF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  PCC_W // outCond
+};
+
+pCodeInstruction pic16_pciMULLW = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   genericDestruct,
+   genericPrint},
+  POC_MULLW,
+  "MULLW",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  1,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_LITERAL),   // inCond
+  PCC_REGISTER // outCond - PROD
+};
+
+pCodeInstruction pic16_pciMULWF = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   genericDestruct,
+   genericPrint},
+  POC_MULWF,
+  "MULWF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER),   // inCond
+  PCC_REGISTER // outCond - PROD
+};
+
+pCodeInstruction pic16_pciNEGF = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   genericDestruct,
+   genericPrint},
+  POC_NEGF,
+  "NEGF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER, // inCond
+  (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciNOP = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   genericDestruct,
+   genericPrint},
+  POC_NOP,
+  "NOP",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  0,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_NONE,   // inCond
+  PCC_NONE // outCond
+};
+
+pCodeInstruction pic16_pciPOP = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   genericDestruct,
+   genericPrint},
+  POC_POP,
+  "POP",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  0,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_NONE,  // inCond
+  PCC_NONE   // outCond
+};
+
+pCodeInstruction pic16_pciPUSH = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   genericDestruct,
+   genericPrint},
+  POC_PUSH,
+  "PUSH",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  0,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_NONE,  // inCond
+  PCC_NONE   // outCond
+};
+
+pCodeInstruction pic16_pciRCALL = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   genericDestruct,
+   genericPrint},
+  POC_RCALL,
+  "RCALL",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REL_ADDR,  // inCond
+  PCC_NONE   // outCond
+};
+
+pCodeInstruction pic16_pciRETFIE = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   AnalyzeRETURN,
+   genericDestruct,
+   genericPrint},
+  POC_RETFIE,
+  "RETFIE",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  1,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_NONE,   // inCond
+  PCC_NONE    // outCond (not true... affects the GIE bit too)
+};
+
+pCodeInstruction pic16_pciRETLW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   AnalyzeRETURN,
+   genericDestruct,
+   genericPrint},
+  POC_RETLW,
+  "RETLW",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  1,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_LITERAL,   // inCond
+  PCC_W // outCond
+};
+
+pCodeInstruction pic16_pciRETURN = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   AnalyzeRETURN,
+   genericDestruct,
+   genericPrint},
+  POC_RETURN,
+  "RETURN",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  1,0,  // branch, skip
+  0,    // literal operand
+  0,    // RAM access bit
+  1,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_NONE,   // inCond
+  PCC_NONE // outCond
+};
+pCodeInstruction pic16_pciRLCF = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_RLCF,
+  "RLCF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_C | PCC_REGISTER),   // inCond
+  (PCC_REGISTER | PCC_C | PCC_Z | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_RLCFW,
+  "RLCF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_C | PCC_REGISTER),   // inCond
+  (PCC_W | PCC_C | PCC_Z | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_RLNCF,
+  "RLNCF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  (PCC_REGISTER | PCC_Z | PCC_N) // outCond
+};
+pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_RLNCFW,
+  "RLNCF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  (PCC_W | PCC_Z | PCC_N) // outCond
+};
+pCodeInstruction pic16_pciRRCF = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_RRCF,
+  "RRCF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_C | PCC_REGISTER),   // inCond
+  (PCC_REGISTER | PCC_C | PCC_Z | PCC_N) // outCond
+};
+pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_RRCFW,
+  "RRCF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_C | PCC_REGISTER),   // inCond
+  (PCC_W | PCC_C | PCC_Z | PCC_N) // outCond
+};
+pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_RRNCF,
+  "RRNCF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  (PCC_REGISTER | PCC_Z | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_RRNCFW,
+  "RRNCF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  (PCC_W | PCC_Z | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciSETF = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_SETF,
+  "SETF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,  // inCond
+  PCC_REGISTER   // outCond
+};
+
+pCodeInstruction pic16_pciSUBLW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_SUBLW,
+  "SUBLW",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  1,    // literal operand
+  0,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_LITERAL),   // inCond
+  (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciSUBFWB = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_SUBFWB,
+  "SUBFWB",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER | PCC_C),   // inCond
+  (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciSUBWF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_SUBWF,
+  "SUBWF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER),   // inCond
+  (PCC_REGISTER | PCC_Z) // outCond
+};
+
+pCodeInstruction pic16_pciSUBFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_SUBFW,
+  "SUBWF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER),   // inCond
+  (PCC_W | PCC_Z | PCC_OV | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_SUBFWB_D1,
+  "SUBFWB",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER | PCC_C),   // inCond
+  (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_SUBFWB_D0,
+  "SUBFWB",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER | PCC_C),   // inCond
+  (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_SUBWFB_D1,
+  "SUBWFB",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER | PCC_C),   // inCond
+  (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_SUBWFB_D0,
+  "SUBWFB",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER | PCC_C),   // inCond
+  (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciSWAPF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_SWAPF,
+  "SWAPF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_REGISTER),   // inCond
+  (PCC_REGISTER) // outCond
+};
+
+pCodeInstruction pic16_pciSWAPFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_SWAPFW,
+  "SWAPF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_REGISTER),   // inCond
+  (PCC_W) // outCond
+};
+
+// mdubuc - Remove TRIS
+
+pCodeInstruction pic16_pciTRIS = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_TRIS,
+  "TRIS",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  POC_NOP,
+  PCC_NONE,   // inCond
+  PCC_REGISTER // outCond
+};
+
+pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_TSTFSZ,
+  "TSTFSZ",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  1,1,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  PCC_REGISTER,   // inCond
+  PCC_NONE // outCond
+};
+
+pCodeInstruction pic16_pciXORWF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_XORWF,
+  "XORWF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  1,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER),   // inCond
+  (PCC_REGISTER | PCC_Z | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciXORFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_XORFW,
+  "XORWF",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  3,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  0,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_REGISTER),   // inCond
+  (PCC_W | PCC_Z | PCC_N) // outCond
+};
+
+pCodeInstruction pic16_pciXORLW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_XORLW,
+  "XORLW",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  1,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  1,    // literal operand
+  1,    // RAM access bit
+  0,    // fast call/return mode select bit
+  POC_NOP,
+  (PCC_W | PCC_LITERAL),   // inCond
+  (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N) // outCond
+};
+
+
+#define MAX_PIC16MNEMONICS 100
+pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
+
+#if OPT_DISABLE_PIC
+/* This definition needs to be part of configure.in */
+// #define USE_VSNPRINTF
+
+#ifdef USE_VSNPRINTF
+  // Alas, vsnprintf is not ANSI standard, and does not exist
+  // on Solaris (and probably other non-Gnu flavored Unixes).
+
+/*-----------------------------------------------------------------*/
+/* SAFE_snprintf - like snprintf except the string pointer is      */
+/*                 after the string has been printed to. This is   */
+/*                 useful for printing to string as though if it   */
+/*                 were a stream.                                  */
+/*-----------------------------------------------------------------*/
+void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
+{
+  va_list val;
+  int len;
+
+  if(!str || !*str)
+    return;
+
+  va_start(val, format);
+
+  vsnprintf(*str, *size, format, val);
+
+  va_end (val);
+
+  len = strlen(*str);
+  if(len > *size) {
+    fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
+    fprintf(stderr,"len = %d is > str size %d\n",len,*size);
+  }
+
+  *str += len;
+  *size -= len;
+
+}
+
+#else  //  USE_VSNPRINTF
+
+// This version is *not* safe, despite the name.
+
+void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
+{
+  va_list val;
+  int len;
+  static char buffer[1024]; /* grossly conservative, but still not inherently safe */
+
+  if(!str || !*str)
+    return;
+
+  va_start(val, format);
+
+  vsprintf(buffer, format, val);
+  va_end (val);
+
+  len = strlen(buffer);
+  if(len > *size) {
+    fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
+    fprintf(stderr,"len = %d is > str size %d\n",len,*size);
+  }
+
+  strcpy(*str, buffer);
+  *str += len;
+  *size -= len;
+
+}
+
+#endif    //  USE_VSNPRINTF
+    
+#endif // OPT_DISABLE_PIC
+
+
+extern  void pic16_initStack(int base_address, int size);
+extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
+extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
+extern void pic16_init_pic(char *);
+
+void  pic16_pCodeInitRegisters(void)
+{
+  static int initialized=0;
+
+  if(initialized)
+    return;
+  initialized = 1;
+
+  pic16_initStack(0xfff, 8);
+  pic16_init_pic(port->processor);
+
+  pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
+  pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
+  pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
+  pic16_pc_fsr0.r = pic16_allocProcessorRegister(IDX_FSR0,"FSR0", PO_FSR0, 0x80);
+  pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
+  pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
+  pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
+
+  pic16_pc_status.rIdx = IDX_STATUS;
+  pic16_pc_fsr0.rIdx = IDX_FSR0;
+  pic16_pc_indf0.rIdx = IDX_INDF0;
+  pic16_pc_intcon.rIdx = IDX_INTCON;
+  pic16_pc_pcl.rIdx = IDX_PCL;
+  pic16_pc_pclath.rIdx = IDX_PCLATH;
+  pic16_pc_wreg.rIdx = IDX_WREG;
+
+  pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
+  pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
+  pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
+
+  pic16_pc_kzero.rIdx = IDX_KZ;
+  pic16_pc_wsave.rIdx = IDX_WSAVE;
+  pic16_pc_ssave.rIdx = IDX_SSAVE;
+
+  /* probably should put this in a separate initialization routine */
+  pb_dead_pcodes = newpBlock();
+
+}
+
+#if OPT_DISABLE_PIC
+/*-----------------------------------------------------------------*/
+/*  mnem2key - convert a pic mnemonic into a hash key              */
+/*   (BTW - this spreads the mnemonics quite well)                 */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
+int mnem2key(char const *mnem)
+{
+  int key = 0;
+
+  if(!mnem)
+    return 0;
+
+  while(*mnem) {
+
+    key += toupper(*mnem++) +1;
+
+  }
+
+  return (key & 0x1f);
+
+}
+#endif // OPT_DISABLE_PIC
+
+void pic16initMnemonics(void)
+{
+  int i = 0;
+  int key;
+  //  char *str;
+  pCodeInstruction *pci;
+
+  if(mnemonics_initialized)
+    return;
+
+  // NULL out the array before making the assignments
+  // since we check the array contents below this initialization.
+
+  for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
+    pic16Mnemonics[i] = NULL;
+  }
+
+  pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
+  pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
+  pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
+  pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
+  pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
+  pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
+  pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
+  pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
+  pic16Mnemonics[POC_BC] = &pic16_pciBC;
+  pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
+  pic16Mnemonics[POC_BN] = &pic16_pciBN;
+  pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
+  pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
+  pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
+  pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
+  pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
+  pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
+  pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
+  pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
+  pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
+  pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
+  pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
+  pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
+  pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
+  pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
+  pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
+  pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
+  pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
+  pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
+  pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
+  pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
+  pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
+  pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
+  pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
+  pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
+  pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
+  pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
+  pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
+  pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
+  pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
+  pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
+  pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
+  pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
+  pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
+  pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
+  pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
+  pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
+  pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
+  pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
+  pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
+  pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
+  pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
+  pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
+  pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
+  pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
+  pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
+  pic16Mnemonics[POC_POP] = &pic16_pciPOP;
+  pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
+  pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
+  pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
+  pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
+  pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
+  pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
+  pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
+  pic16Mnemonics[POC_RLCF] = &pic16_pciRLNCF;
+  pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
+  pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
+  pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
+  pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
+  pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
+  pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
+  pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
+  pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
+  pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
+  pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
+  pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
+  pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
+  pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
+  pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
+  pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
+  pic16Mnemonics[POC_TRIS] = &pic16_pciTRIS;
+  pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
+  pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
+  pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
+  pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
+
+  for(i=0; i<MAX_PIC16MNEMONICS; i++)
+    if(pic16Mnemonics[i])
+      hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
+  pci = hTabFirstItem(pic16MnemonicsHash, &key);
+
+  while(pci) {
+    DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
+    pci = hTabNextItem(pic16MnemonicsHash, &key);
+  }
+
+  mnemonics_initialized = 1;
+}
+
+int pic16_getpCodePeepCommand(char *cmd);
+
+int pic16_getpCode(char *mnem,unsigned dest)
+{
+
+  pCodeInstruction *pci;
+  int key = mnem2key(mnem);
+
+  if(!mnemonics_initialized)
+    pic16initMnemonics();
+
+  pci = hTabFirstItemWK(pic16MnemonicsHash, key);
+
+  while(pci) {
+
+    if(STRCASECMP(pci->mnemonic, mnem) == 0) {
+      if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst) ||
+         (pci->num_ops <= 2 && pci->isAccess) ||
+         (pci->num_ops <= 2 && pci->isFastCall))
+       return(pci->op);
+    }
+
+    pci = hTabNextItemWK (pic16MnemonicsHash);
+  
+  }
+
+  return -1;
+}
+
+/*-----------------------------------------------------------------*
+ * pic16initpCodePeepCommands
+ *
+ *-----------------------------------------------------------------*/
+void pic16initpCodePeepCommands(void)
+{
+
+  int key, i;
+  peepCommand *pcmd;
+
+  i = 0;
+  do {
+    hTabAddItem(&pic16pCodePeepCommandsHash, 
+               mnem2key(peepCommands[i].cmd), &peepCommands[i]);
+    i++;
+  } while (peepCommands[i].cmd);
+
+  pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
+
+  while(pcmd) {
+    //fprintf(stderr, "peep command %s  key %d\n",pcmd->cmd,pcmd->id);
+    pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
+  }
+
+}
+
+/*-----------------------------------------------------------------
+ *
+ *
+ *-----------------------------------------------------------------*/
+
+int pic16_getpCodePeepCommand(char *cmd)
+{
+
+  peepCommand *pcmd;
+  int key = mnem2key(cmd);
+
+
+  pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
+
+  while(pcmd) {
+    // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
+    if(STRCASECMP(pcmd->cmd, cmd) == 0) {
+      return pcmd->id;
+    }
+
+    pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
+  
+  }
+
+  return -1;
+}
+
+static char getpBlock_dbName(pBlock *pb)
+{
+  if(!pb)
+    return 0;
+
+  if(pb->cmemmap)
+    return pb->cmemmap->dbName;
+
+  return pb->dbName;
+}
+void pic16_pBlockConvert2ISR(pBlock *pb)
+{
+  if(!pb)
+    return;
+
+  if(pb->cmemmap)
+    pb->cmemmap = NULL;
+
+  pb->dbName = 'I';
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_movepBlock2Head - given the dbname of a pBlock, move all  */
+/*                   instances to the front of the doubly linked   */
+/*                   list of pBlocks                               */
+/*-----------------------------------------------------------------*/
+
+void pic16_movepBlock2Head(char dbName)
+{
+  pBlock *pb;
+
+  pb = the_pFile->pbHead;
+
+  while(pb) {
+
+    if(getpBlock_dbName(pb) == dbName) {
+      pBlock *pbn = pb->next;
+      pb->next = the_pFile->pbHead;
+      the_pFile->pbHead->prev = pb;
+      the_pFile->pbHead = pb;
+
+      if(pb->prev)
+       pb->prev->next = pbn;
+
+      // If the pBlock that we just moved was the last
+      // one in the link of all of the pBlocks, then we
+      // need to point the tail to the block just before
+      // the one we moved.
+      // Note: if pb->next is NULL, then pb must have 
+      // been the last pBlock in the chain.
+
+      if(pbn)
+       pbn->prev = pb->prev;
+      else
+       the_pFile->pbTail = pb->prev;
+
+      pb = pbn;
+
+    } else
+      pb = pb->next;
+
+  }
+
+}
+
+void pic16_copypCode(FILE *of, char dbName)
+{
+  pBlock *pb;
+
+  if(!of || !the_pFile)
+    return;
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+    if(getpBlock_dbName(pb) == dbName) {
+      pBlockStats(of,pb);
+      pic16_printpBlock(of,pb);
+    }
+  }
+
+}
+void pic16_pcode_test(void)
+{
+
+  DFPRINTF((stderr,"pcode is alive!\n"));
+
+  //initMnemonics();
+
+  if(the_pFile) {
+
+    pBlock *pb;
+    FILE *pFile;
+    char buffer[100];
+
+    /* create the file name */
+    strcpy(buffer,srcFileName);
+    strcat(buffer,".p");
+
+    if( !(pFile = fopen(buffer, "w" ))) {
+      werror(E_FILE_OPEN_ERR,buffer);
+      exit(1);
+    }
+
+    fprintf(pFile,"pcode dump\n\n");
+
+    for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+      fprintf(pFile,"\n\tNew pBlock\n\n");
+      if(pb->cmemmap)
+       fprintf(pFile,"%s",pb->cmemmap->sname);
+      else
+       fprintf(pFile,"internal pblock");
+
+      fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
+      pic16_printpBlock(pFile,pb);
+    }
+  }
+}
+/*-----------------------------------------------------------------*/
+/* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg-  */
+/*      ister, RegCond will return the bit being referenced.       */
+/*                                                                 */
+/* fixme - why not just OR in the pcop bit field                   */
+/*-----------------------------------------------------------------*/
+
+static int RegCond(pCodeOp *pcop)
+{
+
+  if(!pcop)
+    return 0;
+
+  if(pcop->type == PO_GPR_BIT  && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
+    switch(PCORB(pcop)->bit) {
+    case PIC_C_BIT:
+      return PCC_C;
+    case PIC_DC_BIT:
+       return PCC_DC;
+    case PIC_Z_BIT:
+      return PCC_Z;
+    }
+
+  }
+
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_newpCode - create and return a newly initialized pCode          */
+/*                                                                 */
+/*  fixme - rename this                                            */
+/*                                                                 */
+/* The purpose of this routine is to create a new Instruction      */
+/* pCode. This is called by gen.c while the assembly code is being */
+/* generated.                                                      */
+/*                                                                 */
+/* Inouts:                                                         */
+/*  PIC_OPCODE op - the assembly instruction we wish to create.    */
+/*                  (note that the op is analogous to but not the  */
+/*                  same thing as the opcode of the instruction.)  */
+/*  pCdoeOp *pcop - pointer to the operand of the instruction.     */
+/*                                                                 */
+/* Outputs:                                                        */
+/*  a pointer to the new malloc'd pCode is returned.               */
+/*                                                                 */
+/*                                                                 */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
+{
+  pCodeInstruction *pci ;
+
+  if(!mnemonics_initialized)
+    pic16initMnemonics();
+    
+  pci = Safe_calloc(1, sizeof(pCodeInstruction));
+
+  if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
+    memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
+    pci->pcop = pcop;
+
+    if(pci->inCond & PCC_EXAMINE_PCOP)
+      pci->inCond  |= RegCond(pcop);
+
+    if(pci->outCond & PCC_EXAMINE_PCOP)
+      pci->outCond  |= RegCond(pcop);
+
+    pci->pc.prev = pci->pc.next = NULL;
+    return (pCode *)pci;
+  }
+
+  fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
+  exit(1);
+
+  return NULL;
+}      
+
+/*-----------------------------------------------------------------*/
+/* pic16_newpCodeWild - create a "wild" as in wild card pCode            */
+/*                                                                 */
+/* Wild pcodes are used during the peep hole optimizer to serve    */
+/* as place holders for any instruction. When a snippet of code is */
+/* compared to a peep hole rule, the wild card opcode will match   */
+/* any instruction. However, the optional operand and label are    */
+/* additional qualifiers that must also be matched before the      */
+/* line (of assembly code) is declared matched. Note that the      */
+/* operand may be wild too.                                        */
+/*                                                                 */
+/*   Note, a wild instruction is specified just like a wild var:   */
+/*      %4     ; A wild instruction,                               */
+/*  See the peeph.def file for additional examples                 */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
+pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
+{
+
+  pCodeWild *pcw;
+    
+  pcw = Safe_calloc(1,sizeof(pCodeWild));
+
+  pcw->pci.pc.type = PC_WILD;
+  pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
+  pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
+  pcw->pci.pc.pb = NULL;
+
+  //  pcw->pci.pc.analyze = genericAnalyze;
+  pcw->pci.pc.destruct = genericDestruct;
+  pcw->pci.pc.print = genericPrint;
+
+  pcw->id = pCodeID;              // this is the 'n' in %n
+  pcw->operand = optional_operand;
+  pcw->label   = optional_label;
+
+  pcw->mustBeBitSkipInst = 0;
+  pcw->mustNotBeBitSkipInst = 0;
+  pcw->invertBitSkipInst = 0;
+
+  return ( (pCode *)pcw);
+  
+}
+
+ /*-----------------------------------------------------------------*/
+/* newPcodeInlineP - create a new pCode from a char string           */
+/*-----------------------------------------------------------------*/
+
+
+pCode *pic16_newpCodeInlineP(char *cP)
+{
+
+  pCodeComment *pcc ;
+    
+  pcc = Safe_calloc(1,sizeof(pCodeComment));
+
+  pcc->pc.type = PC_INLINE;
+  pcc->pc.prev = pcc->pc.next = NULL;
+  //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
+  pcc->pc.pb = NULL;
+
+  //  pcc->pc.analyze = genericAnalyze;
+  pcc->pc.destruct = genericDestruct;
+  pcc->pc.print = genericPrint;
+
+  if(cP)
+    pcc->comment = Safe_strdup(cP);
+  else
+    pcc->comment = NULL;
+
+  return ( (pCode *)pcc);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* newPcodeCharP - create a new pCode from a char string           */
+/*-----------------------------------------------------------------*/
+
+pCode *pic16_newpCodeCharP(char *cP)
+{
+
+  pCodeComment *pcc ;
+    
+  pcc = Safe_calloc(1,sizeof(pCodeComment));
+
+  pcc->pc.type = PC_COMMENT;
+  pcc->pc.prev = pcc->pc.next = NULL;
+  //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
+  pcc->pc.pb = NULL;
+
+  //  pcc->pc.analyze = genericAnalyze;
+  pcc->pc.destruct = genericDestruct;
+  pcc->pc.print = genericPrint;
+
+  if(cP)
+    pcc->comment = Safe_strdup(cP);
+  else
+    pcc->comment = NULL;
+
+  return ( (pCode *)pcc);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_newpCodeFunction -                                              */
+/*-----------------------------------------------------------------*/
+
+
+pCode *pic16_newpCodeFunction(char *mod,char *f)
+{
+  pCodeFunction *pcf;
+
+  pcf = Safe_calloc(1,sizeof(pCodeFunction));
+  //_ALLOC(pcf,sizeof(pCodeFunction));
+
+  pcf->pc.type = PC_FUNCTION;
+  pcf->pc.prev = pcf->pc.next = NULL;
+  //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
+  pcf->pc.pb = NULL;
+
+  //  pcf->pc.analyze = genericAnalyze;
+  pcf->pc.destruct = genericDestruct;
+  pcf->pc.print = pCodePrintFunction;
+
+  pcf->ncalled = 0;
+
+  if(mod) {
+    //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
+    pcf->modname = Safe_calloc(1,strlen(mod)+1);
+    strcpy(pcf->modname,mod);
+  } else
+    pcf->modname = NULL;
+
+  if(f) {
+    //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
+    pcf->fname = Safe_calloc(1,strlen(f)+1);
+    strcpy(pcf->fname,f);
+  } else
+    pcf->fname = NULL;
+
+  return ( (pCode *)pcf);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_newpCodeFlow                                                    */
+/*-----------------------------------------------------------------*/
+static void destructpCodeFlow(pCode *pc)
+{
+  if(!pc || !isPCFL(pc))
+    return;
+
+/*
+  if(PCFL(pc)->from)
+  if(PCFL(pc)->to)
+*/
+  pic16_unlinkpCode(pc);
+
+  deleteSet(&PCFL(pc)->registers);
+  deleteSet(&PCFL(pc)->from);
+  deleteSet(&PCFL(pc)->to);
+  free(pc);
+
+}
+
+pCode *pic16_newpCodeFlow(void )
+{
+  pCodeFlow *pcflow;
+
+  //_ALLOC(pcflow,sizeof(pCodeFlow));
+  pcflow = Safe_calloc(1,sizeof(pCodeFlow));
+
+  pcflow->pc.type = PC_FLOW;
+  pcflow->pc.prev = pcflow->pc.next = NULL;
+  pcflow->pc.pb = NULL;
+
+  //  pcflow->pc.analyze = genericAnalyze;
+  pcflow->pc.destruct = destructpCodeFlow;
+  pcflow->pc.print = genericPrint;
+
+  pcflow->pc.seq = GpcFlowSeq++;
+
+  pcflow->from = pcflow->to = NULL;
+
+  pcflow->inCond = PCC_NONE;
+  pcflow->outCond = PCC_NONE;
+
+  pcflow->firstBank = -1;
+  pcflow->lastBank = -1;
+
+  pcflow->FromConflicts = 0;
+  pcflow->ToConflicts = 0;
+
+  pcflow->end = NULL;
+
+  pcflow->registers = newSet();
+
+  return ( (pCode *)pcflow);
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
+{
+  pCodeFlowLink *pcflowLink;
+
+  pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
+
+  pcflowLink->pcflow = pcflow;
+  pcflowLink->bank_conflict = 0;
+
+  return pcflowLink;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_newpCodeCSource - create a new pCode Source Symbol              */
+/*-----------------------------------------------------------------*/
+
+pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
+{
+
+  pCodeCSource *pccs;
+    
+  pccs = Safe_calloc(1,sizeof(pCodeCSource));
+
+  pccs->pc.type = PC_CSOURCE;
+  pccs->pc.prev = pccs->pc.next = NULL;
+  pccs->pc.pb = NULL;
+
+  pccs->pc.destruct = genericDestruct;
+  pccs->pc.print = genericPrint;
+
+  pccs->line_number = ln;
+  if(l)
+    pccs->line = Safe_strdup(l);
+  else
+    pccs->line = NULL;
+
+  if(f)
+    pccs->file_name = Safe_strdup(f);
+  else
+    pccs->file_name = NULL;
+
+  return ( (pCode *)pccs);
+
+}
+/*-----------------------------------------------------------------*/
+/* pCodeLabelDestruct - free memory used by a label.               */
+/*-----------------------------------------------------------------*/
+static void pCodeLabelDestruct(pCode *pc)
+{
+
+  if(!pc)
+    return;
+
+  if((pc->type == PC_LABEL) && PCL(pc)->label)
+    free(PCL(pc)->label);
+
+  free(pc);
+
+}
+
+pCode *pic16_newpCodeLabel(char *name, int key)
+{
+
+  char *s = buffer;
+  pCodeLabel *pcl;
+    
+  pcl = Safe_calloc(1,sizeof(pCodeLabel) );
+
+  pcl->pc.type = PC_LABEL;
+  pcl->pc.prev = pcl->pc.next = NULL;
+  //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
+  pcl->pc.pb = NULL;
+
+  //  pcl->pc.analyze = genericAnalyze;
+  pcl->pc.destruct = pCodeLabelDestruct;
+  pcl->pc.print = pCodePrintLabel;
+
+  pcl->key = key;
+
+  pcl->label = NULL;
+  if(key>0) {
+    sprintf(s,"_%05d_DS_",key);
+  } else
+    s = name;
+
+  if(s)
+    pcl->label = Safe_strdup(s);
+
+  //fprintf(stderr,"pic16_newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
+  return ( (pCode *)pcl);
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/* newpBlock - create and return a pointer to a new pBlock         */
+/*-----------------------------------------------------------------*/
+static pBlock *newpBlock(void)
+{
+
+  pBlock *PpB;
+
+  PpB = Safe_calloc(1,sizeof(pBlock) );
+  PpB->next = PpB->prev = NULL;
+
+  PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
+  PpB->tregisters = NULL;
+  PpB->visited = 0;
+  PpB->FlowTree = NULL;
+
+  return PpB;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_newpCodeChain - create a new chain of pCodes                    */
+/*-----------------------------------------------------------------*
+ *
+ *  This function will create a new pBlock and the pointer to the
+ *  pCode that is passed in will be the first pCode in the block.
+ *-----------------------------------------------------------------*/
+
+
+pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
+{
+
+  pBlock *pB  = newpBlock();
+
+  pB->pcHead  = pB->pcTail = pc;
+  pB->cmemmap = cm;
+  pB->dbName  = c;
+
+  return pB;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_newpCodeOpLabel - Create a new label given the key              */
+/*  Note, a negative key means that the label is part of wild card */
+/*  (and hence a wild card label) used in the pCodePeep            */
+/*   optimizations).                                               */
+/*-----------------------------------------------------------------*/
+
+pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
+{
+  char *s=NULL;
+  static int label_key=-1;
+
+  pCodeOp *pcop;
+
+  pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
+  pcop->type = PO_LABEL;
+
+  pcop->name = NULL;
+
+  if(key>0)
+    sprintf(s=buffer,"_%05d_DS_",key);
+  else 
+    s = name, key = label_key--;
+
+  if(s)
+    pcop->name = Safe_strdup(s);
+
+  ((pCodeOpLabel *)pcop)->key = key;
+
+  //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
+  return pcop;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+pCodeOp *pic16_newpCodeOpLit(int lit)
+{
+  char *s = buffer;
+  pCodeOp *pcop;
+
+
+  pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
+  pcop->type = PO_LITERAL;
+
+  pcop->name = NULL;
+  if(lit>=0) {
+    sprintf(s,"0x%02x",lit);
+    if(s)
+      pcop->name = Safe_strdup(s);
+  }
+
+  ((pCodeOpLit *)pcop)->lit = lit;
+
+  return pcop;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
+{
+  pCodeOp *pcop;
+
+  pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
+  pcop->type = PO_IMMEDIATE;
+  if(name) {
+    regs *r = pic16_dirregWithName(name);
+    pcop->name = Safe_strdup(name);
+    PCOI(pcop)->r = r;
+    if(r) {
+      //fprintf(stderr, " pic16_newpCodeOpImmd reg %s exists\n",name);
+      PCOI(pcop)->rIdx = r->rIdx;
+    } else {
+      //fprintf(stderr, " pic16_newpCodeOpImmd reg %s doesn't exist\n",name);
+      PCOI(pcop)->rIdx = -1;
+    }
+    //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
+  } else {
+    pcop->name = NULL;
+  }
+
+  PCOI(pcop)->index = index;
+  PCOI(pcop)->offset = offset;
+  PCOI(pcop)->_const = code_space;
+
+  return pcop;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
+{
+  char *s = buffer;
+  pCodeOp *pcop;
+
+
+  if(!pcwb || !subtype) {
+    fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
+    exit(1);
+  }
+
+  pcop = Safe_calloc(1,sizeof(pCodeOpWild));
+  pcop->type = PO_WILD;
+  sprintf(s,"%%%d",id);
+  pcop->name = Safe_strdup(s);
+
+  PCOW(pcop)->id = id;
+  PCOW(pcop)->pcwb = pcwb;
+  PCOW(pcop)->subtype = subtype;
+  PCOW(pcop)->matched = NULL;
+
+  return pcop;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
+{
+  pCodeOp *pcop;
+
+  pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
+  pcop->type = PO_GPR_BIT;
+  if(s)
+    pcop->name = Safe_strdup(s);   
+  else
+    pcop->name = NULL;
+
+  PCORB(pcop)->bit = bit;
+  PCORB(pcop)->inBitSpace = inBitSpace;
+
+  /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
+  PCOR(pcop)->r = NULL;
+  PCOR(pcop)->rIdx = 0;
+  return pcop;
+}
+
+/*-----------------------------------------------------------------*
+ * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
+ *
+ * If rIdx >=0 then a specific register from the set of registers
+ * will be selected. If rIdx <0, then a new register will be searched
+ * for.
+ *-----------------------------------------------------------------*/
+
+pCodeOp *pic16_newpCodeOpReg(int rIdx)
+{
+  pCodeOp *pcop;
+
+  pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
+
+  pcop->name = NULL;
+
+  if(rIdx >= 0) {
+    PCOR(pcop)->rIdx = rIdx;
+    PCOR(pcop)->r = pic16_regWithIdx(rIdx);
+  } else {
+    PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
+
+    if(PCOR(pcop)->r)
+      PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
+  }
+
+  pcop->type = PCOR(pcop)->r->pc_type;
+
+  return pcop;
+}
+
+pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
+{
+  pCodeOp *pcop;
+
+  pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
+  PCOR(pcop)->r = pic16_allocRegByName(name, 1);
+  PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
+  pcop->type = PCOR(pcop)->r->pc_type;
+  pcop->name = PCOR(pcop)->r->name;
+
+  return pcop;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+
+pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
+{
+  pCodeOp *pcop;
+
+  switch(type) {
+  case PO_BIT:
+  case PO_GPR_BIT:
+    pcop = pic16_newpCodeOpBit(name, -1,0);
+    break;
+
+  case PO_LITERAL:
+    pcop = pic16_newpCodeOpLit(-1);
+    break;
+
+  case PO_LABEL:
+    pcop = pic16_newpCodeOpLabel(NULL,-1);
+    break;
+  case PO_GPR_TEMP:
+    pcop = pic16_newpCodeOpReg(-1);
+    break;
+
+  case PO_GPR_REGISTER:
+    if(name)
+      pcop = pic16_newpCodeOpRegFromStr(name);
+    else
+      pcop = pic16_newpCodeOpReg(-1);
+    break;
+
+  default:
+    pcop = Safe_calloc(1,sizeof(pCodeOp) );
+    pcop->type = type;
+    if(name)
+      pcop->name = Safe_strdup(name);   
+    else
+      pcop->name = NULL;
+  }
+
+  return pcop;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void pic16_pCodeConstString(char *name, char *value)
+{
+  pBlock *pb;
+
+  //  fprintf(stderr, " %s  %s  %s\n",__FUNCTION__,name,value);
+
+  if(!name || !value)
+    return;
+
+  pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
+
+  pic16_addpBlock(pb);
+
+  sprintf(buffer,"; %s = %s",name,value);
+  
+  pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
+  pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
+
+  do {
+    pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(*value)));
+  }while (*value++);
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void pCodeReadCodeTable(void)
+{
+  pBlock *pb;
+
+  fprintf(stderr, " %s\n",__FUNCTION__);
+
+  pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
+
+  pic16_addpBlock(pb);
+
+  pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
+  pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
+  pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
+  pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
+
+  pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
+  pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
+  pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
+  pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_addpCode2pBlock - place the pCode into the pBlock linked list   */
+/*-----------------------------------------------------------------*/
+void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
+{
+
+  if(!pc)
+    return;
+
+  if(!pb->pcHead) {
+    /* If this is the first pcode to be added to a block that
+     * was initialized with a NULL pcode, then go ahead and
+     * make this pcode the head and tail */
+    pb->pcHead  = pb->pcTail = pc;
+  } else {
+    //    if(pb->pcTail)
+    pb->pcTail->next = pc;
+
+    pc->prev = pb->pcTail;
+    pc->pb = pb;
+
+    pb->pcTail = pc;
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_addpBlock - place a pBlock into the pFile                 */
+/*-----------------------------------------------------------------*/
+void pic16_addpBlock(pBlock *pb)
+{
+  // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
+
+  if(!the_pFile) {
+    /* First time called, we'll pass through here. */
+    //_ALLOC(the_pFile,sizeof(pFile));
+    the_pFile = Safe_calloc(1,sizeof(pFile));
+    the_pFile->pbHead = the_pFile->pbTail = pb;
+    the_pFile->functions = NULL;
+    return;
+  }
+
+  the_pFile->pbTail->next = pb;
+  pb->prev = the_pFile->pbTail;
+  pb->next = NULL;
+  the_pFile->pbTail = pb;
+}
+
+/*-----------------------------------------------------------------*/
+/* removepBlock - remove a pBlock from the pFile                   */
+/*-----------------------------------------------------------------*/
+static void removepBlock(pBlock *pb)
+{
+  pBlock *pbs;
+
+  if(!the_pFile)
+    return;
+
+
+  //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
+
+  for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
+    if(pbs == pb) {
+
+      if(pbs == the_pFile->pbHead)
+       the_pFile->pbHead = pbs->next;
+
+      if (pbs == the_pFile->pbTail) 
+       the_pFile->pbTail = pbs->prev;
+
+      if(pbs->next)
+       pbs->next->prev = pbs->prev;
+
+      if(pbs->prev)
+       pbs->prev->next = pbs->next;
+
+      return;
+
+    }
+  }
+
+  fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* printpCode - write the contents of a pCode to a file            */
+/*-----------------------------------------------------------------*/
+static void printpCode(FILE *of, pCode *pc)
+{
+
+  if(!pc || !of)
+    return;
+
+  if(pc->print) {
+    pc->print(of,pc);
+    return;
+  }
+
+  fprintf(of,"warning - unable to print pCode\n");
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_printpBlock - write the contents of a pBlock to a file    */
+/*-----------------------------------------------------------------*/
+void pic16_printpBlock(FILE *of, pBlock *pb)
+{
+  pCode *pc;
+
+  if(!pb)
+    return;
+
+  if(!of)
+    of = stderr;
+
+  for(pc = pb->pcHead; pc; pc = pc->next)
+    printpCode(of,pc);
+
+}
+
+/*-----------------------------------------------------------------*/
+/*                                                                 */
+/*       pCode processing                                          */
+/*                                                                 */
+/*                                                                 */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
+void pic16_unlinkpCode(pCode *pc)
+{
+
+
+  if(pc) {
+#ifdef PCODE_DEBUG
+    fprintf(stderr,"Unlinking: ");
+    printpCode(stderr, pc);
+#endif
+    if(pc->prev) 
+      pc->prev->next = pc->next;
+    if(pc->next)
+      pc->next->prev = pc->prev;
+
+    pc->prev = pc->next = NULL;
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+
+static void genericDestruct(pCode *pc)
+{
+
+  pic16_unlinkpCode(pc);
+
+  if(isPCI(pc)) {
+    /* For instructions, tell the register (if there's one used)
+     * that it's no longer needed */
+    regs *reg = pic16_getRegFromInstruction(pc);
+    if(reg)
+      deleteSetItem (&(reg->reglives.usedpCodes),pc);
+  }
+
+  /* Instead of deleting the memory used by this pCode, mark
+   * the object as bad so that if there's a pointer to this pCode
+   * dangling around somewhere then (hopefully) when the type is
+   * checked we'll catch it.
+   */
+
+  pc->type = PC_BAD;
+
+  pic16_addpCode2pBlock(pb_dead_pcodes, pc);
+
+  //free(pc);
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void pBlockRegs(FILE *of, pBlock *pb)
+{
+
+  regs  *r;
+
+  r = setFirstItem(pb->tregisters);
+  while (r) {
+    r = setNextItem(pb->tregisters);
+  }
+}
+
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+char *pic16_get_op(pCodeOp *pcop,char *buffer, int size)
+{
+  regs *r;
+  static char b[50];
+  char *s;
+  int use_buffer = 1;    // copy the string to the passed buffer pointer
+
+  if(!buffer) {
+    buffer = b;
+    size = sizeof(b);
+    use_buffer = 0;     // Don't bother copying the string to the buffer.
+  } 
+
+  if(pcop) {
+    switch(pcop->type) {
+    case PO_INDF0:
+    case PO_FSR0:
+      if(use_buffer) {
+       SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
+       return buffer;
+      }
+      return PCOR(pcop)->r->name;
+      break;
+    case PO_GPR_TEMP:
+      r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
+
+      if(use_buffer) {
+       SAFE_snprintf(&buffer,&size,"%s",r->name);
+       return buffer;
+      }
+
+      return r->name;
+
+
+    case PO_IMMEDIATE:
+      s = buffer;
+
+      if(PCOI(pcop)->_const) {
+
+       if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
+         SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
+                       pcop->name,
+                       PCOI(pcop)->index,
+                       8 * PCOI(pcop)->offset );
+       } else
+         SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
+      } else {
+      
+       if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
+         SAFE_snprintf(&s,&size,"(%s + %d)",
+                       pcop->name,
+                       PCOI(pcop)->index );
+       } else {
+         if(PCOI(pcop)->offset)
+           SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
+         else
+           SAFE_snprintf(&s,&size,"%s",pcop->name);
+       }
+      }
+
+      return buffer;
+
+    case PO_DIR:
+      s = buffer;
+      //size = sizeof(buffer);
+      if( PCOR(pcop)->instance) {
+       SAFE_snprintf(&s,&size,"(%s + %d)",
+                     pcop->name,
+                     PCOR(pcop)->instance );
+       //fprintf(stderr,"PO_DIR %s\n",buffer);
+      } else
+       SAFE_snprintf(&s,&size,"%s",pcop->name);
+      return buffer;
+
+    default:
+      if  (pcop->name) {
+       if(use_buffer) {
+         SAFE_snprintf(&buffer,&size,"%s",pcop->name);
+         return buffer;
+       }
+       return pcop->name;
+      }
+
+    }
+  }
+
+  return "NO operand";
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
+{
+
+  if(pcc )
+    return pic16_get_op(pcc->pcop,NULL,0);
+  
+  return ("ERROR Null: "__FUNCTION__);
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
+{
+
+  fprintf(of,"pcodeopprint- not implemented\n");
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static char *pCode2str(char *str, int size, pCode *pc)
+{
+  char *s = str;
+
+  switch(pc->type) {
+
+  case PC_OPCODE:
+
+    SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
+
+    if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
+
+      if(PCI(pc)->isBitInst) {
+       if(PCI(pc)->pcop->type == PO_GPR_BIT) {
+         if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
+           SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
+                         PCI(pc)->pcop->name ,
+                         PCI(pc)->pcop->name );
+         else
+           SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)), 
+                         (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
+       } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
+         SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
+       }else
+         SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
+       //PCI(pc)->pcop->t.bit );
+      } else {
+
+       if(PCI(pc)->pcop->type == PO_GPR_BIT) {
+         if( PCI(pc)->num_ops == 3)
+           SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
+         else
+           SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
+
+       }else {
+         SAFE_snprintf(&s,&size,"%s",pic16_get_op_from_instruction(PCI(pc)));
+
+         if( PCI(pc)->num_ops == 3)
+           SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
+       }
+      }
+
+    }
+    break;
+
+  case PC_COMMENT:
+    /* assuming that comment ends with a \n */
+    SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
+    break;
+
+  case PC_INLINE:
+    /* assuming that inline code ends with a \n */
+    SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
+    break;
+
+  case PC_LABEL:
+    SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
+    break;
+  case PC_FUNCTION:
+    SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
+    break;
+  case PC_WILD:
+    SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
+    break;
+  case PC_FLOW:
+    SAFE_snprintf(&s,&size,";\t--FLOW change\n");
+    break;
+  case PC_CSOURCE:
+    SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
+    break;
+
+  case PC_BAD:
+    SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
+  }
+
+  return str;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genericPrint - the contents of a pCode to a file                */
+/*-----------------------------------------------------------------*/
+static void genericPrint(FILE *of, pCode *pc)
+{
+
+  if(!pc || !of)
+    return;
+
+  switch(pc->type) {
+  case PC_COMMENT:
+    fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
+    break;
+
+  case PC_INLINE:
+    fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
+     break;
+
+  case PC_OPCODE:
+    // If the opcode has a label, print that first
+    {
+      pBranch *pbl = PCI(pc)->label;
+      while(pbl && pbl->pc) {
+       if(pbl->pc->type == PC_LABEL)
+         pCodePrintLabel(of, pbl->pc);
+       pbl = pbl->next;
+      }
+    }
+
+    if(PCI(pc)->cline) 
+      genericPrint(of,PCODE(PCI(pc)->cline));
+
+    {
+      char str[256];
+      
+      pCode2str(str, 256, pc);
+
+      fprintf(of,"%s",str);
+
+      /* Debug */
+      if(pic16_debug_verbose) {
+       fprintf(of, "\t;key=%03x",pc->seq);
+       if(PCI(pc)->pcflow)
+         fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
+      }
+    }
+#if 0
+    {
+      pBranch *dpb = pc->to;   // debug
+      while(dpb) {
+       switch ( dpb->pc->type) {
+       case PC_OPCODE:
+         fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
+         break;
+       case PC_LABEL:
+         fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
+         break;
+       case PC_FUNCTION:
+         fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
+         break;
+       case PC_FLOW:
+         fprintf(of, "\t;flow");
+         break;
+       case PC_COMMENT:
+       case PC_WILD:
+         break;
+       }
+       dpb = dpb->next;
+      }
+    }
+#endif
+    fprintf(of,"\n");
+    break;
+
+  case PC_WILD:
+    fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
+    if(PCW(pc)->pci.label)
+      pCodePrintLabel(of, PCW(pc)->pci.label->pc);
+
+    if(PCW(pc)->operand) {
+      fprintf(of,";\toperand  ");
+      pCodeOpPrint(of,PCW(pc)->operand );
+    }
+    break;
+
+  case PC_FLOW:
+    if(pic16_debug_verbose) {
+      fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
+      if(PCFL(pc)->ancestor)
+       fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
+      fprintf(of,"\n");
+
+    }
+    break;
+
+  case PC_CSOURCE:
+    fprintf(of,";#CSRC\t%s %d\n;  %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
+    break;
+  case PC_LABEL:
+  default:
+    fprintf(of,"unknown pCode type %d\n",pc->type);
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* pCodePrintFunction - prints function begin/end                  */
+/*-----------------------------------------------------------------*/
+
+static void pCodePrintFunction(FILE *of, pCode *pc)
+{
+
+  if(!pc || !of)
+    return;
+
+  if( ((pCodeFunction *)pc)->modname) 
+    fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
+
+  if(PCF(pc)->fname) {
+    pBranch *exits = PCF(pc)->to;
+    int i=0;
+    fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
+    while(exits) {
+      i++;
+      exits = exits->next;
+    }
+    //if(i) i--;
+    fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
+    
+  }else {
+    if((PCF(pc)->from && 
+       PCF(pc)->from->pc->type == PC_FUNCTION &&
+       PCF(PCF(pc)->from->pc)->fname) )
+      fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
+    else
+      fprintf(of,"; exit point [can't find entry point]\n");
+  }
+}
+/*-----------------------------------------------------------------*/
+/* pCodePrintLabel - prints label                                  */
+/*-----------------------------------------------------------------*/
+
+static void pCodePrintLabel(FILE *of, pCode *pc)
+{
+
+  if(!pc || !of)
+    return;
+
+  if(PCL(pc)->label) 
+    fprintf(of,"%s\n",PCL(pc)->label);
+  else if (PCL(pc)->key >=0) 
+    fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
+  else
+    fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
+
+}
+/*-----------------------------------------------------------------*/
+/* unlinkpCodeFromBranch - Search for a label in a pBranch and     */
+/*                         remove it if it is found.               */
+/*-----------------------------------------------------------------*/
+static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
+{
+  pBranch *b, *bprev;
+
+
+  bprev = NULL;
+
+  if(pcl->type == PC_OPCODE)
+    b = PCI(pcl)->label;
+  else {
+    fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
+    exit(1);
+
+  }
+
+  //fprintf (stderr, "%s \n",__FUNCTION__);
+  //pcl->print(stderr,pcl);
+  //pc->print(stderr,pc);
+  while(b) {
+    if(b->pc == pc) {
+      //fprintf (stderr, "found label\n");
+
+      /* Found a label */
+      if(bprev) {
+       bprev->next = b->next;  /* Not first pCode in chain */
+       free(b);
+      } else {
+       pc->destruct(pc);
+       PCI(pcl)->label = b->next;   /* First pCode in chain */
+       free(b);
+      }
+      return;  /* A label can't occur more than once */
+    }
+    bprev = b;
+    b = b->next;
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
+{
+  pBranch *b;
+
+  if(!h)
+    return n;
+
+  if(h == n)
+    return n;
+
+  b = h;
+  while(b->next)
+    b = b->next;
+
+  b->next = n;
+
+  return h;
+  
+}  
+/*-----------------------------------------------------------------*/
+/* pBranchLink - given two pcodes, this function will link them    */
+/*               together through their pBranches                  */
+/*-----------------------------------------------------------------*/
+static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
+{
+  pBranch *b;
+
+  // Declare a new branch object for the 'from' pCode.
+
+  //_ALLOC(b,sizeof(pBranch));
+  b = Safe_calloc(1,sizeof(pBranch));
+  b->pc = PCODE(t);             // The link to the 'to' pCode.
+  b->next = NULL;
+
+  f->to = pic16_pBranchAppend(f->to,b);
+
+  // Now do the same for the 'to' pCode.
+
+  //_ALLOC(b,sizeof(pBranch));
+  b = Safe_calloc(1,sizeof(pBranch));
+  b->pc = PCODE(f);
+  b->next = NULL;
+
+  t->from = pic16_pBranchAppend(t->from,b);
+  
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* pBranchFind - find the pBranch in a pBranch chain that contains */
+/*               a pCode                                           */
+/*-----------------------------------------------------------------*/
+static pBranch *pBranchFind(pBranch *pb,pCode *pc)
+{
+  while(pb) {
+
+    if(pb->pc == pc)
+      return pb;
+
+    pb = pb->next;
+  }
+
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
+/*-----------------------------------------------------------------*/
+static void pCodeUnlink(pCode *pc)
+{
+  pBranch *pb1,*pb2;
+  pCode *pc1;
+
+  if(!pc->prev || !pc->next) {
+    fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
+    exit(1);
+  }
+
+  /* first remove the pCode from the chain */
+  pc->prev->next = pc->next;
+  pc->next->prev = pc->prev;
+
+  /* Now for the hard part... */
+
+  /* Remove the branches */
+
+  pb1 = pc->from;
+  while(pb1) {
+    pc1 = pb1->pc;    /* Get the pCode that branches to the
+                      * one we're unlinking */
+
+    /* search for the link back to this pCode (the one we're
+     * unlinking) */
+    if(pb2 = pBranchFind(pc1->to,pc)) {
+      pb2->pc = pc->to->pc;  // make the replacement
+
+      /* if the pCode we're unlinking contains multiple 'to'
+       * branches (e.g. this a skip instruction) then we need
+       * to copy these extra branches to the chain. */
+      if(pc->to->next)
+       pic16_pBranchAppend(pb2, pc->to->next);
+    }
+    
+    pb1 = pb1->next;
+  }
+
+
+}
+#endif
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+#if 0
+static void genericAnalyze(pCode *pc)
+{
+  switch(pc->type) {
+  case PC_WILD:
+  case PC_COMMENT:
+    return;
+  case PC_LABEL:
+  case PC_FUNCTION:
+  case PC_OPCODE:
+    {
+      // Go through the pCodes that are in pCode chain and link
+      // them together through the pBranches. Note, the pCodes
+      // are linked together as a contiguous stream like the 
+      // assembly source code lines. The linking here mimics this
+      // except that comments are not linked in.
+      // 
+      pCode *npc = pc->next;
+      while(npc) {
+       if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
+         pBranchLink(pc,npc);
+         return;
+       } else
+         npc = npc->next;
+      }
+      /* reached the end of the pcode chain without finding
+       * an instruction we could link to. */
+    }
+    break;
+  case PC_FLOW:
+    fprintf(stderr,"analyze PC_FLOW\n");
+
+    return;
+  case PC_BAD:
+    fprintf(stderr,,";A bad pCode is being used\n");
+
+  }
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
+{
+  pBranch *pbr;
+
+  if(pc->type == PC_LABEL) {
+    if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
+      return TRUE;
+  }
+  if(pc->type == PC_OPCODE) {
+    pbr = PCI(pc)->label;
+    while(pbr) {
+      if(pbr->pc->type == PC_LABEL) {
+       if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
+         return TRUE;
+      }
+      pbr = pbr->next;
+    }
+  }
+
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static int checkLabel(pCode *pc)
+{
+  pBranch *pbr;
+
+  if(pc && isPCI(pc)) {
+    pbr = PCI(pc)->label;
+    while(pbr) {
+      if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
+       return TRUE;
+
+      pbr = pbr->next;
+    }
+  }
+
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* findLabelinpBlock - Search the pCode for a particular label     */
+/*-----------------------------------------------------------------*/
+static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
+{
+  pCode  *pc;
+
+  if(!pb)
+    return NULL;
+
+  for(pc = pb->pcHead; pc; pc = pc->next) 
+    if(compareLabel(pc,pcop_label))
+      return pc;
+    
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* findLabel - Search the pCode for a particular label             */
+/*-----------------------------------------------------------------*/
+static pCode * findLabel(pCodeOpLabel *pcop_label)
+{
+  pBlock *pb;
+  pCode  *pc;
+
+  if(!the_pFile)
+    return NULL;
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+    if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
+      return pc;
+  }
+
+  fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_findNextpCode - given a pCode, find the next of type 'pct'      */
+/*                 in the linked list                              */
+/*-----------------------------------------------------------------*/
+pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
+{
+
+  while(pc) {
+    if(pc->type == pct)
+      return pc;
+
+    pc = pc->next;
+  }
+
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* findPrevpCode - given a pCode, find the previous of type 'pct'  */
+/*                 in the linked list                              */
+/*-----------------------------------------------------------------*/
+static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
+{
+
+  while(pc) {
+    if(pc->type == pct)
+      return pc;
+
+    pc = pc->prev;
+  }
+
+  return NULL;
+}
+/*-----------------------------------------------------------------*/
+/* pic16_findNextInstruction - given a pCode, find the next instruction  */
+/*                       in the linked list                        */
+/*-----------------------------------------------------------------*/
+pCode * pic16_findNextInstruction(pCode *pci)
+{
+  pCode *pc = pci;
+
+  while(pc) {
+    if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
+      return pc;
+
+#ifdef PCODE_DEBUG
+    fprintf(stderr,"pic16_findNextInstruction:  ");
+    printpCode(stderr, pc);
+#endif
+    pc = pc->next;
+  }
+
+  //fprintf(stderr,"Couldn't find instruction\n");
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_findNextInstruction - given a pCode, find the next instruction  */
+/*                       in the linked list                        */
+/*-----------------------------------------------------------------*/
+pCode * pic16_findPrevInstruction(pCode *pci)
+{
+  return findPrevpCode(pci, PC_OPCODE);
+}
+
+/*-----------------------------------------------------------------*/
+/* findFunctionEnd - given a pCode find the end of the function    */
+/*                   that contains it                              */
+/*-----------------------------------------------------------------*/
+static pCode * findFunctionEnd(pCode *pc)
+{
+
+  while(pc) {
+    if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
+      return pc;
+
+    pc = pc->next;
+  }
+
+  fprintf(stderr,"Couldn't find function end\n");
+  return NULL;
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* AnalyzeLabel - if the pCode is a label, then merge it with the  */
+/*                instruction with which it is associated.         */
+/*-----------------------------------------------------------------*/
+static void AnalyzeLabel(pCode *pc)
+{
+
+  pCodeUnlink(pc);
+
+}
+#endif
+
+#if 0
+static void AnalyzeGOTO(pCode *pc)
+{
+
+  pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
+
+}
+
+static void AnalyzeSKIP(pCode *pc)
+{
+
+  pBranchLink(pc,pic16_findNextInstruction(pc->next));
+  pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
+
+}
+
+static void AnalyzeRETURN(pCode *pc)
+{
+
+  //  branch_link(pc,findFunctionEnd(pc->next));
+
+}
+
+#endif
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+regs * pic16_getRegFromInstruction(pCode *pc)
+{
+
+  if(!pc                   || 
+     !isPCI(pc)            ||
+     !PCI(pc)->pcop        ||
+     PCI(pc)->num_ops == 0 ||
+     (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
+    return NULL;
+
+  switch(PCI(pc)->pcop->type) {
+  case PO_INDF0:
+  case PO_FSR0:
+    return PCOR(PCI(pc)->pcop)->r;
+
+    //    return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
+
+  case PO_BIT:
+  case PO_GPR_TEMP:
+    //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
+    return PCOR(PCI(pc)->pcop)->r;
+
+  case PO_IMMEDIATE:
+    if(PCOI(PCI(pc)->pcop)->r)
+      return (PCOI(PCI(pc)->pcop)->r);
+
+    //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
+    return pic16_dirregWithName(PCI(pc)->pcop->name);
+    //return NULL; // PCOR(PCI(pc)->pcop)->r;
+
+  case PO_GPR_BIT:
+    return PCOR(PCI(pc)->pcop)->r;
+
+  case PO_DIR:
+    //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
+    return PCOR(PCI(pc)->pcop)->r;
+  case PO_LITERAL:
+    //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
+    break;
+
+  default:
+    //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
+    //genericPrint(stderr, pc);
+    break;
+  }
+
+  return NULL;
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+
+static void AnalyzepBlock(pBlock *pb)
+{
+  pCode *pc;
+
+  if(!pb)
+    return;
+
+  /* Find all of the registers used in this pBlock 
+   * by looking at each instruction and examining it's
+   * operands
+   */
+  for(pc = pb->pcHead; pc; pc = pc->next) {
+
+    /* Is this an instruction with operands? */
+    if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
+
+      if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
+
+       /* Loop through all of the registers declared so far in
+          this block and see if we find this one there */
+
+       regs *r = setFirstItem(pb->tregisters);
+
+       while(r) {
+         if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
+           PCOR(PCI(pc)->pcop)->r = r;
+           break;
+         }
+         r = setNextItem(pb->tregisters);
+       }
+
+       if(!r) {
+         /* register wasn't found */
+         //r = Safe_calloc(1, sizeof(regs));
+         //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
+         //addSet(&pb->tregisters, r);
+         addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
+         //PCOR(PCI(pc)->pcop)->r = r;
+         //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
+       }/* else 
+         fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
+        */
+      }
+      if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
+       if(PCOR(PCI(pc)->pcop)->r) {
+         pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
+         DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
+       } else {
+         if(PCI(pc)->pcop->name)
+           fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
+         else
+           fprintf(stderr,"ERROR: NULL register\n");
+       }
+      }
+    }
+
+
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* */
+/*-----------------------------------------------------------------*/
+#define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
+
+static void InsertpFlow(pCode *pc, pCode **pflow)
+{
+  if(*pflow)
+    PCFL(*pflow)->end = pc;
+
+  if(!pc || !pc->next)
+    return;
+
+  *pflow = pic16_newpCodeFlow();
+  pic16_pCodeInsertAfter(pc, *pflow);
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
+/*                         the flow blocks.                        */
+/*
+ * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
+ * point the instruction flow changes. 
+ */
+/*-----------------------------------------------------------------*/
+void pic16_BuildFlow(pBlock *pb)
+{
+  pCode *pc;
+  pCode *last_pci=NULL;
+  pCode *pflow=NULL;
+  int seq = 0;
+
+  if(!pb)
+    return;
+
+  //fprintf (stderr,"build flow start seq %d  ",GpcFlowSeq);
+  /* Insert a pCodeFlow object at the beginning of a pBlock */
+
+  InsertpFlow(pb->pcHead, &pflow);
+
+  //pflow = pic16_newpCodeFlow();    /* Create a new Flow object */
+  //pflow->next = pb->pcHead;  /* Make the current head the next object */
+  //pb->pcHead->prev = pflow;  /* let the current head point back to the flow object */
+  //pb->pcHead = pflow;        /* Make the Flow object the head */
+  //pflow->pb = pb;
+
+  for( pc = pic16_findNextInstruction(pb->pcHead);
+       pc != NULL;
+       pc=pic16_findNextInstruction(pc)) { 
+
+    pc->seq = seq++;
+    PCI(pc)->pcflow = PCFL(pflow);
+
+    //fprintf(stderr," build: ");
+    //pflow->print(stderr,pflow);
+
+    if( PCI(pc)->isSkip) {
+
+      /* The two instructions immediately following this one 
+       * mark the beginning of a new flow segment */
+
+      while(pc && PCI(pc)->isSkip) {
+
+       PCI(pc)->pcflow = PCFL(pflow);
+       pc->seq = seq-1;
+       seq = 1;
+
+       InsertpFlow(pc, &pflow);
+       pc=pic16_findNextInstruction(pc->next);
+      }
+
+      seq = 0;
+
+      if(!pc)
+       break;
+
+      PCI(pc)->pcflow = PCFL(pflow);
+      pc->seq = 0;
+      InsertpFlow(pc, &pflow);
+
+    } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next)))  {
+
+      InsertpFlow(pc, &pflow);
+      seq = 0;
+
+    } else if (checkLabel(pc)) { 
+
+      /* This instruction marks the beginning of a
+       * new flow segment */
+
+      pc->seq = 0;
+      seq = 1;
+
+      /* If the previous pCode is not a flow object, then 
+       * insert a new flow object. (This check prevents 
+       * two consecutive flow objects from being insert in
+       * the case where a skip instruction preceeds an
+       * instruction containing a label.) */
+
+      if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
+       InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
+
+      PCI(pc)->pcflow = PCFL(pflow);
+      
+    }
+    last_pci = pc;
+    pc = pc->next;
+  }
+
+  //fprintf (stderr,",end seq %d",GpcFlowSeq);
+  if(pflow)
+    PCFL(pflow)->end = pb->pcTail;
+}
+
+/*-------------------------------------------------------------------*/
+/* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
+/*                           the flow blocks.                        */
+/*
+ * unBuildFlow removes pCodeFlow objects from a pCode chain
+ */
+/*-----------------------------------------------------------------*/
+static void unBuildFlow(pBlock *pb)
+{
+  pCode *pc,*pcnext;
+
+  if(!pb)
+    return;
+
+  pc = pb->pcHead;
+
+  while(pc) {
+    pcnext = pc->next;
+
+    if(isPCI(pc)) {
+
+      pc->seq = 0;
+      if(PCI(pc)->pcflow) {
+       //free(PCI(pc)->pcflow);
+       PCI(pc)->pcflow = NULL;
+      }
+
+    } else if(isPCFL(pc) )
+      pc->destruct(pc);
+
+    pc = pcnext;
+  }
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void dumpCond(int cond)
+{
+
+  static char *pcc_str[] = {
+    //"PCC_NONE",
+    "PCC_REGISTER",
+    "PCC_REGISTER2",
+    "PCC_C",
+    "PCC_Z",
+    "PCC_DC",
+    "PCC_OV",
+    "PCC_N",
+    "PCC_W",
+    "PCC_EXAMINE_PCOP",
+    "PCC_LITERAL",
+    "PCC_REL_ADDR"
+  };
+
+  int ncond = sizeof(pcc_str) / sizeof(char *);
+  int i,j;
+
+  fprintf(stderr, "0x%04X\n",cond);
+
+  for(i=0,j=1; i<ncond; i++, j<<=1)
+    if(cond & j)
+      fprintf(stderr, "  %s\n",pcc_str[i]);
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void FlowStats(pCodeFlow *pcflow)
+{
+
+  pCode *pc;
+
+  if(!isPCFL(pcflow))
+    return;
+
+  fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
+
+  pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE); 
+
+  if(!pc) {
+    fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
+    return;
+  }
+
+
+  fprintf(stderr, "  FlowStats inCond: ");
+  dumpCond(pcflow->inCond);
+  fprintf(stderr, "  FlowStats outCond: ");
+  dumpCond(pcflow->outCond);
+
+}
+
+/*-----------------------------------------------------------------*
+ * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
+ *    if it affects the banking bits. 
+ * 
+ * return: -1 == Banking bits are unaffected by this pCode.
+ *
+ * return: > 0 == Banking bits are affected.
+ *
+ *  If the banking bits are affected, then the returned value describes
+ * which bits are affected and how they're affected. The lower half
+ * of the integer maps to the bits that are affected, the upper half
+ * to whether they're set or cleared.
+ *
+ *-----------------------------------------------------------------*/
+
+static int isBankInstruction(pCode *pc)
+{
+  regs *reg;
+  int bank = -1;
+
+  if(!isPCI(pc))
+    return -1;
+
+  if( PCI(pc)->op == POC_MOVLB ||
+      (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
+    bank = PCOL(pc)->lit;
+  }
+
+  return bank;
+}
+
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void FillFlow(pCodeFlow *pcflow)
+{
+
+  pCode *pc;
+  int cur_bank;
+
+  if(!isPCFL(pcflow))
+    return;
+
+  //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
+
+  pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE); 
+
+  if(!pc) {
+    //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
+    return;
+  }
+
+  cur_bank = -1;
+
+  do {
+    isBankInstruction(pc);
+    pc = pc->next;
+  } while (pc && (pc != pcflow->end) && !isPCFL(pc));
+
+/*
+  if(!pc ) {
+    fprintf(stderr, "  FillFlow - Bad end of flow\n");
+  } else {
+    fprintf(stderr, "  FillFlow - Ending flow with\n  ");
+    pc->print(stderr,pc);
+  }
+
+  fprintf(stderr, "  FillFlow inCond: ");
+  dumpCond(pcflow->inCond);
+  fprintf(stderr, "  FillFlow outCond: ");
+  dumpCond(pcflow->outCond);
+*/
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
+{
+  pCodeFlowLink *fromLink, *toLink;
+
+  if(!from || !to || !to->pcflow || !from->pcflow)
+    return;
+
+  fromLink = pic16_newpCodeFlowLink(from->pcflow);
+  toLink   = pic16_newpCodeFlowLink(to->pcflow);
+
+  addSetIfnotP(&(from->pcflow->to), toLink);   //to->pcflow);
+  addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
+
+}
+
+/*-----------------------------------------------------------------*
+ * void LinkFlow(pBlock *pb)
+ *
+ * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
+ * non-branching segments. In LinkFlow, we determine the execution
+ * order of these segments. For example, if one of the segments ends
+ * with a skip, then we know that there are two possible flow segments
+ * to which control may be passed.
+ *-----------------------------------------------------------------*/
+static void LinkFlow(pBlock *pb)
+{
+  pCode *pc=NULL;
+  pCode *pcflow;
+  pCode *pct;
+
+  //fprintf(stderr,"linkflow \n");
+
+  for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
+       pcflow != NULL;
+       pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
+
+    if(!isPCFL(pcflow))
+      fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
+
+    //fprintf(stderr," link: ");
+    //pcflow->print(stderr,pcflow);
+
+    //FillFlow(PCFL(pcflow));
+
+    pc = PCFL(pcflow)->end;
+
+    //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
+    if(isPCI_SKIP(pc)) {
+      //fprintf(stderr, "ends with skip\n");
+      //pc->print(stderr,pc);
+      pct=pic16_findNextInstruction(pc->next);
+      LinkFlow_pCode(PCI(pc),PCI(pct));
+      pct=pic16_findNextInstruction(pct->next);
+      LinkFlow_pCode(PCI(pc),PCI(pct));
+      continue;
+    }
+
+    if(isPCI_BRANCH(pc)) {
+      pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
+
+      //fprintf(stderr, "ends with branch\n  ");
+      //pc->print(stderr,pc);
+
+      if(!(pcol && isPCOLAB(pcol))) {
+       if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
+         pc->print(stderr,pc);
+         fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
+       }
+       continue;
+      }
+
+      if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
+       LinkFlow_pCode(PCI(pc),PCI(pct));
+      else
+       fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
+               __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
+  //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
+
+      continue;
+    }
+
+    if(isPCI(pc)) {
+      //fprintf(stderr, "ends with non-branching instruction:\n");
+      //pc->print(stderr,pc);
+
+      LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
+
+      continue;
+    }
+
+    if(pc) {
+      //fprintf(stderr, "ends with unknown\n");
+      //pc->print(stderr,pc);
+      continue;
+    }
+
+    //fprintf(stderr, "ends with nothing: ERROR\n");
+    
+  }
+}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
+{
+
+  if(!pc || !pcflow)
+    return 0;
+
+  if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
+    return 0;
+
+  if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
+    return 1;
+
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* BanksUsedFlow - Identify which banks are used in flow 2.        */
+/*-----------------------------------------------------------------*/
+static void BanksUsedFlow2(pCode *pcflow)
+{
+  pCode *pc=NULL;
+
+  int bank = -1;
+  bool RegUsed = 0;
+
+  regs *reg;
+
+  if(!isPCFL(pcflow)) {
+    fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
+    return;
+  }
+
+  pc = pic16_findNextInstruction(pcflow->next);
+
+  PCFL(pcflow)->lastBank = -1;
+
+  while(pic16_isPCinFlow(pc,pcflow)) {
+
+    int bank_selected = isBankInstruction(pc);
+
+    //if(PCI(pc)->pcflow) 
+    //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
+
+    if(bank_selected >= 0) {
+      //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
+
+      /* This instruction is modifying banking bits before accessing registers */
+      if(!RegUsed)
+       PCFL(pcflow)->firstBank = -1;
+
+      if(PCFL(pcflow)->lastBank == -1)
+       PCFL(pcflow)->lastBank = 0;
+
+      bank = 1 << bank_selected;
+      PCFL(pcflow)->lastBank |= bank;
+                                
+
+    } else { 
+      reg = pic16_getRegFromInstruction(pc);
+
+      if(reg && !pic16_isREGinBank(reg, bank)) {
+       int allbanks = pic16_REGallBanks(reg);
+       if(bank == -1)
+         PCFL(pcflow)->firstBank = allbanks;
+
+       PCFL(pcflow)->lastBank = allbanks;
+
+       bank = allbanks;
+      }
+      RegUsed = 1;
+    }
+
+    pc = pic16_findNextInstruction(pc->next);
+  }
+
+//  fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
+//       pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
+
+
+
+}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void BanksUsedFlow(pBlock *pb)
+{
+  pCode *pcflow;
+
+
+  //pb->pcHead->print(stderr, pb->pcHead);
+
+  pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
+  //pcflow->print(stderr,pcflow);
+
+  for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
+       pcflow != NULL;
+       pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
+
+    BanksUsedFlow2(pcflow);
+  }
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void insertBankSwitch(int position, pCode *pc, int bsr)
+{
+  pCode *new_pc;
+
+  if(!pc)
+    return;
+
+  new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
+
+  if(position) {
+    /* insert the bank switch after this pc instruction */
+    pCode *pcnext = pic16_findNextInstruction(pc);
+    pic16_pCodeInsertAfter(pc, new_pc);
+    if(pcnext)
+      pc = pcnext;
+
+  } else
+    pic16_pCodeInsertAfter(pc->prev, new_pc);
+
+  /* Move the label, if there is one */
+
+  if(PCI(pc)->label) {
+    PCI(new_pc)->label = PCI(pc)->label;
+    PCI(pc)->label = NULL;
+  }
+
+  /* The new instruction has the same pcflow block */
+  PCI(new_pc)->pcflow = PCI(pc)->pcflow;
+
+}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
+{
+  pCode *pc=NULL;
+  pCode *pcprev=NULL;
+  pCode *new_pc;
+
+  regs *reg;
+
+  if(!pcfl)
+    return;
+
+  pc = pic16_findNextInstruction(pcfl->pc.next);
+
+  while(pic16_isPCinFlow(pc,PCODE(pcfl))) {
+
+    reg = pic16_getRegFromInstruction(pc);
+#if 0
+    if(reg) {
+      fprintf(stderr, "  %s  ",reg->name);
+      fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
+
+    }
+#endif
+
+    if( ( (reg && !isACCESS_BANK(reg) && REG_BANK(reg)!=cur_bank) || 
+         ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
+       (!isPCI_LIT(pc)) ){
+
+      /* Examine the instruction before this one to make sure it is
+       * not a skip type instruction */
+      pcprev = findPrevpCode(pc->prev, PC_OPCODE);
+
+      if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
+       int reg_bank;
+
+       reg_bank =  (reg) ? REG_BANK(reg) : 0;
+
+       
+        if (cur_bank != reg_bank) {
+         //fprintf(stderr, "Cool! can switch banks\n");
+         cur_bank = reg_bank;
+         insertBankSwitch(0, pc, cur_bank);
+       }
+
+      } else {
+       //fprintf(stderr, "Bummer can't switch banks\n");
+       ;
+      }
+    }
+
+    pcprev = pc;
+    pc = pic16_findNextInstruction(pc->next);
+
+  }
+
+  if(pcprev && cur_bank) {
+    /* Brute force - make sure that we point to bank 0 at the
+     * end of each flow block */
+    new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
+    pic16_pCodeInsertAfter(pcprev, new_pc);
+      cur_bank = 0;
+    //fprintf(stderr, "Brute force switch\n");
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/*int compareBankFlow - compare the banking requirements between   */
+/*  flow objects. */
+/*-----------------------------------------------------------------*/
+static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
+{
+
+  if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
+    return 0;
+
+  if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
+    return 0;
+
+  if(pcflow->firstBank == -1)
+    return 0;
+
+
+  if(pcflowLink->pcflow->firstBank == -1) {
+    pCodeFlowLink *pctl = setFirstItem( toORfrom ? 
+                                       pcflowLink->pcflow->to : 
+                                       pcflowLink->pcflow->from);
+    return compareBankFlow(pcflow, pctl, toORfrom);
+  }
+
+  if(toORfrom) {
+    if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
+      return 0;
+
+    pcflowLink->bank_conflict++;
+    pcflowLink->pcflow->FromConflicts++;
+    pcflow->ToConflicts++;
+  } else {
+    
+    if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
+      return 0;
+
+    pcflowLink->bank_conflict++;
+    pcflowLink->pcflow->ToConflicts++;
+    pcflow->FromConflicts++;
+
+  }
+  /*
+  fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
+         pcflowLink->pcflow->pc.seq,
+         pcflowLink->pcflow->FromConflicts,
+         pcflowLink->pcflow->ToConflicts);
+  */
+  return 1;
+
+}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void FixBankFlow(pBlock *pb)
+{
+  pCode *pc=NULL;
+  pCode *pcflow;
+  pCodeFlowLink *pcfl;
+
+  pCode *pcflow_max_To=NULL;
+  pCode *pcflow_max_From=NULL;
+  int max_ToConflicts=0;
+  int max_FromConflicts=0;
+
+  //fprintf(stderr,"Fix Bank flow \n");
+  pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
+
+
+  /*
+    First loop through all of the flow objects in this pcode block
+    and fix the ones that have banking conflicts between the 
+    entry and exit.
+  */
+
+  //fprintf(stderr, "FixBankFlow - Phase 1\n");
+
+  for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
+       pcflow != NULL;
+       pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
+
+    if(!isPCFL(pcflow)) {
+      fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
+      continue;
+    }
+
+    if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank  &&
+       PCFL(pcflow)->firstBank >= 0 &&
+       PCFL(pcflow)->lastBank >= 0 ) {
+
+      int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
+       PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
+
+      FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
+      BanksUsedFlow2(pcflow);
+
+    }
+  }
+
+  //fprintf(stderr, "FixBankFlow - Phase 2\n");
+
+  for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
+       pcflow != NULL;
+       pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
+
+    int nFlows;
+    int nConflicts;
+
+    if(!isPCFL(pcflow)) {
+      fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
+      continue;
+    }
+
+    PCFL(pcflow)->FromConflicts = 0;
+    PCFL(pcflow)->ToConflicts = 0;
+
+    nFlows = 0;
+    nConflicts = 0;
+
+    //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
+    pcfl = setFirstItem(PCFL(pcflow)->from);
+    while (pcfl) {
+
+      pc = PCODE(pcfl->pcflow);
+
+      if(!isPCFL(pc)) {
+       fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
+       pc->print(stderr,pc);
+      }
+
+      nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
+      nFlows++;
+
+      pcfl=setNextItem(PCFL(pcflow)->from);
+    }
+
+    if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
+      //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
+
+      FixRegisterBankingInFlow(PCFL(pcflow),0);
+      BanksUsedFlow2(pcflow);
+
+      continue;  /* Don't need to check the flow from here - it's already been fixed */
+
+    }
+
+    nFlows = 0;
+    nConflicts = 0;
+
+    pcfl = setFirstItem(PCFL(pcflow)->to);
+    while (pcfl) {
+
+      pc = PCODE(pcfl->pcflow);
+      if(!isPCFL(pc)) {
+       fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
+       pc->print(stderr,pc);
+      }
+
+      nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
+      nFlows++;
+
+      pcfl=setNextItem(PCFL(pcflow)->to);
+    }
+
+    if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
+      //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
+
+      FixRegisterBankingInFlow(PCFL(pcflow),0);
+      BanksUsedFlow2(pcflow);
+    }
+  }
+
+  /*
+    Loop through the flow objects again and find the ones with the 
+    maximum conflicts
+  */
+
+  for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
+       pcflow != NULL;
+       pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
+
+    if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
+      pcflow_max_To = pcflow;
+
+    if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
+      pcflow_max_From = pcflow;
+  }
+/*
+  if(pcflow_max_To)
+    fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
+           PCFL(pcflow_max_To)->pc.seq,
+           PCFL(pcflow_max_To)->ToConflicts);
+
+  if(pcflow_max_From)
+    fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
+           PCFL(pcflow_max_From)->pc.seq,
+           PCFL(pcflow_max_From)->FromConflicts);
+*/
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void DumpFlow(pBlock *pb)
+{
+  pCode *pc=NULL;
+  pCode *pcflow;
+  pCodeFlowLink *pcfl;
+
+
+  fprintf(stderr,"Dump flow \n");
+  pb->pcHead->print(stderr, pb->pcHead);
+
+  pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
+  pcflow->print(stderr,pcflow);
+
+  for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
+       pcflow != NULL;
+       pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
+
+    if(!isPCFL(pcflow)) {
+      fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
+      continue;
+    }
+    fprintf(stderr,"dumping: ");
+    pcflow->print(stderr,pcflow);
+    FlowStats(PCFL(pcflow));
+
+    for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
+
+      pc = PCODE(pcfl->pcflow);
+
+      fprintf(stderr, "    from seq %d:\n",pc->seq);
+      if(!isPCFL(pc)) {
+       fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
+       pc->print(stderr,pc);
+      }
+
+    }
+
+    for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
+
+      pc = PCODE(pcfl->pcflow);
+
+      fprintf(stderr, "    to seq %d:\n",pc->seq);
+      if(!isPCFL(pc)) {
+       fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
+       pc->print(stderr,pc);
+      }
+
+    }
+
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static int OptimizepBlock(pBlock *pb)
+{
+  pCode *pc, *pcprev;
+  int matches =0;
+
+  if(!pb || !peepOptimizing)
+    return 0;
+
+  DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
+/*
+  for(pc = pb->pcHead; pc; pc = pc->next)
+    matches += pic16_pCodePeepMatchRule(pc);
+*/
+
+  pc = pic16_findNextInstruction(pb->pcHead);
+  if(!pc)
+    return 0;
+
+  pcprev = pc->prev;
+  do {
+
+
+    if(pic16_pCodePeepMatchRule(pc)) {
+
+      matches++;
+
+      if(pcprev)
+       pc = pic16_findNextInstruction(pcprev->next);
+      else 
+       pc = pic16_findNextInstruction(pb->pcHead);
+    } else
+      pc = pic16_findNextInstruction(pc->next);
+  } while(pc);
+
+  if(matches)
+    DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
+  return matches;
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
+{
+  pCode *pc;
+
+  for(pc = pcs; pc; pc = pc->next) {
+
+    if((pc->type == PC_OPCODE) && 
+       (PCI(pc)->pcop) && 
+       (PCI(pc)->pcop->type == PO_LABEL) &&
+       (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
+      return pc;
+  }
+
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
+{
+
+  char *s=NULL;
+
+  if(isPCI(pc) && 
+     (PCI(pc)->pcop) && 
+     (PCI(pc)->pcop->type == PO_LABEL)) {
+
+    pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
+
+    //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
+    if(pcol->pcop.name)
+      free(pcol->pcop.name);
+
+    /* If the key is negative, then we (probably) have a label to
+     * a function and the name is already defined */
+       
+    if(pcl->key>0)
+      sprintf(s=buffer,"_%05d_DS_",pcl->key);
+    else 
+      s = pcl->label;
+
+    //sprintf(buffer,"_%05d_DS_",pcl->key);
+    if(!s) {
+      fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
+    }
+    pcol->pcop.name = Safe_strdup(s);
+    pcol->key = pcl->key;
+    //pc->print(stderr,pc);
+
+  }
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
+/*                            pCode chain if they're not used.     */
+/*-----------------------------------------------------------------*/
+static void pBlockRemoveUnusedLabels(pBlock *pb)
+{
+  pCode *pc; pCodeLabel *pcl;
+
+  if(!pb)
+    return;
+
+  for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
+
+    pBranch *pbr = PCI(pc)->label;
+    if(pbr && pbr->next) {
+      pCode *pcd = pb->pcHead;
+
+      //fprintf(stderr, "multiple labels\n");
+      //pc->print(stderr,pc);
+
+      pbr = pbr->next;
+      while(pbr) {
+
+       while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
+         //fprintf(stderr,"Used by:\n");
+         //pcd->print(stderr,pcd);
+
+         exchangeLabels(PCL(pbr->pc),pcd);
+
+         pcd = pcd->next;
+       }
+       pbr = pbr->next;
+      }
+    }
+  }
+
+  for(pc = pb->pcHead; pc; pc = pc->next) {
+
+    if(isPCL(pc)) // pc->type == PC_LABEL)
+      pcl = PCL(pc);
+    else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
+      pcl = PCL(PCI(pc)->label->pc);
+    else continue;
+
+    //fprintf(stderr," found  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
+
+    /* This pCode is a label, so search the pBlock to see if anyone
+     * refers to it */
+
+    if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
+    //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
+      /* Couldn't find an instruction that refers to this label
+       * So, unlink the pCode label from it's pCode chain
+       * and destroy the label */
+      //fprintf(stderr," removed  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
+
+      DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
+      if(pc->type == PC_LABEL) {
+       pic16_unlinkpCode(pc);
+       pCodeLabelDestruct(pc);
+      } else {
+       unlinkpCodeFromBranch(pc, PCODE(pcl));
+       /*if(pc->label->next == NULL && pc->label->pc == NULL) {
+         free(pc->label);
+       }*/
+      }
+
+    }
+  }
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/* pic16_pBlockMergeLabels - remove the pCode labels from the pCode      */
+/*                     chain and put them into pBranches that are  */
+/*                     associated with the appropriate pCode       */
+/*                     instructions.                               */
+/*-----------------------------------------------------------------*/
+void pic16_pBlockMergeLabels(pBlock *pb)
+{
+  pBranch *pbr;
+  pCode *pc, *pcnext=NULL;
+
+  if(!pb)
+    return;
+
+  /* First, Try to remove any unused labels */
+  //pBlockRemoveUnusedLabels(pb);
+
+  /* Now loop through the pBlock and merge the labels with the opcodes */
+
+  pc = pb->pcHead;
+  //  for(pc = pb->pcHead; pc; pc = pc->next) {
+
+  while(pc) {
+    pCode *pcn = pc->next;
+
+    if(pc->type == PC_LABEL) {
+
+      //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
+      //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
+      if((pcnext = pic16_findNextInstruction(pc) )) {
+
+       // Unlink the pCode label from it's pCode chain
+       pic16_unlinkpCode(pc);
+       
+       //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
+       // And link it into the instruction's pBranch labels. (Note, since
+       // it's possible to have multiple labels associated with one instruction
+       // we must provide a means to accomodate the additional labels. Thus
+       // the labels are placed into the singly-linked list "label" as 
+       // opposed to being a single member of the pCodeInstruction.)
+
+       //_ALLOC(pbr,sizeof(pBranch));
+       pbr = Safe_calloc(1,sizeof(pBranch));
+       pbr->pc = pc;
+       pbr->next = NULL;
+
+       PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
+
+      } else {
+       fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
+      }
+    } else if(pc->type == PC_CSOURCE) {
+
+      /* merge the source line symbolic info into the next instruction */
+      if((pcnext = pic16_findNextInstruction(pc) )) {
+
+       // Unlink the pCode label from it's pCode chain
+       pic16_unlinkpCode(pc);
+       PCI(pcnext)->cline = PCCS(pc);
+       //fprintf(stderr, "merging CSRC\n");
+       //genericPrint(stderr,pcnext);
+      }
+
+    }
+    pc = pcn;
+  }
+  pBlockRemoveUnusedLabels(pb);
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static int OptimizepCode(char dbName)
+{
+#define MAX_PASSES 4
+
+  int matches = 0;
+  int passes = 0;
+  pBlock *pb;
+
+  if(!the_pFile)
+    return 0;
+
+  DFPRINTF((stderr," Optimizing pCode\n"));
+
+  do {
+    matches = 0;
+    for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+      if('*' == dbName || getpBlock_dbName(pb) == dbName)
+       matches += OptimizepBlock(pb);
+    }
+  }
+  while(matches && ++passes < MAX_PASSES);
+
+  return matches;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_popCopyGPR2Bit - copy a pcode operator                          */
+/*-----------------------------------------------------------------*/
+
+pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
+{
+  pCodeOp *pcop;
+
+  pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
+
+  if( !( (pcop->type == PO_LABEL) ||
+        (pcop->type == PO_LITERAL) ||
+        (pcop->type == PO_STR) ))
+    PCOR(pcop)->r = PCOR(pc)->r;  /* This is dangerous... */
+
+  return pcop;
+}
+
+
+
+#if 0
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+int InstructionRegBank(pCode *pc)
+{
+  regs *reg;
+
+  if( (reg = pic16_getRegFromInstruction(pc)) == NULL)
+    return -1;
+
+  return REG_BANK(reg);
+
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void FixRegisterBanking(pBlock *pb)
+{
+  pCode *pc=NULL;
+  pCode *pcprev=NULL;
+
+  int cur_bank;
+  regs *reg;
+
+  if(!pb)
+    return;
+
+  //pc = pic16_findNextpCode(pb->pcHead, PC_FLOW);
+  pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
+  if(!pc)
+    return;
+  /* loop through all of the flow blocks with in one pblock */
+
+  //fprintf(stderr,"Register banking\n");
+  cur_bank = 0;
+  do {
+    /* at this point, pc should point to a PC_FLOW object */
+
+
+    /* for each flow block, determine the register banking 
+       requirements */
+
+    //    do {
+      if(isPCI(pc)) {
+       //genericPrint(stderr, pc);
+
+       reg = pic16_getRegFromInstruction(pc);
+#if 0
+       if(reg) {
+         fprintf(stderr, "  %s  ",reg->name);
+         fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
+                 reg->address,REG_BANK(reg),reg->isBitField);
+
+       }
+#endif
+
+       if( ( (reg && !isACCESS_BANK(reg) && REG_BANK(reg)!=cur_bank) || 
+             ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
+           (!isPCI_LIT(pc)) ){
+
+
+         /* Examine the instruction before this one to make sure it is
+          * not a skip type instruction */
+         pcprev = findPrevpCode(pc->prev, PC_OPCODE);
+
+         if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
+           int reg_bank;
+
+           reg_bank =  (reg) ? REG_BANK(reg) : 0;
+         
+            if (cur_bank != reg_bank) {
+             cur_bank = reg_bank;
+             insertBankSwitch(0, pc, cur_bank);
+           }
+
+         }else {
+           //fprintf(stderr, "Bummer can't switch banks\n");
+           ;
+         }
+       }
+
+       pcprev = pc;
+
+      }
+
+      pc = pc->next;
+      // } while(pc && !(isPCFL(pc))); 
+
+
+  }while (pc);
+
+  if(pcprev && cur_bank) {
+
+    int pos = 1;  /* Assume that the bank switch instruction(s)
+                  * are inserted after this instruction */
+
+    if((PCI(pcprev)->op == POC_RETLW) || 
+       (PCI(pcprev)->op == POC_RETURN) || 
+       (PCI(pcprev)->op == POC_RETFIE)) {
+
+      /* oops, a RETURN - we need to switch banks *before* the RETURN */
+
+      pos = 0;
+
+    } 
+           
+    /* Brute force - make sure that we point to bank 0 at the
+     * end of each flow block */
+
+    insertBankSwitch(pos, pcprev, 0);
+/*
+    new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
+    pic16_pCodeInsertAfter(pcprev, new_pc);
+*/
+    cur_bank = 0;
+    //fprintf(stderr, "Brute force switch\n");
+  }
+
+}
+
+
+
+
+#if 0
+       if(reg && REG_BANK(reg)!=cur_bank) {
+         //fprintf(stderr,"need to switch banks\n");
+         /* Examine the instruction before this one to make sure it is
+          * not a skip type instruction */
+         pcprev = findPrevpCode(pc->prev, PC_OPCODE);
+         if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
+           int b = cur_bank ^ REG_BANK(reg);
+
+           cur_bank = REG_BANK(reg);
+
+           switch(b & 3) {
+           case 0:
+             break;
+           case 1:
+             insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
+             break;
+           case 2:
+             insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+             insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+             break;
+           case 3:
+             if(cur_bank & 3) {
+               insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
+               insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+             } else
+               insertBankSwitch(0, pc, -1, -1);
+             break;
+
+           }
+#endif
+
+
+
+
+static void pBlockDestruct(pBlock *pb)
+{
+
+  if(!pb)
+    return;
+
+
+  free(pb);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
+/*                                  name dbName and combine them   */
+/*                                  into one block                 */
+/*-----------------------------------------------------------------*/
+static void mergepBlocks(char dbName)
+{
+
+  pBlock *pb, *pbmerged = NULL,*pbn;
+
+  pb = the_pFile->pbHead;
+
+  //fprintf(stderr," merging blocks named %c\n",dbName);
+  while(pb) {
+
+    pbn = pb->next;
+    //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
+    if( getpBlock_dbName(pb) == dbName) {
+
+      //fprintf(stderr," merged block %c\n",dbName);
+
+      if(!pbmerged) {
+       pbmerged = pb;
+      } else {
+       pic16_addpCode2pBlock(pbmerged, pb->pcHead);
+       /* pic16_addpCode2pBlock doesn't handle the tail: */
+       pbmerged->pcTail = pb->pcTail;
+
+       pb->prev->next = pbn;
+       if(pbn) 
+         pbn->prev = pb->prev;
+
+
+       pBlockDestruct(pb);
+      }
+      //pic16_printpBlock(stderr, pbmerged);
+    } 
+    pb = pbn;
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* AnalyzeFlow - Examine the flow of the code and optimize         */
+/*                                                                 */
+/* level 0 == minimal optimization                                 */
+/*   optimize registers that are used only by two instructions     */
+/* level 1 == maximal optimization                                 */
+/*   optimize by looking at pairs of instructions that use the     */
+/*   register.                                                     */
+/*-----------------------------------------------------------------*/
+
+static void AnalyzeFlow(int level)
+{
+  static int times_called=0;
+
+  pBlock *pb;
+
+  if(!the_pFile)
+    return;
+
+
+  /* if this is not the first time this function has been called,
+     then clean up old flow information */
+  if(times_called++) {
+    for(pb = the_pFile->pbHead; pb; pb = pb->next)
+      unBuildFlow(pb);
+
+    pic16_RegsUnMapLiveRanges();
+
+  }
+
+  GpcFlowSeq = 1;
+
+  /* Phase 2 - Flow Analysis - Register Banking
+   *
+   * In this phase, the individual flow blocks are examined
+   * and register banking is fixed.
+   */
+
+  //for(pb = the_pFile->pbHead; pb; pb = pb->next)
+  //FixRegisterBanking(pb);
+
+  /* Phase 2 - Flow Analysis
+   *
+   * In this phase, the pCode is partition into pCodeFlow 
+   * blocks. The flow blocks mark the points where a continuous
+   * stream of instructions changes flow (e.g. because of
+   * a call or goto or whatever).
+   */
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    pic16_BuildFlow(pb);
+
+
+  /* Phase 2 - Flow Analysis - linking flow blocks
+   *
+   * In this phase, the individual flow blocks are examined
+   * to determine their order of excution.
+   */
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    LinkFlow(pb);
+
+  /* Phase 3 - Flow Analysis - Flow Tree
+   *
+   * In this phase, the individual flow blocks are examined
+   * to determine their order of excution.
+   */
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    pic16_BuildFlowTree(pb);
+
+
+  /* Phase x - Flow Analysis - Used Banks
+   *
+   * In this phase, the individual flow blocks are examined
+   * to determine the Register Banks they use
+   */
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    FixBankFlow(pb);
+
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    pic16_pCodeRegMapLiveRanges(pb);
+
+  pic16_RemoveUnusedRegisters();
+
+  //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+  pic16_pCodeRegOptimizeRegUsage(level);
+
+  OptimizepCode('*');
+
+
+/*
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    DumpFlow(pb);
+*/
+  /* debug stuff */ 
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+    pCode *pcflow;
+    for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
+        (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
+        pcflow = pcflow->next) {
+
+      FillFlow(PCFL(pcflow));
+    }
+  }
+
+/*
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+    pCode *pcflow;
+    for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
+        (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
+        pcflow = pcflow->next) {
+
+      FlowStats(PCFL(pcflow));
+    }
+  }
+*/
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_AnalyzeBanking - Called after the memory addresses have been    */
+/*                  assigned to the registers.                     */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
+void pic16_AnalyzeBanking(void)
+{
+  pBlock  *pb;
+
+  if(!pic16_picIsInitialized()) {
+    fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
+    fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
+    fprintf(stderr,"support/scripts/inc2h.pl\n");
+    fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
+
+    exit(1);
+  }
+
+  /* Phase x - Flow Analysis - Used Banks
+   *
+   * In this phase, the individual flow blocks are examined
+   * to determine the Register Banks they use
+   */
+
+  AnalyzeFlow(0);
+  AnalyzeFlow(1);
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    BanksUsedFlow(pb);
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    FixRegisterBanking(pb);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* buildCallTree - Look at the flow and extract all of the calls.  */
+/*-----------------------------------------------------------------*/
+static set *register_usage(pBlock *pb);
+
+static void buildCallTree(void    )
+{
+  pBranch *pbr;
+  pBlock  *pb;
+  pCode   *pc;
+
+  if(!the_pFile)
+    return;
+
+
+
+  /* Now build the call tree.
+     First we examine all of the pCodes for functions.
+     Keep in mind that the function boundaries coincide
+     with pBlock boundaries. 
+
+     The algorithm goes something like this:
+     We have two nested loops. The outer loop iterates
+     through all of the pBlocks/functions. The inner
+     loop iterates through all of the pCodes for
+     a given pBlock. When we begin iterating through
+     a pBlock, the variable pc_fstart, pCode of the start
+     of a function, is cleared. We then search for pCodes
+     of type PC_FUNCTION. When one is encountered, we
+     initialize pc_fstart to this and at the same time
+     associate a new pBranch object that signifies a 
+     branch entry. If a return is found, then this signifies
+     a function exit point. We'll link the pCodes of these
+     returns to the matching pc_fstart.
+
+     When we're done, a doubly linked list of pBranches
+     will exist. The head of this list is stored in
+     `the_pFile', which is the meta structure for all
+     of the pCode. Look at the pic16_printCallTree function
+     on how the pBranches are linked together.
+
+   */
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+    pCode *pc_fstart=NULL;
+    for(pc = pb->pcHead; pc; pc = pc->next) {
+      if(isPCF(pc)) {
+       if (PCF(pc)->fname) {
+
+         if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
+           //fprintf(stderr," found main \n");
+           pb->cmemmap = NULL;  /* FIXME do we need to free ? */
+           pb->dbName = 'M';
+         }
+
+         pbr = Safe_calloc(1,sizeof(pBranch));
+         pbr->pc = pc_fstart = pc;
+         pbr->next = NULL;
+
+         the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
+
+         // Here's a better way of doing the same:
+         addSet(&pb->function_entries, pc);
+
+       } else {
+         // Found an exit point in a function, e.g. return
+         // (Note, there may be more than one return per function)
+         if(pc_fstart)
+           pBranchLink(PCF(pc_fstart), PCF(pc));
+
+         addSet(&pb->function_exits, pc);
+       }
+      } else if(isCALL(pc)) {
+       addSet(&pb->function_calls,pc);
+      }
+    }
+  }
+
+  /* Re-allocate the registers so that there are no collisions
+   * between local variables when one function call another */
+
+  // this is weird...
+  //  pic16_deallocateAllRegs();
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+    if(!pb->visited)
+      register_usage(pb);
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_AnalyzepCode - parse the pCode that has been generated and form */
+/*                all of the logical connections.                  */
+/*                                                                 */
+/* Essentially what's done here is that the pCode flow is          */
+/* determined.                                                     */
+/*-----------------------------------------------------------------*/
+
+void pic16_AnalyzepCode(char dbName)
+{
+  pBlock *pb;
+  int i,changes;
+
+  if(!the_pFile)
+    return;
+
+  mergepBlocks('D');
+
+
+  /* Phase 1 - Register allocation and peep hole optimization
+   *
+   * The first part of the analysis is to determine the registers
+   * that are used in the pCode. Once that is done, the peep rules
+   * are applied to the code. We continue to loop until no more
+   * peep rule optimizations are found (or until we exceed the
+   * MAX_PASSES threshold). 
+   *
+   * When done, the required registers will be determined.
+   *
+   */
+  i = 0;
+  do {
+
+    DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
+    //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
+
+    /* First, merge the labels with the instructions */
+    for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+      if('*' == dbName || getpBlock_dbName(pb) == dbName) {
+
+       DFPRINTF((stderr," analyze and merging block %c\n",dbName));
+       //fprintf(stderr," analyze and merging block %c\n",dbName);
+       pic16_pBlockMergeLabels(pb);
+       AnalyzepBlock(pb);
+      } else {
+       DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
+      }
+    }
+
+    changes = OptimizepCode(dbName);
+
+  } while(changes && (i++ < MAX_PASSES));
+
+  buildCallTree();
+}
+
+/*-----------------------------------------------------------------*/
+/* ispCodeFunction - returns true if *pc is the pCode of a         */
+/*                   function                                      */
+/*-----------------------------------------------------------------*/
+static bool ispCodeFunction(pCode *pc)
+{
+
+  if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
+    return 1;
+
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* findFunction - Search for a function by name (given the name)   */
+/*                in the set of all functions that are in a pBlock */
+/* (note - I expect this to change because I'm planning to limit   */
+/*  pBlock's to just one function declaration                      */
+/*-----------------------------------------------------------------*/
+static pCode *findFunction(char *fname)
+{
+  pBlock *pb;
+  pCode *pc;
+  if(!fname)
+    return NULL;
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+
+    pc = setFirstItem(pb->function_entries);
+    while(pc) {
+    
+      if((pc->type == PC_FUNCTION) &&
+        (PCF(pc)->fname) && 
+        (strcmp(fname, PCF(pc)->fname)==0))
+       return pc;
+
+      pc = setNextItem(pb->function_entries);
+
+    }
+
+  }
+  return NULL;
+}
+
+static void MarkUsedRegisters(set *regset)
+{
+
+  regs *r1,*r2;
+
+  for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
+    r2 = pic16_regWithIdx(r1->rIdx);
+    r2->isFree = 0;
+    r2->wasUsed = 1;
+  }
+}
+
+static void pBlockStats(FILE *of, pBlock *pb)
+{
+
+  pCode *pc;
+  regs  *r;
+
+  fprintf(of,";***\n;  pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
+
+  // for now just print the first element of each set
+  pc = setFirstItem(pb->function_entries);
+  if(pc) {
+    fprintf(of,";entry:  ");
+    pc->print(of,pc);
+  }
+  pc = setFirstItem(pb->function_exits);
+  if(pc) {
+    fprintf(of,";has an exit\n");
+    //pc->print(of,pc);
+  }
+
+  pc = setFirstItem(pb->function_calls);
+  if(pc) {
+    fprintf(of,";functions called:\n");
+
+    while(pc) {
+      if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
+       fprintf(of,";   %s\n",pic16_get_op_from_instruction(PCI(pc)));
+      }
+      pc = setNextItem(pb->function_calls);
+    }
+  }
+
+  r = setFirstItem(pb->tregisters);
+  if(r) {
+    int n = elementsInSet(pb->tregisters);
+
+    fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
+
+    while (r) {
+      fprintf(of,";   %s\n",r->name);
+      r = setNextItem(pb->tregisters);
+    }
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+#if 0
+static void sequencepCode(void)
+{
+  pBlock *pb;
+  pCode *pc;
+
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+
+    pb->seq = GpCodeSequenceNumber+1;
+
+    for( pc = pb->pcHead; pc; pc = pc->next)
+      pc->seq = ++GpCodeSequenceNumber;
+  }
+
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static set *register_usage(pBlock *pb)
+{
+  pCode *pc,*pcn;
+  set *registers=NULL;
+  set *registersInCallPath = NULL;
+
+  /* check recursion */
+
+  pc = setFirstItem(pb->function_entries);
+
+  if(!pc)
+    return registers;
+
+  pb->visited = 1;
+
+  if(pc->type != PC_FUNCTION)
+    fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
+
+  pc = setFirstItem(pb->function_calls);
+  for( ; pc; pc = setNextItem(pb->function_calls)) {
+
+    if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
+      char *dest = pic16_get_op_from_instruction(PCI(pc));
+
+      pcn = findFunction(dest);
+      if(pcn) 
+       registersInCallPath = register_usage(pcn->pb);
+    } else
+      fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
+
+  }
+
+#ifdef PCODE_DEBUG
+  pBlockStats(stderr,pb);  // debug
+#endif
+
+  // Mark the registers in this block as used.
+
+  MarkUsedRegisters(pb->tregisters);
+  if(registersInCallPath) {
+    /* registers were used in the functions this pBlock has called */
+    /* so now, we need to see if these collide with the ones we are */
+    /* using here */
+
+    regs *r1,*r2, *newreg;
+
+    DFPRINTF((stderr,"comparing registers\n"));
+
+    r1 = setFirstItem(registersInCallPath);
+    while(r1) {
+
+      r2 = setFirstItem(pb->tregisters);
+
+      while(r2 && (r1->type != REG_STK)) {
+
+       if(r2->rIdx == r1->rIdx) {
+         newreg = pic16_findFreeReg(REG_GPR);
+
+
+         if(!newreg) {
+           DFPRINTF((stderr,"Bummer, no more registers.\n"));
+           exit(1);
+         }
+
+         DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
+                 r1->rIdx, newreg->rIdx));
+         r2->rIdx = newreg->rIdx;
+         //if(r2->name) free(r2->name);
+         if(newreg->name)
+           r2->name = Safe_strdup(newreg->name);
+         else
+           r2->name = NULL;
+         newreg->isFree = 0;
+         newreg->wasUsed = 1;
+       }
+       r2 = setNextItem(pb->tregisters);
+      }
+
+      r1 = setNextItem(registersInCallPath);
+    }
+
+    /* Collisions have been resolved. Now free the registers in the call path */
+    r1 = setFirstItem(registersInCallPath);
+    while(r1) {
+      if(r1->type != REG_STK) {
+       newreg = pic16_regWithIdx(r1->rIdx);
+       newreg->isFree = 1;
+      }
+      r1 = setNextItem(registersInCallPath);
+    }
+
+  }// else
+  //    MarkUsedRegisters(pb->registers);
+
+  registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
+#ifdef PCODE_DEBUG
+  if(registers) 
+    DFPRINTF((stderr,"returning regs\n"));
+  else
+    DFPRINTF((stderr,"not returning regs\n"));
+
+  DFPRINTF((stderr,"pBlock after register optim.\n"));
+  pBlockStats(stderr,pb);  // debug
+#endif
+
+  return registers;
+}
+
+/*-----------------------------------------------------------------*/
+/* pct2 - writes the call tree to a file                           */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void pct2(FILE *of,pBlock *pb,int indent)
+{
+  pCode *pc,*pcn;
+  int i;
+  //  set *registersInCallPath = NULL;
+
+  if(!of)
+    return;
+
+  if(indent > 10)
+    return; //recursion ?
+
+  pc = setFirstItem(pb->function_entries);
+
+  if(!pc)
+    return;
+
+  pb->visited = 0;
+
+  for(i=0;i<indent;i++)   // Indentation
+    fputc(' ',of);
+
+  if(pc->type == PC_FUNCTION)
+    fprintf(of,"%s\n",PCF(pc)->fname);
+  else
+    return;  // ???
+
+
+  pc = setFirstItem(pb->function_calls);
+  for( ; pc; pc = setNextItem(pb->function_calls)) {
+
+    if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
+      char *dest = pic16_get_op_from_instruction(PCI(pc));
+
+      pcn = findFunction(dest);
+      if(pcn) 
+       pct2(of,pcn->pb,indent+1);
+    } else
+      fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
+
+  }
+
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/* pic16_printCallTree - writes the call tree to a file                  */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
+void pic16_printCallTree(FILE *of)
+{
+  pBranch *pbr;
+  pBlock  *pb;
+  pCode   *pc;
+
+  if(!the_pFile)
+    return;
+
+  if(!of)
+    of = stderr;
+
+  fprintf(of, "\npBlock statistics\n");
+  for(pb = the_pFile->pbHead; pb;  pb = pb->next )
+    pBlockStats(of,pb);
+
+
+
+  fprintf(of,"Call Tree\n");
+  pbr = the_pFile->functions;
+  while(pbr) {
+    if(pbr->pc) {
+      pc = pbr->pc;
+      if(!ispCodeFunction(pc))
+       fprintf(of,"bug in call tree");
+
+
+      fprintf(of,"Function: %s\n", PCF(pc)->fname);
+
+      while(pc->next && !ispCodeFunction(pc->next)) {
+       pc = pc->next;
+       if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
+         fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
+      }
+    }
+
+    pbr = pbr->next;
+  }
+
+
+  fprintf(of,"\n**************\n\na better call tree\n");
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+    if(pb->visited)
+      pct2(of,pb,0);
+  }
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+    fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
+  }
+}
+
+
+
+/*-----------------------------------------------------------------*/
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
+static void InlineFunction(pBlock *pb)
+{
+  pCode *pc;
+  pCode *pc_call;
+
+  if(!pb)
+    return;
+
+  pc = setFirstItem(pb->function_calls);
+
+  for( ; pc; pc = setNextItem(pb->function_calls)) {
+
+    if(isCALL(pc)) {
+      pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
+      pCode *pct;
+      pCode *pce;
+
+      pBranch *pbr;
+
+      if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
+       
+       //fprintf(stderr,"Cool can inline:\n");
+       //pcn->print(stderr,pcn);
+
+       //fprintf(stderr,"recursive call Inline\n");
+       InlineFunction(pcn->pb);
+       //fprintf(stderr,"return from recursive call Inline\n");
+
+       /*
+         At this point, *pc points to a CALL mnemonic, and
+         *pcn points to the function that is being called.
+
+         To in-line this call, we need to remove the CALL
+         and RETURN(s), and link the function pCode in with
+         the CALLee pCode.
+
+       */
+
+
+       /* Remove the CALL */
+       pc_call = pc;
+       pc = pc->prev;
+
+       /* remove callee pBlock from the pBlock linked list */
+       removepBlock(pcn->pb);
+
+       pce = pcn;
+       while(pce) {
+         pce->pb = pb;
+         pce = pce->next;
+       }
+
+       /* Remove the Function pCode */
+       pct = pic16_findNextInstruction(pcn->next);
+
+       /* Link the function with the callee */
+       pc->next = pcn->next;
+       pcn->next->prev = pc;
+       
+       /* Convert the function name into a label */
+
+       pbr = Safe_calloc(1,sizeof(pBranch));
+       pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
+       pbr->next = NULL;
+       PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
+       PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
+
+       /* turn all of the return's except the last into goto's */
+       /* check case for 2 instruction pBlocks */
+       pce = pic16_findNextInstruction(pcn->next);
+       while(pce) {
+         pCode *pce_next = pic16_findNextInstruction(pce->next);
+
+         if(pce_next == NULL) {
+           /* found the last return */
+           pCode *pc_call_next =  pic16_findNextInstruction(pc_call->next);
+
+           //fprintf(stderr,"found last return\n");
+           //pce->print(stderr,pce);
+           pce->prev->next = pc_call->next;
+           pc_call->next->prev = pce->prev;
+           PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
+                                                     PCI(pce)->label);
+         }
+
+         pce = pce_next;
+       }
+
+
+      }
+    } else
+      fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
+
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
+void pic16_InlinepCode(void)
+{
+
+  pBlock  *pb;
+  pCode   *pc;
+
+  if(!the_pFile)
+    return;
+
+  if(!functionInlining)
+    return;
+
+  /* Loop through all of the function definitions and count the
+   * number of times each one is called */
+  //fprintf(stderr,"inlining %d\n",__LINE__);
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+
+    pc = setFirstItem(pb->function_calls);
+
+    for( ; pc; pc = setNextItem(pb->function_calls)) {
+
+      if(isCALL(pc)) {
+       pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
+       if(pcn && isPCF(pcn)) {
+         PCF(pcn)->ncalled++;
+       }
+      } else
+       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
+
+    }
+  }
+
+  //fprintf(stderr,"inlining %d\n",__LINE__);
+
+  /* Now, Loop through the function definitions again, but this
+   * time inline those functions that have only been called once. */
+  
+  InlineFunction(the_pFile->pbHead);
+  //fprintf(stderr,"inlining %d\n",__LINE__);
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    unBuildFlow(pb);
+
+}
diff --git a/src/pic16/pcode.h b/src/pic16/pcode.h
new file mode 100644 (file)
index 0000000..c8c2452
--- /dev/null
@@ -0,0 +1,885 @@
+/*-------------------------------------------------------------------------
+
+   pcode.h - post code generation
+   Written By -  Scott Dattalo scott@dattalo.com
+   Ported to PIC16 By -  Martin Dubuc m.dubuc@rogers.com
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+-------------------------------------------------------------------------*/
+
+//#include "ralloc.h"
+struct regs;
+
+/*
+   Post code generation
+
+   The post code generation is an assembler optimizer. The assembly code
+   produced by all of the previous steps is fully functional. This step
+   will attempt to analyze the flow of the assembly code and agressively 
+   optimize it. The peep hole optimizer attempts to do the same thing.
+   As you may recall, the peep hole optimizer replaces blocks of assembly
+   with more optimal blocks (e.g. removing redundant register loads).
+   However, the peep hole optimizer has to be somewhat conservative since
+   an assembly program has implicit state information that's unavailable 
+   when only a few instructions are examined.
+     Consider this example:
+
+   example1:
+     movwf  t1
+     movf   t1,w
+
+   The movf seems redundant since we know that the W register already
+   contains the same value of t1. So a peep hole optimizer is tempted to
+   remove the "movf". However, this is dangerous since the movf affects
+   the flags in the status register (specifically the Z flag) and subsequent
+   code may depend upon this. Look at these two examples:
+
+   example2:
+     movwf  t1
+     movf   t1,w     ; Can't remove this movf
+     skpz
+      return
+
+   example3:
+     movwf  t1
+     movf   t1,w     ; This  movf can be removed
+     xorwf  t2,w     ; since xorwf will over write Z 
+     skpz
+      return
+
+*/
+
+
+#ifndef __PCODE_H__
+#define __PCODE_H__
+
+/***********************************************************************
+ * debug stuff
+ * 
+ * The DFPRINTF macro will call fprintf if PCODE_DEBUG is defined.
+ * The macro is used like:
+ *
+ * DPRINTF(("%s #%d\n","test", 1));
+ *
+ * The double parenthesis (()) are necessary
+ * 
+ ***********************************************************************/
+//#define PCODE_DEBUG
+
+#ifdef PCODE_DEBUG
+#define DFPRINTF(args) (fprintf args)
+#else
+#define DFPRINTF(args) ;
+#endif
+
+
+/***********************************************************************
+ *  PIC status bits - this will move into device dependent headers
+ ***********************************************************************/
+#define PIC_C_BIT    0
+#define PIC_DC_BIT   1
+#define PIC_Z_BIT    2
+#define PIC_OV_BIT   3
+#define PIC_N_BIT    4
+#define PIC_IRP_BIT  7   /* Indirect register page select */
+
+/***********************************************************************
+ *  PIC INTCON bits - this will move into device dependent headers
+ ***********************************************************************/
+#define PIC_RBIF_BIT 0   /* Port B level has changed flag */
+#define PIC_INTF_BIT 1   /* Port B bit 0 interrupt on edge flag */
+#define PIC_T0IF_BIT 2   /* TMR0 has overflowed flag */
+#define PIC_RBIE_BIT 3   /* Port B level has changed - Interrupt Enable */
+#define PIC_INTE_BIT 4   /* Port B bit 0 interrupt on edge - Int Enable */
+#define PIC_T0IE_BIT 5   /* TMR0 overflow Interrupt Enable */
+#define PIC_PIE_BIT  6   /* Peripheral Interrupt Enable */
+#define PIC_GIE_BIT  7   /* Global Interrupt Enable */
+
+/***********************************************************************
+ *  PIC bank definitions
+ ***********************************************************************/
+#define PIC_BANK_FIRST 0
+#define PIC_BANK_LAST  0xf
+
+
+/***********************************************************************
+ *  Operand types 
+ ***********************************************************************/
+#define POT_RESULT  0
+#define POT_LEFT    1
+#define POT_RIGHT   2
+
+
+/***********************************************************************
+ *
+ *  PIC_OPTYPE - Operand types that are specific to the PIC architecture
+ *
+ *  If a PIC assembly instruction has an operand then here is where we
+ *  associate a type to it. For example,
+ *
+ *     movf    reg,W
+ *
+ *  The movf has two operands: 'reg' and the W register. 'reg' is some
+ *  arbitrary general purpose register, hence it has the type PO_GPR_REGISTER.
+ *  The W register, which is the PIC's accumulator, has the type PO_W.
+ *
+ ***********************************************************************/
+
+
+
+typedef enum 
+{
+  PO_NONE=0,         // No operand e.g. NOP
+  PO_W,              // The working register (as a destination)
+  PO_WREG,           // The working register (as a file register)
+  PO_STATUS,         // The 'STATUS' register
+  PO_BSR,            // The 'BSR' register
+  PO_FSR0,           // The "file select register" (in PIC18 family it's one 
+                     // of three)
+  PO_INDF0,          // The Indirect register
+  PO_INTCON,         // Interrupt Control register
+  PO_GPR_REGISTER,   // A general purpose register
+  PO_GPR_BIT,        // A bit of a general purpose register
+  PO_GPR_TEMP,       // A general purpose temporary register
+  PO_SFR_REGISTER,   // A special function register (e.g. PORTA)
+  PO_PCL,            // Program counter Low register
+  PO_PCLATH,         // Program counter Latch high register
+  PO_LITERAL,        // A constant
+  PO_REL_ADDR,       // A relative address
+  PO_IMMEDIATE,      //  (8051 legacy)
+  PO_DIR,            // Direct memory (8051 legacy)
+  PO_CRY,            // bit memory (8051 legacy)
+  PO_BIT,            // bit operand.
+  PO_STR,            //  (8051 legacy)
+  PO_LABEL,
+  PO_WILD            // Wild card operand in peep optimizer
+} PIC_OPTYPE;
+
+
+/***********************************************************************
+ *
+ *  PIC_OPCODE
+ *
+ *  This is not a list of the PIC's opcodes per se, but instead
+ *  an enumeration of all of the different types of pic opcodes. 
+ *
+ ***********************************************************************/
+
+typedef enum
+{
+  POC_WILD=-1,   /* Wild card - used in the pCode peep hole optimizer
+                 * to represent ANY pic opcode */
+  POC_ADDLW=0,
+  POC_ADDWF,
+  POC_ADDFW,
+  POC_ADDFWC,
+  POC_ADDWFC,
+  POC_ANDLW,
+  POC_ANDWF,
+  POC_ANDFW,
+  POC_BC,
+  POC_BCF,
+  POC_BN,
+  POC_BNC,
+  POC_BNN,
+  POC_BNOV,
+  POC_BNZ,
+  POC_BOV,
+  POC_BRA,
+  POC_BSF,
+  POC_BTFSC,
+  POC_BTFSS,
+  POC_BTG,
+  POC_BZ,
+  POC_CALL,
+  POC_CLRF,
+  POC_CLRWDT,
+  POC_COMF,
+  POC_COMFW,
+  POC_CPFSEQ,
+  POC_CPFSGT,
+  POC_CPFSLT,
+  POC_DAW,
+  POC_DCFSNZ,
+  POC_DCFSNZW,
+  POC_DECF,
+  POC_DECFW,
+  POC_DECFSZ,
+  POC_DECFSZW,
+  POC_GOTO,
+  POC_INCF,
+  POC_INCFW,
+  POC_INCFSZ,
+  POC_INCFSZW,
+  POC_INFSNZ,
+  POC_IORWF,
+  POC_IORFW,
+  POC_IORLW,
+  POC_LFSR,
+  POC_MOVF,
+  POC_MOVFW,
+  POC_MOVFF,
+  POC_MOVLB,
+  POC_MOVLW,
+  POC_MOVWF,
+  POC_MULLW,
+  POC_MULWF,
+  POC_NEGF,
+  POC_NOP,
+  POC_POP,
+  POC_PUSH,
+  POC_RCALL,
+  POC_RETFIE,
+  POC_RETLW,
+  POC_RETURN,
+  POC_RLCF,
+  POC_RLCFW,
+  POC_RLNCF,
+  POC_RLNCFW,
+  POC_RRCF,
+  POC_RRCFW,
+  POC_RRNCF,
+  POC_RRNCFW,
+  POC_SETF,
+  POC_SUBLW,
+  POC_SUBFWB,
+  POC_SUBWF,
+  POC_SUBFW,
+  POC_SUBWFB_D0,
+  POC_SUBWFB_D1,
+  POC_SUBFWB_D0,
+  POC_SUBFWB_D1,
+  POC_SWAPF,
+  POC_SWAPFW,
+  POC_TRIS, // To be removed
+  POC_TSTFSZ,
+  POC_XORLW,
+  POC_XORWF,
+  POC_XORFW
+} PIC_OPCODE;
+
+
+/***********************************************************************
+ *  PC_TYPE  - pCode Types
+ ***********************************************************************/
+
+typedef enum
+{
+  PC_COMMENT=0,   /* pCode is a comment     */
+  PC_INLINE,      /* user's inline code     */
+  PC_OPCODE,      /* PORT dependent opcode  */
+  PC_LABEL,       /* assembly label         */
+  PC_FLOW,        /* flow analysis          */
+  PC_FUNCTION,    /* Function start or end  */
+  PC_WILD,        /* wildcard - an opcode place holder used 
+                  * in the pCode peep hole optimizer */
+  PC_CSOURCE,     /* C-Source Line  */
+  PC_BAD          /* Mark the pCode object as being bad */
+} PC_TYPE;
+
+/************************************************/
+/***************  Structures ********************/
+/************************************************/
+/* These are here as forward references - the 
+ * full definition of these are below           */
+struct pCode;
+struct pCodeWildBlock;
+struct pCodeRegLives;
+
+/*************************************************
+  pBranch
+
+  The first step in optimizing pCode is determining
+ the program flow. This information is stored in
+ single-linked lists in the for of 'from' and 'to'
+ objects with in a pcode. For example, most instructions
+ don't involve any branching. So their from branch
+ points to the pCode immediately preceding them and
+ their 'to' branch points to the pcode immediately
+ following them. A skip instruction is an example of
+ a pcode that has multiple (in this case two) elements
+ in the 'to' branch. A 'label' pcode is an where there
+ may be multiple 'from' branches.
+ *************************************************/
+
+typedef struct pBranch
+{
+  struct pCode   *pc;    // Next pCode in a branch
+  struct pBranch *next;  /* If more than one branch
+                         * the next one is here */
+
+} pBranch;
+
+/*************************************************
+  pCodeOp
+
+  pCode Operand structure.
+  For those assembly instructions that have arguments, 
+  the pCode will have a pCodeOp in which the argument
+  can be stored. For example
+
+    movf   some_register,w
+
+  'some_register' will be stored/referenced in a pCodeOp
+
+ *************************************************/
+
+typedef struct pCodeOp
+{
+  PIC_OPTYPE type;
+  char *name;
+  
+} pCodeOp;
+#if 0
+typedef struct pCodeOpBit
+{
+  pCodeOp pcop;
+  int bit;
+  unsigned int inBitSpace: 1; /* True if in bit space, else
+                                just a bit of a register */
+} pCodeOpBit;
+#endif
+typedef struct pCodeOpLit
+{
+  pCodeOp pcop;
+  int lit;
+} pCodeOpLit;
+
+typedef struct pCodeOpImmd
+{
+  pCodeOp pcop;
+  int offset;           /* low,med, or high byte of immediat value */
+  int index;            /* add this to the immediate value */
+  unsigned _const:1;    /* is in code space    */
+
+  int rIdx;             /* If this immd points to a register */
+  struct regs *r;       /* then this is the reg. */
+
+} pCodeOpImmd;
+
+typedef struct pCodeOpLabel
+{
+  pCodeOp pcop;
+  int key;
+} pCodeOpLabel;
+
+typedef struct pCodeOpReg
+{
+  pCodeOp pcop;    // Can be either GPR or SFR
+  int rIdx;        // Index into the register table
+  struct regs *r;
+  int instance;    // byte # of Multi-byte registers
+  struct pBlock *pb;
+} pCodeOpReg;
+
+typedef struct pCodeOpRegBit
+{
+  pCodeOpReg  pcor;       // The Register containing this bit
+  int bit;                // 0-7 bit number.
+  PIC_OPTYPE subtype;     // The type of this register.
+  unsigned int inBitSpace: 1; /* True if in bit space, else
+                                just a bit of a register */
+} pCodeOpRegBit;
+
+
+typedef struct pCodeOpWild
+{
+  pCodeOp pcop;
+
+  struct pCodeWildBlock *pcwb;
+
+  int id;                 /* index into an array of char *'s that will match
+                          * the wild card. The array is in *pcp. */
+  pCodeOp *subtype;       /* Pointer to the Operand type into which this wild
+                          * card will be expanded */
+  pCodeOp *matched;       /* When a wild matches, we'll store a pointer to the
+                          * opcode we matched */
+
+} pCodeOpWild;
+
+
+/*************************************************
+    pCode
+
+    Here is the basic build block of a PIC instruction.
+    Each pic instruction will get allocated a pCode.
+    A linked list of pCodes makes a program.
+
+**************************************************/
+
+typedef struct pCode
+{
+  PC_TYPE    type;
+
+  struct pCode *prev;  // The pCode objects are linked together
+  struct pCode *next;  // in doubly linked lists.
+
+  int seq;             // sequence number
+
+  struct pBlock *pb;   // The pBlock that contains this pCode.
+
+  /* "virtual functions"
+   *  The pCode structure is like a base class
+   * in C++. The subsequent structures that "inherit"
+   * the pCode structure will initialize these function
+   * pointers to something useful */
+  //  void (*analyze) (struct pCode *_this);
+  void (*destruct)(struct pCode *_this);
+  void (*print)  (FILE *of,struct pCode *_this);
+
+} pCode;
+
+
+/*************************************************
+    pCodeComment
+**************************************************/
+
+typedef struct pCodeComment
+{
+
+  pCode  pc;
+
+  char *comment;
+
+} pCodeComment;
+
+/*************************************************
+    pCodeComment
+**************************************************/
+
+typedef struct pCodeCSource
+{
+
+  pCode  pc;
+
+  int  line_number;
+  char *line;
+  char *file_name;
+
+} pCodeCSource;
+
+
+/*************************************************
+    pCodeFlow
+
+  The Flow object is used as marker to separate 
+ the assembly code into contiguous chunks. In other
+ words, everytime an instruction cause or potentially
+ causes a branch, a Flow object will be inserted into
+ the pCode chain to mark the beginning of the next
+ contiguous chunk.
+
+**************************************************/
+
+typedef struct pCodeFlow
+{
+
+  pCode  pc;
+
+  pCode *end;   /* Last pCode in this flow. Note that
+                  the first pCode is pc.next */
+
+  /*  set **uses;   * map the pCode instruction inCond and outCond conditions 
+                * in this array of set's. The reason we allocate an 
+                * array of pointers instead of declaring each type of 
+                * usage is because there are port dependent usage definitions */
+  //int nuses;    /* number of uses sets */
+
+  set *from;    /* flow blocks that can send control to this flow block */
+  set *to;      /* flow blocks to which this one can send control */
+  struct pCodeFlow *ancestor; /* The most immediate "single" pCodeFlow object that
+                              * executes prior to this one. In many cases, this 
+                              * will be just the previous */
+
+  int inCond;   /* Input conditions - stuff assumed defined at entry */
+  int outCond;  /* Output conditions - stuff modified by flow block */
+
+  int firstBank; /* The first and last bank flags are the first and last */
+  int lastBank;  /* register banks used within one flow object */
+
+  int FromConflicts;
+  int ToConflicts;
+
+  set *registers;/* Registers used in this flow */
+
+} pCodeFlow;
+
+/*************************************************
+  pCodeFlowLink
+
+  The Flow Link object is used to record information
+ about how consecutive excutive Flow objects are related.
+ The pCodeFlow objects demarcate the pCodeInstructions
+ into contiguous chunks. The FlowLink records conflicts
+ in the discontinuities. For example, if one Flow object
+ references a register in bank 0 and the next Flow object
+ references a register in bank 1, then there is a discontinuity
+ in the banking registers.
+
+*/
+typedef struct pCodeFlowLink
+{
+  pCodeFlow  *pcflow;   /* pointer to linked pCodeFlow object */
+
+  int bank_conflict;    /* records bank conflicts */
+
+} pCodeFlowLink;
+
+/*************************************************
+    pCodeInstruction
+
+    Here we describe all the facets of a PIC instruction
+    (expansion for the 18cxxx is also provided).
+
+**************************************************/
+
+typedef struct pCodeInstruction
+{
+
+  pCode  pc;
+
+  PIC_OPCODE op;        // The opcode of the instruction.
+
+  char const * const mnemonic;       // Pointer to mnemonic string
+
+  pBranch *from;       // pCodes that execute before this one
+  pBranch *to;         // pCodes that execute after
+  pBranch *label;      // pCode instructions that have labels
+
+  pCodeOp *pcop;               /* Operand, if this instruction has one */
+  pCodeFlow *pcflow;           /* flow block to which this instruction belongs */
+  pCodeCSource *cline;         /* C Source from which this instruction was derived */
+
+  unsigned int num_ops;        /* Number of operands (0,1,2 for mid range pics) */
+  unsigned int isModReg:  1;   /* If destination is W or F, then 1==F */
+  unsigned int isBitInst: 1;   /* e.g. BCF */
+  unsigned int isBranch:  1;   /* True if this is a branching instruction */
+  unsigned int isSkip:    1;   /* True if this is a skip instruction */
+  unsigned int isLit:     1;   /* True if this instruction has an literal operand */
+  unsigned int isAccess:   1;   /* True if this instruction has an access RAM operand */
+  unsigned int isFastCall: 1;   /* True if this instruction has a fast call/return mode select operand */
+
+  PIC_OPCODE inverted_op;      /* Opcode of instruction that's the opposite of this one */
+  unsigned int inCond;   // Input conditions for this instruction
+  unsigned int outCond;  // Output conditions for this instruction
+
+} pCodeInstruction;
+
+
+/*************************************************
+    pCodeLabel
+**************************************************/
+
+typedef struct pCodeLabel
+{
+
+  pCode  pc;
+
+  char *label;
+  int key;
+
+} pCodeLabel;
+
+/*************************************************
+    pCodeFunction
+**************************************************/
+
+typedef struct pCodeFunction
+{
+
+  pCode  pc;
+
+  char *modname;
+  char *fname;     /* If NULL, then this is the end of
+                     a function. Otherwise, it's the
+                     start and the name is contained
+                     here */
+
+  pBranch *from;       // pCodes that execute before this one
+  pBranch *to;         // pCodes that execute after
+  pBranch *label;      // pCode instructions that have labels
+
+  int  ncalled;    /* Number of times function is called */
+
+} pCodeFunction;
+
+
+/*************************************************
+    pCodeWild
+**************************************************/
+
+typedef struct pCodeWild
+{
+
+  pCodeInstruction  pci;
+
+  int    id;     /* Index into the wild card array of a peepBlock 
+                 * - this wild card will get expanded into that pCode
+                 *   that is stored at this index */
+
+  /* Conditions on wild pcode instruction */
+  int    mustBeBitSkipInst:1;
+  int    mustNotBeBitSkipInst:1;
+  int    invertBitSkipInst:1;
+
+  pCodeOp *operand;  // Optional operand
+  pCodeOp *label;    // Optional label
+
+} pCodeWild;
+
+/*************************************************
+    pBlock
+
+    Here are PIC program snippets. There's a strong
+    correlation between the eBBlocks and pBlocks.
+    SDCC subdivides a C program into managable chunks.
+    Each chunk becomes a eBBlock and ultimately in the
+    PIC port a pBlock.
+
+**************************************************/
+
+typedef struct pBlock
+{
+  memmap *cmemmap;   /* The snippet is from this memmap */
+  char   dbName;     /* if cmemmap is NULL, then dbName will identify the block */
+  pCode *pcHead;     /* A pointer to the first pCode in a link list of pCodes */
+  pCode *pcTail;     /* A pointer to the last pCode in a link list of pCodes */
+
+  struct pBlock *next;      /* The pBlocks will form a doubly linked list */
+  struct pBlock *prev;
+
+  set *function_entries;    /* dll of functions in this pblock */
+  set *function_exits;
+  set *function_calls;
+  set *tregisters;
+
+  set *FlowTree;
+  unsigned visited:1;       /* set true if traversed in call tree */
+
+  unsigned seq;             /* sequence number of this pBlock */
+
+} pBlock;
+
+/*************************************************
+    pFile
+
+    The collection of pBlock program snippets are
+    placed into a linked list that is implemented
+    in the pFile structure.
+
+    The pcode optimizer will parse the pFile.
+
+**************************************************/
+
+typedef struct pFile
+{
+  pBlock *pbHead;     /* A pointer to the first pBlock */
+  pBlock *pbTail;     /* A pointer to the last pBlock */
+
+  pBranch *functions; /* A SLL of functions in this pFile */
+
+} pFile;
+
+
+
+/*************************************************
+  pCodeWildBlock
+
+  The pCodeWildBlock object keeps track of the wild
+  variables, operands, and opcodes that exist in
+  a pBlock.
+**************************************************/
+typedef struct pCodeWildBlock {
+  pBlock    *pb;
+  struct pCodePeep *pcp;    // pointer back to ... I don't like this...
+
+  int       nvars;          // Number of wildcard registers in target.
+  char    **vars;           // array of pointers to them
+
+  int       nops;           // Number of wildcard operands in target.
+  pCodeOp **wildpCodeOps;   // array of pointers to the pCodeOp's.
+
+  int       nwildpCodes;    // Number of wildcard pCodes in target/replace
+  pCode   **wildpCodes;     // array of pointers to the pCode's.
+
+} pCodeWildBlock;
+
+/*************************************************
+  pCodePeep
+
+  The pCodePeep object mimics the peep hole optimizer
+  in the main SDCC src (e.g. SDCCpeeph.c). Essentially
+  there is a target pCode chain and a replacement
+  pCode chain. The target chain is compared to the
+  pCode that is generated by gen.c. If a match is
+  found then the pCode is replaced by the replacement
+  pCode chain.
+**************************************************/
+typedef struct pCodePeep {
+  pCodeWildBlock target;     // code we'd like to optimize
+  pCodeWildBlock replace;    // and this is what we'll optimize it with.
+
+  //pBlock *target;
+  //pBlock replace;            // and this is what we'll optimize it with.
+
+
+
+  /* (Note: a wildcard register is a place holder. Any register
+   * can be replaced by the wildcard when the pcode is being 
+   * compared to the target. */
+
+  /* Post Conditions. A post condition is a condition that
+   * must be either true or false before the peep rule is
+   * accepted. For example, a certain rule may be accepted
+   * if and only if the Z-bit is not used as an input to 
+   * the subsequent instructions in a pCode chain.
+   */
+  unsigned int postFalseCond;  
+  unsigned int postTrueCond;
+
+} pCodePeep;
+
+/*************************************************
+
+  pCode peep command definitions 
+
+ Here are some special commands that control the
+way the peep hole optimizer behaves
+
+**************************************************/
+
+enum peepCommandTypes{
+  NOTBITSKIP = 0,
+  BITSKIP,
+  INVERTBITSKIP,
+  _LAST_PEEP_COMMAND_
+};
+
+/*************************************************
+    peepCommand structure stores the peep commands.
+
+**************************************************/
+
+typedef struct peepCommand {
+  int id;
+  char *cmd;
+} peepCommand;
+
+/*************************************************
+    pCode Macros
+
+**************************************************/
+#define PCODE(x)  ((pCode *)(x))
+#define PCI(x)    ((pCodeInstruction *)(x))
+#define PCL(x)    ((pCodeLabel *)(x))
+#define PCF(x)    ((pCodeFunction *)(x))
+#define PCFL(x)   ((pCodeFlow *)(x))
+#define PCFLINK(x)((pCodeFlowLink *)(x))
+#define PCW(x)    ((pCodeWild *)(x))
+#define PCCS(x)   ((pCodeCSource *)(x))
+
+#define PCOP(x)   ((pCodeOp *)(x))
+//#define PCOB(x)   ((pCodeOpBit *)(x))
+#define PCOL(x)   ((pCodeOpLit *)(x))
+#define PCOI(x)   ((pCodeOpImmd *)(x))
+#define PCOLAB(x) ((pCodeOpLabel *)(x))
+#define PCOR(x)   ((pCodeOpReg *)(x))
+#define PCORB(x)  ((pCodeOpRegBit *)(x))
+#define PCOW(x)   ((pCodeOpWild *)(x))
+
+#define PBR(x)    ((pBranch *)(x))
+
+#define PCWB(x)   ((pCodeWildBlock *)(x))
+
+
+/*
+  macros for checking pCode types
+*/
+#define isPCI(x)        ((PCODE(x)->type == PC_OPCODE))
+#define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isBranch)
+#define isPCI_SKIP(x)   ((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isSkip)
+#define isPCI_LIT(x)    ((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isLit)
+#define isPCI_BITSKIP(x)((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isSkip && PCI(x)->isBitInst)
+#define isPCFL(x)       ((PCODE(x)->type == PC_FLOW))
+#define isPCF(x)        ((PCODE(x)->type == PC_FUNCTION))
+#define isPCL(x)        ((PCODE(x)->type == PC_LABEL))
+#define isPCW(x)        ((PCODE(x)->type == PC_WILD))
+#define isPCCS(x)       ((PCODE(x)->type == PC_CSOURCE))
+
+#define isCALL(x)       ((isPCI(x)) && (PCI(x)->op == POC_CALL))
+#define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
+#define isBSR_REG(r)    ((r)->pc_type == PO_BSR)
+
+#define isACCESS_LOW(r) ((pic16_finalMapping[REG_ADDR(r)].bank == \
+                          PIC_BANK_FIRST) && (REG_ADDR(r) < 0x80))
+#define isACCESS_HI(r)  (pic16_finalMapping[REG_ADDR(r)].bank == PIC_BANK_LAST)
+#define isACCESS_BANK(r)(isACCESS_LOW(r) || isACCESS_HI(r))
+
+#define isPCOLAB(x)     ((PCOP(x)->type) == PO_LABEL)
+
+/*-----------------------------------------------------------------*
+ * pCode functions.
+ *-----------------------------------------------------------------*/
+
+pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop); // Create a new pCode given an operand
+pCode *pic16_newpCodeCharP(char *cP);              // Create a new pCode given a char *
+pCode *pic16_newpCodeInlineP(char *cP);            // Create a new pCode given a char *
+pCode *pic16_newpCodeFunction(char *g, char *f);   // Create a new function
+pCode *pic16_newpCodeLabel(char *name,int key);    // Create a new label given a key
+pCode *pic16_newpCodeCSource(int ln, char *f, char *l); // Create a new symbol line 
+pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc); // Create a new pBlock
+void pic16_printpBlock(FILE *of, pBlock *pb);      // Write a pBlock to a file
+void pic16_addpCode2pBlock(pBlock *pb, pCode *pc); // Add a pCode to a pBlock
+void pic16_addpBlock(pBlock *pb);                  // Add a pBlock to a pFile
+void pic16_copypCode(FILE *of, char dbName);       // Write all pBlocks with dbName to *of
+void pic16_movepBlock2Head(char dbName);           // move pBlocks around
+void pic16_AnalyzepCode(char dbName);
+void pic16_printCallTree(FILE *of);
+void pCodePeepInit(void);
+void pic16_pBlockConvert2ISR(pBlock *pb);
+
+pCodeOp *pic16_newpCodeOpLabel(char *name, int key);
+pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space);
+pCodeOp *pic16_newpCodeOpLit(int lit);
+pCodeOp *pic16_newpCodeOpBit(char *name, int bit,int inBitSpace);
+pCodeOp *pic16_newpCodeOpRegFromStr(char *name);
+pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE p);
+pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop);
+
+pCode * pic16_findNextInstruction(pCode *pci);
+pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct);
+int pic16_isPCinFlow(pCode *pc, pCode *pcflow);
+struct regs * pic16_getRegFromInstruction(pCode *pc);
+
+extern void pic16_pcode_test(void);
+
+/*-----------------------------------------------------------------*
+ * pCode objects.
+ *-----------------------------------------------------------------*/
+
+extern pCodeOpReg pic16_pc_status;
+extern pCodeOpReg pic16_pc_intcon;
+extern pCodeOpReg pic16_pc_indf0;
+extern pCodeOpReg pic16_pc_fsr0;
+extern pCodeOpReg pic16_pc_pcl;
+extern pCodeOpReg pic16_pc_pclath;
+extern pCodeOpReg pic16_pc_wreg;
+extern pCodeOpReg pic16_pc_kzero;
+extern pCodeOpReg pic16_pc_wsave;     /* wsave and ssave are used to save W and the Status */
+extern pCodeOpReg pic16_pc_ssave;     /* registers during an interrupt */
+
+
+#endif // __PCODE_H__
diff --git a/src/pic16/pcodeflow.c b/src/pic16/pcodeflow.c
new file mode 100644 (file)
index 0000000..8beaac4
--- /dev/null
@@ -0,0 +1,350 @@
+/*-------------------------------------------------------------------------
+
+   pcodeflow.c - post code generation flow analysis
+
+   Written By -  Scott Dattalo scott@dattalo.com
+   Ported to PIC16 By -  Martin Dubuc m.dubuc@rogers.com
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+-------------------------------------------------------------------------*/
+/*
+  pcodeflow.c
+
+  The purpose of the code in this file is to analyze the flow of the
+  pCode.
+
+*/
+
+#include <stdio.h>
+
+#include "common.h"   // Include everything in the SDCC src directory
+#include "newalloc.h"
+#include "ralloc.h"
+#include "device.h"
+#include "pcode.h"
+#include "pcoderegs.h"
+#include "pcodeflow.h"
+
+#if 0
+
+/* 
+   In the section that follows, an exhaustive flow "tree" is built.
+   It's not a tree that's really built, but instead every possible
+   flow path is constructed. 
+
+   This is really overkill...
+*/
+
+static set *FlowTree=NULL;
+
+void dbg_dumpFlowTree(set *FlowTree)
+{
+  set *segment;
+  pCodeFlow *pcflow;
+
+  fprintf(stderr,"Flow Tree: \n");
+
+  for(segment = setFirstItem(FlowTree); segment; segment=setNextItem(FlowTree)) {
+
+    fprintf(stderr,"Segment:\n");
+
+    for(pcflow=PCFL(setFirstItem(segment)); pcflow; pcflow=PCFL(setNextItem(segment))) {
+      fprintf(stderr, "  0x%03x",pcflow->pc.seq);
+    }
+    fprintf(stderr,"\n");
+  }
+
+}
+
+
+
+
+/*-----------------------------------------------------------------*
+ * void BuildFlowSegment(set *segment, pCodeFlow *pcflow)
+ *-----------------------------------------------------------------*/
+static void BuildFlowSegment(set *segment, pCodeFlow *pcflow)
+{
+
+  int nNextFlow=0;
+  pCodeFlowLink *pcflowLink=NULL;
+
+  /* Add this flow to the set if it's not in there already */
+  if(isinSet(segment, pcflow)) {
+    addSetHead(&FlowTree, segment);
+    return;
+  }
+
+  addSetHead(&segment, pcflow);
+
+  /* Continue to add contiguous flows */
+
+  while( pcflow->to && ((nNextFlow = elementsInSet(pcflow->to)) == 1)) {
+    pcflowLink = (pCodeFlowLink *)(setFirstItem(pcflow->to));
+    pcflow = pcflowLink->pcflow;
+
+    if(isinSet(segment, pcflow)) {
+      addSetIfnotP(&FlowTree, segment);
+      return;
+    }
+
+    addSetIfnotP(&segment, pcflow);
+
+  }
+
+  /* Branch: for each branch, duplicate the set and recursively call */
+  if(pcflow->to && nNextFlow>=2) {
+    pCodeFlow *pcflow_to;
+
+    set *branch_segment=NULL;
+    
+    pcflowLink = (pCodeFlowLink *)(setFirstItem(pcflow->to));
+    pcflow_to = pcflowLink->pcflow;
+
+    addSetIfnotP(&segment, pcflow);
+
+    pcflowLink = (pCodeFlowLink *)(setNextItem(pcflow->to));
+
+    while(pcflowLink) {
+
+      branch_segment = setFromSet(segment);
+      BuildFlowSegment(setFromSet(segment),pcflowLink->pcflow);
+      pcflowLink = (pCodeFlowLink *)(setNextItem(pcflow->to));
+    }
+
+    /* add the first branch to this segment */
+    BuildFlowSegment(segment,pcflow_to);
+
+  }
+
+  addSetIfnotP(&FlowTree, segment);
+
+  /* done */
+}
+
+/*-----------------------------------------------------------------*
+ * void pic16_BuildFlowTree(pBlock *pb)
+ *-----------------------------------------------------------------*/
+void pic16_BuildFlowTree(pBlock *pb)
+{
+  pCodeFlow *pcflow;
+  set *segment;
+
+  FlowTree = newSet();
+
+  /* Start with the first flow object of this pBlock */
+
+  pcflow = PCFL(pic16_findNextpCode(pb->pcHead, PC_FLOW));
+
+  segment = newSet();
+  BuildFlowSegment(segment, pcflow);
+
+  pb->FlowTree = FlowTree;
+
+  dbg_dumpFlowTree(FlowTree);
+}
+#endif
+
+static void dbg_dumpFlow(pBlock *pb)
+{
+  pCode *pcflow;
+
+  for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
+       pcflow != NULL;
+       pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
+
+    if(!isPCFL(pcflow))
+      fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
+
+    fprintf(stderr, "Flow: 0x%x",pcflow->seq);
+    if(PCFL(pcflow) && PCFL(pcflow)->ancestor)
+      fprintf(stderr,", ancestor 0x%x\n",
+             PCFL(pcflow)->ancestor->pc.seq);
+    else {
+      pCodeFlowLink *from = (PCFL(pcflow)->from) ? (PCFLINK(setFirstItem(PCFL(pcflow)->from))) : NULL;
+      fprintf(stderr," no ancestor");
+      while(from) {
+       fprintf(stderr," (0x%x)",from->pcflow->pc.seq);
+       from = setNextItem(PCFL(pcflow)->from);
+      }
+      fprintf(stderr,"\n");
+    }
+  }
+
+}
+/*-----------------------------------------------------------------*
+ * void BuildFlowSegment(set *segment, pCodeFlow *pcflow)
+ *-----------------------------------------------------------------*/
+
+static void BuildFlowSegment(pCodeFlow *pcflow)
+{
+  static int recursion=0;
+  pCodeFlow *pcflow_other;
+  set *flowset;
+
+  if(!pcflow)
+    return;
+
+  if(recursion++ > 200) {
+    fprintf(stderr, " exceeded recursion\n");
+    return;
+  }
+
+  fprintf(stderr,"examining 0x%x\n",pcflow->pc.seq);
+
+  if(pcflow->from) {
+
+
+    flowset = pcflow->from;
+
+    if(flowset && flowset->next == NULL) {
+
+      /* 
+        There is a flow before this one. In fact, there's
+        exactly one flow before this one (because ->next is
+        NULL). That means all children of this node pass
+        through both this node and the node immediately 
+        before this one; i.e. they have the same ancestor.
+      */
+
+      if( (NULL == (pcflow_other = PCFLINK(flowset->item)->pcflow)) ||
+         (NULL == pcflow_other)) {
+       fprintf(stderr,"2 error in flow link\n");
+       exit(1);
+      }
+      pcflow->ancestor = pcflow_other->ancestor ;
+
+      fprintf(stderr,"Assigning ancestor 0x%x from flow 0x%x\n",
+             pcflow->ancestor->pc.seq, pcflow_other->pc.seq);
+
+    } else {
+
+      if(flowset == NULL) {
+
+       /* There are no flows before this one.
+        * If this is not the first flow object in the pBlock then 
+        * there's an error */
+
+       if(!pcflow->ancestor) {
+         fprintf(stderr,"error in flow link\n");
+         exit(1);
+
+       } 
+
+      } else {
+
+       /* Flow passes to this flow from multiple flows. Let's
+          look at just one of these. If the one we look at has
+          an ancestor, then that's our ancestor too. If the one
+          we look at doesn't have an ancestor, then that means
+          we haven't traversed that branch of the call tree 
+          yet - but we will */
+
+       pcflow_other = PCFLINK(flowset->item)->pcflow;
+       if(pcflow_other) {
+         fprintf(stderr, "coming from 0x%x\n",pcflow_other->pc.seq);
+         if( pcflow_other->ancestor)
+           pcflow->ancestor = pcflow_other->ancestor;
+       }
+      }
+
+
+    }
+
+  } else {
+    /* there are no nodes before this one */
+    if(!pcflow->ancestor)
+      fprintf(stderr,"3 Error in flow link\n");
+  }
+
+  /* Now let's recursively expand the call tree */
+
+  if(pcflow->ancestor && pcflow->to) {
+    flowset = pcflow->to;
+    while(flowset) {
+      BuildFlowSegment(PCFLINK(flowset->item)->pcflow);
+      flowset = flowset->next;
+    }
+  }
+
+}
+
+void pic16_BuildFlowTree(pBlock *pb)
+{
+  pCodeFlow *first_pcflow, *pcflow;
+
+
+  //  fprintf(stderr,"pic16_BuildFlowTree \n");
+
+  first_pcflow = PCFL(pic16_findNextpCode(pb->pcHead, PC_FLOW));
+  if(!first_pcflow)
+    return;
+
+  /* The very first node is like Adam, it's its own ancestor (i.e. 
+   * there are no other flows in this pBlock prior to the first one).
+   */
+
+  first_pcflow->ancestor = first_pcflow;
+
+  /* For each flow that has only one predecessor, it's easy to 
+     identify the ancestor */
+  pcflow = PCFL(pic16_findNextpCode(first_pcflow->pc.next, PC_FLOW));
+
+  while(pcflow) {
+    if(elementsInSet(pcflow->from) == 1) {
+      pCodeFlowLink *from = PCFLINK(setFirstItem(pcflow->from));
+
+      pcflow->ancestor = from->pcflow;
+      /*
+       fprintf(stderr,"Assigning ancestor 0x%x to flow 0x%x\n",
+       pcflow->ancestor->pc.seq, pcflow->pc.seq);
+      */
+    }
+
+    pcflow = PCFL(pic16_findNextpCode(pcflow->pc.next, PC_FLOW));
+
+  }
+
+  pcflow = PCFL(pic16_findNextpCode(first_pcflow->pc.next, PC_FLOW));
+
+  while(pcflow) {
+    if(elementsInSet(pcflow->from) > 1) {
+      pCodeFlow *min_pcflow;
+      pCodeFlowLink *from = PCFLINK(setFirstItem(pcflow->from));
+
+      min_pcflow = from->pcflow;
+
+      while( (from = setNextItem(pcflow->from)) != NULL) {
+       if(from->pcflow->pc.seq < min_pcflow->pc.seq)
+         min_pcflow = from->pcflow;
+      }
+
+      pcflow->ancestor = min_pcflow;
+      /*
+       fprintf(stderr,"Assigning ancestor 0x%x to flow 0x%x from multiple\n",
+       pcflow->ancestor->pc.seq, pcflow->pc.seq);
+      */
+
+    }
+
+    pcflow = PCFL(pic16_findNextpCode(pcflow->pc.next, PC_FLOW));
+
+  }
+  
+  //  BuildFlowSegment(pcflow);
+
+  //dbg_dumpFlow(pb);
+  
+}
diff --git a/src/pic16/pcodeflow.h b/src/pic16/pcodeflow.h
new file mode 100644 (file)
index 0000000..b451dea
--- /dev/null
@@ -0,0 +1,66 @@
+/*-------------------------------------------------------------------------
+
+   pcode.h - post code generation
+   Written By -  Scott Dattalo scott@dattalo.com
+   PIC16 port -  Martin Dubuc m.dubuc@rogers.com
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+-------------------------------------------------------------------------*/
+
+#ifndef __PCODEFLOW_H__
+#define __PCODEFLOW_H__
+
+/*************************************************
+ * pCode conditions:
+ *
+ * The "conditions" are bit-mapped flags that describe
+ * input and/or output conditions that are affected by
+ * the instructions. For example:
+ *
+ *    MOVF   SOME_REG,W
+ *
+ * This instruction depends upon 'SOME_REG'. Consequently
+ * it has the input condition PCC_REGISTER set to true.
+ *
+ * In addition, this instruction affects the Z bit in the
+ * status register and affects W. Thus the output conditions
+ * are the logical or:
+ *  PCC_ZERO_BIT | PCC_W
+ *
+ * The conditions are intialized when the pCode for an
+ * instruction is created. They're subsequently used
+ * by the pCode optimizer determine state information
+ * in the program flow.
+ *************************************************/
+
+#define  PCC_NONE          0
+#define  PCC_REGISTER      (1<<0)
+#define  PCC_REGISTER2     (1<<1)
+#define  PCC_C             (1<<2)
+#define  PCC_Z             (1<<3)
+#define  PCC_DC            (1<<4)
+#define  PCC_OV            (1<<5)
+#define  PCC_N             (1<<6)
+#define  PCC_W             (1<<7)
+#define  PCC_EXAMINE_PCOP  (1<<8)
+#define  PCC_LITERAL       (1<<9)
+#define  PCC_REL_ADDR      (1<<10)
+
+/*------------------------------------------------------------*/
+
+void BuildFlowAncestry(pBlock *pb);
+
+#endif // __PCODEFLOW_H__
diff --git a/src/pic16/pcodepeep.c b/src/pic16/pcodepeep.c
new file mode 100644 (file)
index 0000000..df81ff9
--- /dev/null
@@ -0,0 +1,2226 @@
+/*-------------------------------------------------------------------------
+
+   pcodepeep.c - post code generation
+   Written By -  Scott Dattalo scott@dattalo.com
+   Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"   // Include everything in the SDCC src directory
+#include "newalloc.h"
+//#define PCODE_DEBUG
+#include "pcode.h"
+#include "pcodeflow.h"
+#include "ralloc.h"
+
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
+#endif
+
+pCodeOp *pic16_popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
+
+pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype);
+pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
+pCode * pic16_findNextInstruction(pCode *pc);
+int pic16_getpCode(char *mnem,int dest);
+int pic16_getpCodePeepCommand(char *cmd);
+void pic16_pBlockMergeLabels(pBlock *pb);
+char *pCode2str(char *str, int size, pCode *pc);
+char *pic16_get_op( pCodeOp *pcop,char *buf,int buf_size);
+
+extern pCodeInstruction *pic16Mnemonics[];
+
+
+#define IS_PCCOMMENT(x) ( x && (x->type==PC_COMMENT))
+
+/****************************************************************/
+/*
+ * rootRules - defined in SDCCpeep.c
+ *  This is a pointer to the (parsed) peephole rules that are
+ * defined in peep.def.
+ */
+
+//extern peepRule *rootRules;
+
+
+
+
+/****************************************************************/
+/****************************************************************/
+typedef struct _DLL {
+  struct _DLL *prev;
+  struct _DLL *next;
+  //  void *data;
+} _DLL;
+
+
+typedef struct pCodePeepSnippets
+{
+  _DLL dll;
+  pCodePeep *peep;
+} pCodePeepSnippets;
+
+
+/****************************************************************/
+/*                                                              */
+/* peepSnippets -                                               */
+/*                                                              */
+/****************************************************************/
+
+static pCodePeepSnippets  *peepSnippets=NULL;
+
+/****************************************************************/
+/*                                                              */
+/* curPeep                                                      */
+/*                                                              */
+/****************************************************************/
+
+//static pCodePeep          *curPeep=NULL;
+
+/****************************************************************/
+/*                                                              */
+/* curBlock                                                     */
+/*                                                              */
+/****************************************************************/
+
+//static pBlock             *curBlock=NULL;
+
+
+/****************************************************************/
+/*                                                              */
+/* max wild cards in a peep rule                                */
+/*                                                              */
+/****************************************************************/
+
+//static int                sMaxWildVar   = 0;
+//static int                sMaxWildMnem  = 0;
+
+
+typedef struct pCodeToken 
+{
+  int tt;  // token type;
+  union {
+    char c;  // character
+    int  n;  // number
+    char *s; // string
+  } tok;
+
+} pCodeToken;
+
+pCodeToken tokArr[50];
+static unsigned   tokIdx=0;
+
+
+typedef enum  {
+  PCT_NULL=0,
+  PCT_SPACE=1,
+  PCT_PERCENT,
+  PCT_LESSTHAN,
+  PCT_GREATERTHAN,
+  PCT_COLON,
+  PCT_COMMA,
+  PCT_COMMENT,
+  PCT_STRING,
+  PCT_NUMBER
+
+} pCodeTokens;
+
+
+typedef struct parsedPattern {
+  struct pcPattern *pcp;
+  pCodeToken *pct;
+} parsedPattern;
+
+#define MAX_PARSEDPATARR 50
+parsedPattern parsedPatArr[MAX_PARSEDPATARR];
+static unsigned int parsedPatIdx=0;
+
+
+typedef enum {
+  PCP_LABEL=1,
+  PCP_NUMBER,
+  PCP_STR,
+  PCP_WILDVAR,
+  PCP_WILDSTR,
+  PCP_COMMA,
+  PCP_COMMENT
+} pCodePatterns;
+
+static char pcpat_label[]      = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
+static char pcpat_number[]     = {PCT_NUMBER, 0};
+static char pcpat_string[]     = {PCT_STRING, 0};
+static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
+static char pcpat_wildVar[]    = {PCT_PERCENT, PCT_NUMBER, 0};
+static char pcpat_comma[]      = {PCT_COMMA, 0};
+static char pcpat_comment[]    = {PCT_COMMENT, 0};
+
+
+typedef struct pcPattern {
+  char pt;                 // Pattern type
+  char *tokens;           // list of tokens that describe the pattern
+  void * (*f) (void *,pCodeWildBlock *);
+} pcPattern;
+
+static pcPattern pcpArr[] = {
+  {PCP_LABEL,     pcpat_label,      NULL},
+  {PCP_WILDSTR,   pcpat_wildString, NULL},
+  {PCP_STR,       pcpat_string,     NULL},
+  {PCP_WILDVAR,   pcpat_wildVar,    NULL},
+  {PCP_COMMA,     pcpat_comma,      NULL},
+  {PCP_COMMENT,   pcpat_comment,    NULL},
+  {PCP_NUMBER,    pcpat_number,     NULL}
+};
+
+#define PCPATTERNS (sizeof(pcpArr)/sizeof(pcPattern))
+
+// Assembly Line Token
+typedef enum {
+  ALT_LABEL=1,
+  ALT_COMMENT,
+  ALT_MNEM0,
+  ALT_MNEM0A,
+  ALT_MNEM1,
+  ALT_MNEM1A,
+  ALT_MNEM1B,
+  ALT_MNEM2,
+  ALT_MNEM2A,
+  ALT_MNEM3
+} altPatterns;
+
+static char alt_comment[]   = { PCP_COMMENT, 0};
+static char alt_label[]     = { PCP_LABEL, 0};
+static char alt_mnem0[]     = { PCP_STR, 0};
+static char alt_mnem0a[]    = { PCP_WILDVAR, 0};
+static char alt_mnem1[]     = { PCP_STR, PCP_STR, 0};
+static char alt_mnem1a[]    = { PCP_STR, PCP_WILDVAR, 0};
+static char alt_mnem1b[]    = { PCP_STR, PCP_NUMBER, 0};
+static char alt_mnem2[]     = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
+static char alt_mnem2a[]    = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
+static char alt_mnem3[]     = { PCP_STR, PCP_STR, PCP_COMMA, PCP_NUMBER, 0};
+
+static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb);
+static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb);
+static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb);
+static void * cvt_altpat_mnem0a(void *pp,pCodeWildBlock *pcwb);
+static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb);
+static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb);
+static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb);
+static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb);
+static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb);
+static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb);
+
+static pcPattern altArr[] = {
+  {ALT_LABEL,        alt_label,  cvt_altpat_label},
+  {ALT_COMMENT,      alt_comment,cvt_altpat_comment},
+  {ALT_MNEM3,        alt_mnem3,  cvt_altpat_mnem3},
+  {ALT_MNEM2A,       alt_mnem2a, cvt_altpat_mnem2a},
+  {ALT_MNEM2,        alt_mnem2,  cvt_altpat_mnem2},
+  {ALT_MNEM1B,       alt_mnem1b, cvt_altpat_mnem1b},
+  {ALT_MNEM1A,       alt_mnem1a, cvt_altpat_mnem1a},
+  {ALT_MNEM1,        alt_mnem1,  cvt_altpat_mnem1},
+  {ALT_MNEM0A,       alt_mnem0a, cvt_altpat_mnem0a},
+  {ALT_MNEM0,        alt_mnem0,  cvt_altpat_mnem0},
+
+};
+
+#define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
+
+// forward declarations
+static void * DLL_append(_DLL *list, _DLL *next);
+
+/*-----------------------------------------------------------------*/
+/* cvt_extract_destination - helper function extracts the register */
+/*                           destination from a parsedPattern.     */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static int cvt_extract_destination(parsedPattern *pp)
+{
+
+  if(pp->pct[0].tt == PCT_STRING) {
+
+    // just check first letter for now
+
+    if(toupper(*pp->pct[0].tok.s) == 'F')
+      return 1;
+
+  } else if (pp->pct[0].tt == PCT_NUMBER) {
+
+    if(pp->pct[0].tok.n)
+      return 1;
+  }
+
+  return 0;
+
+}
+
+/*-----------------------------------------------------------------*/
+/*  pCodeOp *cvt_extract_status(char *reg, char *bit)              */
+/*     if *reg is the "status" register and *bit is one of the     */
+/*     status bits, then this function will create a new pCode op  */
+/*     containing the status register.                             */
+/*-----------------------------------------------------------------*/
+
+static pCodeOp *cvt_extract_status(char *reg, char *bit)
+{
+  int len;
+
+  if(STRCASECMP(reg, pic16_pc_status.pcop.name))
+    return NULL;
+
+  len = strlen(bit);
+
+  if(len == 1) {
+    // check C,Z
+    if(toupper(*bit) == 'C')
+      return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_C_BIT));
+    if(toupper(*bit) == 'Z')
+      return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_Z_BIT));
+  }
+
+  // Check DC
+  if(len ==2 && toupper(bit[0]) == 'D' && toupper(bit[1]) == 'C')
+    return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_DC_BIT));
+
+  return NULL;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_label - convert assembly line type to a pCode label  */
+/* INPUT: pointer to the parsedPattern                             */
+/*                                                                 */
+/*  pp[0] - label                                                  */
+/*                                                                 */
+/* label pattern => '%' number ':'                                 */
+/* at this point, we wish to extract only the 'number'             */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb)
+{
+  parsedPattern *p = pp;
+
+  DFPRINTF((stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n));
+  return pic16_newpCodeLabel(NULL,-p->pct[1].tok.n);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_comment - convert assembly line type to a comment    */
+/* INPUT: pointer to the parsedPattern                             */
+/*                                                                 */
+/*  pp[0] - comment                                                */
+/*                                                                 */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb)
+{
+  parsedPattern *p = pp;
+
+  DFPRINTF((stderr,"altpat_comment  = %s\n",p->pct[0].tok.s));
+  return pic16_newpCodeCharP(p->pct[0].tok.s);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_mem0  - convert assembly line type to a wild pCode   */
+/*                    instruction                                  */
+/*                                                                 */
+/*  pp[0] - str                                                    */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb)
+{
+  parsedPattern *p = pp;
+  int opcode;
+
+  pCodeInstruction *pci=NULL;
+
+  DFPRINTF((stderr,"altpat_mnem0 %s\n",  p->pct[0].tok.s));
+
+  opcode = pic16_getpCode(p->pct[0].tok.s,0);
+
+  if(opcode < 0) {
+    /* look for special command strings like _NOTBITSKIP_ */
+
+    //fprintf(stderr, "Bad mnemonic\n");
+
+    opcode  = pic16_getpCodePeepCommand(p->pct[0].tok.s);
+    //if(opcode > 0)
+    //  fprintf(stderr,"  but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
+    return NULL;
+  }
+
+  pci = PCI(pic16_newpCode(opcode, NULL));
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+
+  return pci;
+}
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_mem0a - convert assembly line type to a wild pCode   */
+/*                    instruction                                  */
+/*                                                                 */
+/*  pp[0] - wild var                                               */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_mnem0a(void *pp, pCodeWildBlock *pcwb)
+{
+  parsedPattern *p = pp;
+
+  DFPRINTF((stderr,"altpat_mnem0a wild mnem # %d\n",  p[0].pct[1].tok.n));
+
+  /* Save the index of the maximum wildcard mnemonic */
+
+  //if(p[0].pct[1].tok.n > sMaxWildVar)
+  //  sMaxWildMnem = p[0].pct[1].tok.n;
+
+  if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
+    pcwb->nwildpCodes = p[0].pct[1].tok.n;
+
+  return pic16_newpCodeWild(p[0].pct[1].tok.n,NULL,NULL);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_mem1 - convert assembly line type to a pCode         */
+/*                   instruction with 1 operand.                   */
+/*                                                                 */
+/*  pp[0] - mnem                                                   */
+/*  pp[1] - Operand                                                */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb)
+{
+
+  parsedPattern *p = pp;
+  int opcode;
+
+  pCodeInstruction *pci=NULL;
+  pCodeOp *pcosubtype;
+
+  DFPRINTF((stderr,"altpat_mnem1 %s var %s\n",  p->pct[0].tok.s,p[1].pct[0].tok.s));
+
+  opcode = pic16_getpCode(p->pct[0].tok.s,0);
+  if(opcode < 0) {
+    //fprintf(stderr, "Bad mnemonic\n");
+    opcode  = pic16_getpCodePeepCommand(p->pct[0].tok.s);
+    //if(opcode > 0)
+    //fprintf(stderr,"  but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
+
+    return NULL;
+  }
+
+  if(pic16Mnemonics[opcode]->isBitInst)
+    pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
+  else
+    pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
+
+
+  pci = PCI(pic16_newpCode(opcode, pcosubtype));
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+
+  return pci;
+}
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_mem1a - convert assembly line type to a pCode        */
+/*                    instruction with 1 wild operand.             */
+/*                                                                 */
+/*  pp[0] - mnem                                                   */
+/*  pp[1] - wild var                                               */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb)
+{
+  parsedPattern *p = pp;
+  int opcode;
+
+  pCodeInstruction *pci=NULL;
+  pCodeOp *pcosubtype;
+
+  DFPRINTF((stderr,"altpat_mnem1a %s var %d\n",  p->pct[0].tok.s,p[1].pct[1].tok.n));
+
+  opcode = pic16_getpCode(p->pct[0].tok.s,0);
+  if(opcode < 0) {
+    int cmd_id = pic16_getpCodePeepCommand(p->pct[0].tok.s);
+    pCode *pc=NULL;
+
+    if(cmd_id<0) {
+      fprintf(stderr, "Bad mnemonic\n");
+      return NULL;
+    }
+
+    if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
+      pcwb->nwildpCodes = p[0].pct[1].tok.n;
+
+    pc =  pic16_newpCodeWild(p[1].pct[1].tok.n,NULL,NULL);
+
+    switch(cmd_id) {
+    case NOTBITSKIP:
+      PCW(pc)->mustNotBeBitSkipInst = 1;
+      break;
+    case BITSKIP:
+      PCW(pc)->mustBeBitSkipInst = 1;
+      break;
+    case INVERTBITSKIP:
+      PCW(pc)->invertBitSkipInst = 1;
+    }
+    return pc;
+  }
+
+  if(pic16Mnemonics[opcode]->isBitInst)
+    pcosubtype = pic16_newpCodeOpBit(NULL,-1,0);
+  else
+    pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
+
+
+  pci = PCI(pic16_newpCode(opcode,
+                    pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
+
+  /* Save the index of the maximum wildcard variable */
+  //if(p[1].pct[1].tok.n > sMaxWildVar)
+  //  sMaxWildVar = p[1].pct[1].tok.n;
+
+  if(p[1].pct[1].tok.n > pcwb->nvars)
+    pcwb->nvars = p[1].pct[1].tok.n;
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+
+  return pci;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb)
+{
+  parsedPattern *p = pp;
+  int opcode;
+
+  pCodeInstruction *pci=NULL;
+
+  DFPRINTF((stderr,"altpat_mnem1b %s var %d\n",  p->pct[0].tok.s,p[1].pct[0].tok.n));
+
+  opcode = pic16_getpCode(p->pct[0].tok.s,0);
+  if(opcode < 0) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
+
+  pci = PCI(pic16_newpCode(opcode, pic16_newpCodeOpLit(p[1].pct[0].tok.n) ));
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+
+  return pci;
+}
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_mnem2                                                */
+/*                                                                 */
+/*  pp[0] - mnem                                                   */
+/*  pp[1] - var                                                    */
+/*  pp[2] - comma                                                  */
+/*  pp[3] - destination                                            */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb)
+{
+  parsedPattern *p = pp;
+  int opcode;
+  int dest;
+
+  pCodeInstruction *pci=NULL;
+  pCodeOp *pcosubtype;
+
+  dest = cvt_extract_destination(&p[3]);
+
+  DFPRINTF((stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
+         p->pct[0].tok.s,
+         p[1].pct[0].tok.s,
+         p[3].pct[0].tok.s,
+         dest));
+
+
+  opcode = pic16_getpCode(p->pct[0].tok.s,dest);
+  if(opcode < 0) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
+
+  if(pic16Mnemonics[opcode]->isBitInst) {
+    pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
+    if(pcosubtype == NULL) {
+      fprintf(stderr, "bad operand?\n");
+      return NULL;
+    }
+      
+  } else
+    pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
+
+
+  pci = PCI(pic16_newpCode(opcode,pcosubtype));
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+  return pci;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_mem2a - convert assembly line type to a pCode        */
+/*                    instruction with 1 wild operand and a        */
+/*                    destination operand (e.g. w or f)            */
+/*                                                                 */
+/*  pp[0] - mnem                                                   */
+/*  pp[1] - wild var                                               */
+/*  pp[2] - comma                                                  */
+/*  pp[3] - destination                                            */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
+{
+  parsedPattern *p = pp;
+  int opcode;
+  int dest;
+
+  pCodeInstruction *pci=NULL;
+  pCodeOp *pcosubtype;
+
+  if(!pcwb) {
+    fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
+    return NULL;
+  }
+
+  dest = cvt_extract_destination(&p[3]);
+
+  DFPRINTF((stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
+         p->pct[0].tok.s,
+         p[1].pct[1].tok.n,
+         p[3].pct[0].tok.s,
+         dest));
+
+
+  opcode = pic16_getpCode(p->pct[0].tok.s,dest);
+  if(opcode < 0) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
+
+  if(pic16Mnemonics[opcode]->isBitInst)
+    pcosubtype = pic16_newpCodeOp(NULL,PO_BIT);
+  else
+    pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
+
+
+  pci = PCI(pic16_newpCode(opcode,
+                    pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
+
+  /* Save the index of the maximum wildcard variable */
+  //if(p[1].pct[1].tok.n > sMaxWildVar)
+  //  sMaxWildVar = p[1].pct[1].tok.n;
+
+  if(p[1].pct[1].tok.n > pcwb->nvars)
+    pcwb->nvars = p[1].pct[1].tok.n;
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+  return pci;
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_mem3 -  convert assembly line type to a pCode        */
+/*                    This rule is for bsf/bcf type instructions   */
+/*                                                                 */
+/*                                                                 */
+/*  pp[0] - mnem                                                   */
+/*  pp[1] - register                                               */
+/*  pp[2] - comma                                                  */
+/*  pp[3] - number                                                 */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb)
+{
+  parsedPattern *p = pp;
+  int opcode;
+  int dest;  // or could be bit position in the register
+
+  pCodeInstruction *pci=NULL;
+  pCodeOp *pcosubtype=NULL;
+
+  dest = cvt_extract_destination(&p[3]);
+
+  DFPRINTF((stderr,"altpat_mnem3 %s var %s bit (%d)\n",
+         p->pct[0].tok.s,
+         p[1].pct[0].tok.s,
+         p[3].pct[0].tok.n));
+
+
+  opcode = pic16_getpCode(p->pct[0].tok.s,0);
+  if(opcode < 0) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
+
+
+  if(pic16Mnemonics[opcode]->isBitInst) {
+    //pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
+
+    //if(pcosubtype == NULL) {
+    pcosubtype = pic16_newpCodeOpBit(p[1].pct[0].tok.s,p[3].pct[0].tok.n,0);
+    //}
+  } else
+    pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
+
+  if(pcosubtype == NULL) {
+    fprintf(stderr, "Bad operand\n");
+    return NULL;
+  }
+
+  pci = PCI(pic16_newpCode(opcode, pcosubtype));
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+  return pci;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* tokenizeLineNode - Convert a string (of char's) that was parsed */
+/*                    by SDCCpeeph.c into a string of tokens.      */
+/*                                                                 */
+/*                                                                 */
+/* The tokenizer is of the classic type. When an item is encounterd*/
+/* it is converted into a token. The token is a structure that     */
+/* encodes the item's type and it's value (when appropriate).      */
+/*                                                                 */
+/* Accepted token types:                                           */
+/*    SPACE  NUMBER STRING  %  : ,  ;                              */
+/*                                                                 */
+/*                                                                 */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
+
+static void tokenizeLineNode(char *ln)
+{
+  char *lnstart=ln;
+  tokIdx = 0;               // Starting off at the beginning
+  tokArr[0].tt = PCT_NULL;  // and assume invalid character for first token.
+
+  if(!ln || !*ln)
+    return;
+
+
+  while(*ln) {
+
+    if(isspace(*ln)) {
+      // add a SPACE token and eat the extra spaces.
+      tokArr[tokIdx++].tt = PCT_SPACE;
+      while (isspace (*ln))
+       ln++;
+      continue;
+    }
+
+    if(isdigit(*ln)) {
+
+      tokArr[tokIdx].tt = PCT_NUMBER;
+      tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
+
+      continue;
+
+    }
+
+    switch(*ln) {
+    case '%':
+      tokArr[tokIdx++].tt = PCT_PERCENT;
+      break;
+    case '<':
+      tokArr[tokIdx++].tt = PCT_LESSTHAN;
+      break;
+    case '>':
+      tokArr[tokIdx++].tt = PCT_GREATERTHAN;
+      break;
+    case ':':
+      tokArr[tokIdx++].tt = PCT_COLON;
+      break;
+    case ';':
+      tokArr[tokIdx].tok.s = Safe_strdup(ln);
+      tokArr[tokIdx++].tt = PCT_COMMENT;
+      tokArr[tokIdx].tt = PCT_NULL;
+      return;
+    case ',':
+      tokArr[tokIdx++].tt = PCT_COMMA;
+      break;
+
+
+    default:
+      if(isalpha(*ln) || (*ln == '_') ) {
+       char buffer[50];
+       int i=0;
+
+       while( (isalpha(*ln)  ||  isdigit(*ln) || (*ln == '_')) && i<49)
+         buffer[i++] = *ln++;
+
+       ln--;
+       buffer[i] = 0;
+
+       tokArr[tokIdx].tok.s = Safe_strdup(buffer);
+       tokArr[tokIdx++].tt = PCT_STRING;
+
+      } else {
+       fprintf(stderr, "Error while parsing peep rules (check peeph.def)\n");
+       fprintf(stderr, "Line: %s\n",lnstart);
+       fprintf(stderr, "Token: '%c'\n",*ln);
+       exit(1);
+      }
+    }
+
+    /* Advance to next character in input string .
+     * Note, if none of the tests passed above, then 
+     * we effectively ignore the `bad' character.
+     * Since the line has already been parsed by SDCCpeeph,
+     * chance are that there are no invalid characters... */
+
+    ln++;
+
+  }
+
+  tokArr[tokIdx].tt = 0;
+}
+
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+
+
+
+static void dump1Token(pCodeTokens tt)
+{
+
+  switch(tt) {
+  case PCT_SPACE:
+    fprintf(stderr, " space ");
+    break;
+  case PCT_PERCENT:
+    fprintf(stderr, " pct %%");
+    break;
+  case PCT_LESSTHAN:
+    fprintf(stderr, " pct <");
+    break;
+  case PCT_GREATERTHAN:
+    fprintf(stderr, " pct >");
+    break;
+  case PCT_COLON:
+    fprintf(stderr, " col :");
+    break;
+  case PCT_COMMA:
+    fprintf(stderr, " comma , ");
+    break;
+  case PCT_COMMENT:
+    fprintf(stderr, " comment ");
+    //fprintf(stderr,"%s",tokArr[i].tok.s);
+    break;
+  case PCT_STRING:
+    fprintf(stderr, " str ");
+    //fprintf(stderr,"%s",tokArr[i].tok.s);
+    break;
+  case PCT_NUMBER:
+    fprintf(stderr, " num ");
+    //fprintf(stderr,"%d",tokArr[i].tok.n);
+    break;
+  case PCT_NULL:
+    fprintf(stderr, " null ");
+
+  }
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+
+static int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
+{
+  int i=0;
+
+  if(!pct || !pat || !*pat)
+    return 0;
+
+  //DFPRINTF((stderr,"comparing against:\n"));
+
+  while(i < max_tokens) {
+
+    if(*pat == 0){
+      //DFPRINTF((stderr,"matched\n"));
+      return (i+1);
+    }
+
+    //dump1Token(*pat); DFPRINTF((stderr,"\n"));
+
+    if(pct->tt != *pat) 
+      return 0;
+
+
+    pct++;
+    pat++;
+  }
+
+  return 0;
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+
+static int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
+{
+  int i=0;
+  
+  if(!pct || !pat || !*pct)
+    return 0;
+
+
+  while(i < max_tokens) {
+
+    if(*pct == 0) {
+      //DFPRINTF((stderr,"matched\n"));
+      return i;
+    }
+
+    //dump1Token(*pat); DFPRINTF((stderr,"\n"));
+
+    if( !pat || !pat->pcp )
+      return 0;
+
+    if (pat->pcp->pt != *pct)  
+      return 0;
+
+    //DFPRINTF((stderr," pct=%d\n",*pct));
+    pct++;
+    pat++;
+    i++;
+  }
+
+  return 0;
+
+}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+
+static int advTokIdx(int *v, int amt)
+{
+
+  if((unsigned) (*v + amt) > tokIdx)
+    return 1;
+
+  *v += amt;
+  return 0;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* parseTokens - convert the tokens corresponding to a single line */
+/*               of a peep hole assembly into a pCode object.      */
+/*                                                                 */
+/*                                                                 */
+/*                                                                 */
+/*                                                                 */
+/* This is a simple parser that looks for strings of the type      */
+/* allowed in the peep hole definition file. Essentially the format*/
+/* is the same as a line of assembly:                              */
+/*                                                                 */
+/*  label:    mnemonic   op1, op2, op3    ; comment                */
+/*                                                                 */
+/* Some of these items aren't present. It's the job of the parser  */
+/* to determine which are and convert those into the appropriate   */
+/* pcode.                                                          */
+/*-----------------------------------------------------------------*/
+
+static int parseTokens(pCodeWildBlock *pcwb, pCode **pcret)
+{
+  pCode *pc;
+  int error = 0;
+
+  if(!tokIdx)
+    return error;
+
+#ifdef PCODE_DEBUG
+  {
+    unsigned i;
+    for(i=0; i<=tokIdx; i++)
+      dump1Token(tokArr[i].tt);
+    fputc('\n',stderr);
+  }
+#endif
+
+  {
+    int lparsedPatIdx=0;
+    int lpcpIdx;
+    int ltokIdx =0;
+    int matching = 0;
+    int j=0;
+    int k=0;
+
+    char * cPmnem  = NULL;     // Pointer to non-wild mnemonic (if any)
+    char * cP1stop = NULL;
+    char * cP2ndop = NULL;
+
+    //pCodeOp *pcl   = NULL;       // Storage for a label
+    //pCodeOp *pco1  = NULL;       // 1st operand
+    //pCodeOp *pco2  = NULL;       // 2nd operand
+    //pCode   *pc    = NULL;       // Mnemonic
+
+    typedef enum {
+      PS_START,
+      PS_HAVE_LABEL,
+      PS_HAVE_MNEM,
+      PS_HAVE_1OPERAND,
+      PS_HAVE_COMMA,
+      PS_HAVE_2OPERANDS
+    } ParseStates;
+
+    ParseStates state = PS_START;
+
+    do {
+
+      lpcpIdx=0;
+      matching = 0;
+
+      if(  ((tokArr[ltokIdx].tt == PCT_SPACE) )
+          && (advTokIdx(&ltokIdx, 1)) ) // eat space
+       break;
+
+      do {
+       j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
+       if( j ) {
+
+         switch(pcpArr[lpcpIdx].pt) {
+         case  PCP_LABEL:
+           if(state == PS_START){
+             DFPRINTF((stderr,"  label\n"));
+             state = PS_HAVE_LABEL;
+           } else 
+             DFPRINTF((stderr,"  bad state (%d) for label\n",state));
+           break;
+
+         case  PCP_STR:
+           DFPRINTF((stderr,"  %s is",tokArr[ltokIdx].tok.s));
+           switch(state) {
+           case PS_START:
+           case PS_HAVE_LABEL:
+             DFPRINTF((stderr,"  mnem\n"));
+             cPmnem = tokArr[ltokIdx].tok.s;
+             state = PS_HAVE_MNEM;
+             break;
+           case PS_HAVE_MNEM:
+             DFPRINTF((stderr,"  1st operand\n"));
+             cP1stop = tokArr[ltokIdx].tok.s;
+             //pco1 = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
+             state = PS_HAVE_1OPERAND;
+             break;
+           case PS_HAVE_1OPERAND:
+             DFPRINTF((stderr,"  error expecting comma\n"));
+             break;
+           case PS_HAVE_COMMA:
+             DFPRINTF((stderr,"  2 operands\n"));
+             cP2ndop = tokArr[ltokIdx].tok.s;
+             break;
+           case PS_HAVE_2OPERANDS:
+             break;
+           }
+           break;
+
+         case  PCP_WILDVAR:
+           switch(state) {
+           case PS_START:
+           case PS_HAVE_LABEL:
+             DFPRINTF((stderr,"  wild mnem\n"));
+             state = PS_HAVE_MNEM;
+             break;
+           case PS_HAVE_MNEM:
+             DFPRINTF((stderr,"  1st operand is wild\n"));
+             state = PS_HAVE_1OPERAND;
+             break;
+           case PS_HAVE_1OPERAND:
+             DFPRINTF((stderr,"  error expecting comma\n"));
+             break;
+           case PS_HAVE_COMMA:
+             DFPRINTF((stderr,"  2nd operand is wild\n"));
+             break;
+           case PS_HAVE_2OPERANDS:
+             break;
+           }
+           break;
+
+         case  PCP_NUMBER:
+           switch(state) {
+           case PS_START:
+           case PS_HAVE_LABEL:
+             fprintf(stderr,"  ERROR number\n");
+             break;
+           case PS_HAVE_MNEM:
+             DFPRINTF((stderr,"  1st operand is a number\n"));
+             state = PS_HAVE_1OPERAND;
+             break;
+           case PS_HAVE_1OPERAND:
+             fprintf(stderr,"  error expecting comma\n");
+             break;
+           case PS_HAVE_COMMA:
+             DFPRINTF((stderr,"  2nd operand is a number\n"));
+             break;
+           case PS_HAVE_2OPERANDS:
+             break;
+           }
+           break;
+
+         case  PCP_WILDSTR:
+           break;
+         case  PCP_COMMA:
+           if(state == PS_HAVE_1OPERAND){
+             DFPRINTF((stderr,"  got a comma\n"));
+             state = PS_HAVE_COMMA;
+           } else
+             fprintf(stderr,"  unexpected comma\n");
+           break;
+
+         }
+
+         matching = 1;
+         parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
+         parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
+         lparsedPatIdx++;
+
+         //dump1Token(tokArr[ltokIdx].tt);
+
+         if(advTokIdx(&ltokIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
+           DFPRINTF((stderr," reached end \n"));
+           matching = 0;
+           //return;
+         }
+       }
+
+
+      } while ((++lpcpIdx < PCPATTERNS) && !matching);
+
+    } while (matching);
+
+    parsedPatArr[lparsedPatIdx].pcp = NULL;
+    parsedPatArr[lparsedPatIdx].pct = NULL;
+
+    j=k=0;
+    do {
+      int c;
+
+      if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
+
+       if( altArr[k].f) {
+         pc = altArr[k].f(&parsedPatArr[j],pcwb);
+         //if(pc && pc->print)
+         //  pc->print(stderr,pc);
+         //if(pc && pc->destruct) pc->destruct(pc); dumps core?
+
+         //if(curBlock && pc)
+         //pic16_addpCode2pBlock(curBlock, pc);
+         if(pc) {
+           if (pcret) {
+             *pcret = pc;
+             return 0;       // Only accept one line for now.
+           } else
+             pic16_addpCode2pBlock(pcwb->pb, pc);
+         } else
+           error++;
+       }
+       j += c;
+      }
+      k++;
+    }
+    while(j<=lparsedPatIdx && k<ALTPATTERNS);
+
+/*
+    DFPRINTF((stderr,"\nConverting parsed line to pCode:\n\n"));
+
+    j = 0;
+    do {
+      if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
+       parsedPatArr[j].pcp->f(&parsedPatArr[j]);
+      DFPRINTF((stderr,"  %d",parsedPatArr[j].pcp->pt));
+      j++;
+    }
+    while(j<lparsedPatIdx);
+*/
+    DFPRINTF((stderr,"\n"));
+
+  }
+
+  return error;
+}
+
+/*-----------------------------------------------------------------*/
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void  peepRuleBlock2pCodeBlock(  lineNode *ln, pCodeWildBlock *pcwb)
+{
+
+  if(!ln)
+    return;
+
+  for( ; ln; ln = ln->next) {
+
+    //DFPRINTF((stderr,"%s\n",ln->line));
+
+    tokenizeLineNode(ln->line);
+    
+    if(parseTokens(pcwb,NULL)) {
+      int i;
+      fprintf(stderr,"ERROR assembling line:\n%s\n",ln->line);
+      fprintf(stderr,"Tokens:\n");
+      for(i=0; i<5; i++)
+       dump1Token(tokArr[i].tt);
+      fputc('\n',stderr);
+      exit (1);
+    }
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+pCode *pic16_AssembleLine(char *line)
+{
+  pCode *pc=NULL;
+
+  if(!line || !*line) {
+    fprintf(stderr,"WARNING returning NULL in AssembleLine\n");
+    return NULL;
+  }
+
+  tokenizeLineNode(line);
+    
+  if(parseTokens(NULL,&pc))
+    fprintf(stderr, "WARNING: unable to assemble line:\n%s\n",line);
+
+  return pc;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* peepRuleCondition                                               */
+/*-----------------------------------------------------------------*/
+static void   peepRuleCondition(char *cond, pCodePeep *pcp)
+{
+  if(!cond || !pcp)
+    return;
+
+  //DFPRINTF((stderr,"\nCondition:  %s\n",cond));
+  /* brute force compares for now */
+
+  if(STRCASECMP(cond, "NZ") == 0) {
+    //DFPRINTF((stderr,"found NZ\n"));
+    pcp->postFalseCond = PCC_Z;
+
+  }
+
+}
+
+
+static void initpCodeWildBlock(pCodeWildBlock *pcwb)
+{
+  
+  //  pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
+
+  if(!pcwb)
+    return;
+
+  pcwb->vars = NULL; 
+  pcwb->wildpCodes = NULL;
+  pcwb->wildpCodeOps = NULL;
+
+  pcwb->nvars = 0; 
+  pcwb->nwildpCodes = 0;
+  pcwb->nops = 0;
+
+}
+
+static void postinit_pCodeWildBlock(pCodeWildBlock *pcwb)
+{
+  
+  if(!pcwb)
+    return;
+
+  pcwb->nvars+=2;
+  pcwb->nops = pcwb->nvars;
+
+  pcwb->vars = Safe_calloc(pcwb->nvars, sizeof(char *));
+  pcwb->wildpCodeOps = Safe_calloc(pcwb->nvars, sizeof(pCodeOp *));
+
+  pcwb->nwildpCodes+=2;
+  pcwb->wildpCodes = Safe_calloc(pcwb->nwildpCodes, sizeof(pCode *));
+
+}
+
+static void initpCodePeep(pCodePeep *pcp)
+{
+  
+  //  pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
+
+  if(!pcp)
+    return;
+
+  initpCodeWildBlock(&pcp->target);
+  pcp->target.pb = pic16_newpCodeChain(NULL, 'W', NULL);
+
+  initpCodeWildBlock(&pcp->replace);
+  pcp->replace.pb = pic16_newpCodeChain(NULL, 'W', NULL);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
+/*                   pCode.                                        */
+/*                                                                 */
+/* SDCCpeeph parses the peep rules file and extracts variables,    */
+/* removes white space, and checks the syntax. This function       */
+/* extends that processing to produce pCode objects. You can kind  */
+/* think of this function as an "assembler", though instead of     */
+/* taking raw text to produce machine code, it produces pCode.     */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+extern void pic16initpCodePeepCommands(void);
+
+void  pic16_peepRules2pCode(peepRule *rules)
+{
+  peepRule *pr;
+
+  pCodePeep *currentRule;
+  pCodePeepSnippets *pcps;
+
+  pic16initpCodePeepCommands();
+
+  /* The rules are in a linked-list. Each rule has two portions */
+  /* There's the `target' and there's the `replace'. The target */
+  /* is compared against the SDCC generated code and if it      */
+  /* matches, it gets replaced by the `replace' block of code.  */
+  /*                                                            */
+  /* Here we loop through each rule and convert the target's and*/
+  /* replace's into pCode target and replace blocks             */
+
+  for (pr = rules; pr; pr = pr->next) {
+
+    //DFPRINTF((stderr,"\nRule:\n\n"));
+
+    pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
+    peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
+
+    currentRule = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
+    initpCodePeep(currentRule);
+
+    /* Convert the target block */
+    peepRuleBlock2pCodeBlock(pr->match, &currentRule->target);
+
+    //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
+    //pic16_printpBlock(stderr, currentRule->target.pb);
+
+    //DFPRINTF((stderr,"target with labels merged:\n"));
+    //pic16_pBlockMergeLabels(curBlock);
+    pic16_pBlockMergeLabels(currentRule->target.pb);
+    //pic16_printpBlock(stderr, currentRule->replace.pb);
+
+    //#ifdef PCODE_DEBUG
+    //    pic16_printpBlock(stderr, curBlock);
+    //#endif
+    //DFPRINTF((stderr,"\nReplaced by:\n"));
+
+
+    /* Convert the replace block */
+    peepRuleBlock2pCodeBlock(pr->replace, &currentRule->replace);
+
+    //DFPRINTF((stderr,"finished replace block, here it is in pcode form:\n"));
+    //pic16_printpBlock(stderr, curBlock);
+
+    //DFPRINTF((stderr,"replace with labels merged:\n"));
+
+    pic16_pBlockMergeLabels(currentRule->replace.pb);
+    //pic16_printpBlock(stderr, currentRule->replace.pb);
+
+    peepRuleCondition(pr->cond,currentRule);
+
+    /* The rule has been converted to pCode. Now allocate
+     * space for the wildcards */
+    
+    postinit_pCodeWildBlock(&currentRule->target);
+    postinit_pCodeWildBlock(&currentRule->replace);
+
+    //return; // debug ... don't want to go through all the rules yet
+  }
+
+  {
+    pCodePeep *peepBlock;
+    _DLL *peeprules;
+
+    peeprules = (_DLL *)peepSnippets;
+    //fprintf(stderr,"target rules\n");
+    while(peeprules) {
+      //fprintf(stderr,"   rule:\n");
+      peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
+      //pic16_printpBlock(stderr, peepBlock->target.pb);
+      peeprules = peeprules->next;
+    }
+    //fprintf(stderr," ... done\n");
+  }
+
+}
+
+static void printpCodeString(FILE *of, pCode *pc, int max)
+{
+  int i=0;
+
+  while(pc && (i++<max)) {
+    pc->print(of,pc);
+    pc = pc->next;
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* _DLL * DLL_append                                               */
+/*                                                                 */ 
+/*  Append a _DLL object to the end of a _DLL (doubly linked list) */ 
+/* If The list to which we want to append is non-existant then one */ 
+/* is created. Other wise, the end of the list is sought out and   */ 
+/* a new DLL object is appended to it. In either case, the void    */
+/* *data is added to the newly created DLL object.                 */
+/*-----------------------------------------------------------------*/
+
+static void * DLL_append(_DLL *list, _DLL *next)
+{
+  _DLL *b;
+
+
+  /* If there's no list, then create one: */
+  if(!list) {
+    next->next = next->prev = NULL;
+    return next;
+  }
+
+
+  /* Search for the end of the list. */
+  b = list;
+  while(b->next)
+    b = b->next;
+
+  /* Now append the new DLL object */
+  b->next = next;
+  b->next->prev = b;
+  b = b->next; 
+  b->next = NULL;
+
+  return list;
+  
+}  
+
+
+/*-----------------------------------------------------------------
+
+  pCode peephole optimization
+
+
+  The pCode "peep hole" optimization is not too unlike the peep hole
+  optimization in SDCCpeeph.c. The major difference is that here we
+  use pCode's whereas there we use ASCII strings. The advantage with
+  pCode's is that we can ascertain flow information in the instructions
+  being optimized.
+
+
+<FIX ME> - elaborate...
+
+  -----------------------------------------------------------------*/
+
+
+
+/*-----------------------------------------------------------------*/
+/* pCodeSearchCondition - Search a pCode chain for a 'condition'   */
+/*                                                                 */
+/* return conditions                                               */
+/*  1 - The Condition was found for a pCode's input                */
+/*  0 - No matching condition was found for the whole chain        */
+/* -1 - The Condition was found for a pCode's output               */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+int pic16_pCodeSearchCondition(pCode *pc, unsigned int cond)
+{
+  //fprintf(stderr,"Checking conditions %d\n",cond);
+  while(pc) {
+
+    /* If we reach a function end (presumably an end since we most
+       probably began the search in the middle of a function), then
+       the condition was not found. */
+    if(pc->type == PC_FUNCTION)
+      return 0;
+
+    if(pc->type == PC_OPCODE) {
+      //fprintf(stderr," checking conditions of: ");
+      //pc->print(stderr,pc);
+      //fprintf(stderr,"\t\tinCond=%d\toutCond=%d\n",PCI(pc)->inCond,PCI(pc)->outCond);
+      if(PCI(pc)->inCond & cond)
+       return 1;
+      if(PCI(pc)->outCond & cond)
+       return -1;
+    }
+
+    pc = pc->next;
+  }
+
+  return 0;
+}
+
+/*-----------------------------------------------------------------
+ * int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
+ *
+ * Compare two pCodeOp's and return 1 if they're the same
+ *-----------------------------------------------------------------*/
+static int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
+{
+  char b[50], *n2;
+
+  if(!pcops || !pcopd)
+    return 0;
+/*
+  fprintf(stderr," Comparing operands %s",
+         pic16_get_op( pcops,NULL,0));
+
+  fprintf(stderr," to %s\n",
+         pic16_get_op( pcopd,NULL,0));
+*/
+
+  if(pcops->type != pcopd->type) {
+    //fprintf(stderr,"  - fail - diff types\n");
+    return 0;  // different types
+  }
+
+  if(pcops->type == PO_LITERAL) {
+
+    if((PCOL(pcops)->lit >= 0) && (PCOL(pcops)->lit == PCOL(pcopd)->lit))
+      return 1;
+
+    return 0;
+  }
+
+  b[0]=0;
+  pic16_get_op(pcops,b,50);
+
+  n2 = pic16_get_op(pcopd,NULL,0);
+
+  if( !n2 || strcmp(b,n2)) {
+    //fprintf(stderr,"  - fail - diff names: %s, len=%d,  %s, len=%d\n",b,strlen(b), n2, strlen(n2) );
+    return 0;  // different names
+  }
+
+  switch(pcops->type) {
+  case PO_DIR:
+    if( PCOR(pcops)->instance != PCOR(pcopd)->instance) {
+      //fprintf(stderr, "  - fail different instances\n");
+      return 0;
+    }
+    break;
+  default:
+    break;
+  }
+
+  //fprintf(stderr,"  - pass\n");
+
+  return 1;
+}
+
+static int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
+{
+  int labindex;
+
+  /* Check for a label associated with this wild pCode */
+  // If the wild card has a label, make sure the source code does too.
+  if(PCI(pcd)->label) {
+    pCode *pcl = PCI(pcd)->label->pc;
+
+#ifdef PCODE_DEBUG
+    int li = -PCL(pcl)->key;
+
+    if(peepBlock->target.vars[li] == NULL) {
+      if(PCI(pcs)->label) {
+       DFPRINTF((stderr,"first time for a label: %d %s\n",li,PCL(PCI(pcs)->label->pc)->label));
+      }
+    } else {
+      // DFPRINTF((stderr,"label id = %d \n",PCL(PCI(pcd)->label->pc)->key));
+      DFPRINTF((stderr," label id: %d %s\n",li,peepBlock->target.vars[li]));
+      if(PCI(pcs)->label) {
+       DFPRINTF((stderr," src %s\n",PCL(PCI(pcs)->label->pc)->label));
+      }
+    }
+#endif
+
+
+    if(!PCI(pcs)->label)
+      return 0;
+
+    labindex = -PCL(pcl)->key;
+    if(peepBlock->target.vars[labindex] == NULL) {
+      // First time to encounter this label
+      peepBlock->target.vars[labindex] = PCL(PCI(pcs)->label->pc)->label;
+      DFPRINTF((stderr,"first time for a label: %d %s\n",labindex,PCL(PCI(pcs)->label->pc)->label));
+
+    } else {
+      if(strcmp(peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label) != 0) {
+       DFPRINTF((stderr,"labels don't match dest %s != src %s\n",peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label));
+       return 0;
+      }
+      DFPRINTF((stderr,"matched a label %d %s -hey\n",labindex,peepBlock->target.vars[labindex]));
+    }
+  } else {
+    //DFPRINTF((stderr,"destination doesn't have a label\n"));
+
+    if(PCI(pcs)->label)
+      return 0;
+
+    //DFPRINTF((stderr,"neither src nor dest have labels\n"));
+
+  }
+
+  return 1;
+    
+}
+
+/*-----------------------------------------------------------------*/
+/* pCodePeepMatchLine - Compare source and destination pCodes to   */
+/*                      see they're the same.                      */
+/*                                                                 */
+/* In this context, "source" refers to the coded generated by gen.c*/
+/* and "destination" refers to a pcode in a peep rule. If the dest-*/
+/* ination has no wild cards, then MatchLine will compare the two  */
+/* pcodes (src and dest) for a one-to-one match. If the destination*/
+/* has wildcards, then those get expanded. When a wild card is     */
+/* encountered for the first time it autmatically is considered a  */
+/* match and the object that matches it is referenced in the       */
+/* variables or opcodes array (depending on the type of match).    */
+/*                                                                 */
+/*                                                                 */
+/* Inputs:                                                         */
+/*  *peepBlock - A pointer to the peepBlock that contains the      */
+/*               entire rule to which the destination pcode belongs*/
+/*  *pcs - a pointer to the source pcode                           */
+/*  *pcd - a pointer to the destination pcode                      */
+/*                                                                 */
+/* Returns:                                                        */
+/*  1 - pcodes match                                               */
+/*  0 - pcodes don't match                                         */
+/*                                                                 */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
+static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
+{
+  int index;   // index into wild card arrays
+
+  /* one-for-one match. Here the source and destination opcodes 
+   * are not wild. However, there may be a label or a wild operand */
+
+  if(pcs) {
+    if(PCI(pcs)->label) {
+      DFPRINTF((stderr,"Match line source label: %s\n",PCL(PCI(pcs)->label->pc)->label));
+    }
+  }
+
+  if(pcs->type == pcd->type) {
+
+    if(pcs->type == PC_OPCODE) {
+
+      /* If the opcodes don't match then the line doesn't match */
+      if(PCI(pcs)->op != PCI(pcd)->op)
+       return 0;
+
+#ifdef PCODE_DEBUG
+      DFPRINTF((stderr,"%s comparing\n",__FUNCTION__));
+      pcs->print(stderr,pcs);
+      pcd->print(stderr,pcd);
+#endif
+
+      if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
+       return 0;
+
+      /* Compare the operands */
+      if(PCI(pcd)->pcop) {
+       if (PCI(pcd)->pcop->type == PO_WILD) {
+         index = PCOW(PCI(pcd)->pcop)->id;
+         //DFPRINTF((stderr,"destination is wild\n"));
+#ifdef DEBUG_PCODEPEEP
+         if (index > peepBlock->nops) {
+           DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
+           exit(1);
+         }
+#endif
+
+         PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
+         if(!peepBlock->target.wildpCodeOps[index]) {
+           peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop;
+
+           //if(PCI(pcs)->pcop->type == PO_GPR_TEMP) 
+
+         } else {
+           /*
+             pcs->print(stderr,pcs);
+             pcd->print(stderr,pcd);
+
+             fprintf(stderr, "comparing operands of these instructions, result %d\n",
+             pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
+             );
+           */
+
+           return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
+         }
+
+         {
+           char *n;
+
+           switch(PCI(pcs)->pcop->type) {
+           case PO_GPR_TEMP:
+           case PO_FSR0:
+             //case PO_INDF0:
+             n = PCOR(PCI(pcs)->pcop)->r->name;
+
+             break;
+           default:
+             n = PCI(pcs)->pcop->name;
+           }
+
+           if(peepBlock->target.vars[index])
+             return  (strcmp(peepBlock->target.vars[index],n) == 0);
+           else {
+             DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
+             peepBlock->target.vars[index] = n;
+             return 1;
+           }
+         }
+
+       } else if (PCI(pcd)->pcop->type == PO_LITERAL) {
+         return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
+
+       }
+       /* FIXME - need an else to check the case when the destination 
+        * isn't a wild card */
+      } else
+       /* The pcd has no operand. Lines match if pcs has no operand either*/
+       return (PCI(pcs)->pcop == NULL);
+    }
+  }
+
+  /* Compare a wild instruction to a regular one. */
+
+  if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
+
+    index = PCW(pcd)->id;
+#ifdef PCODE_DEBUG
+    DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
+    pcs->print(stderr,pcs);
+    pcd->print(stderr,pcd);
+#endif
+    peepBlock->target.wildpCodes[PCW(pcd)->id] = pcs;
+
+    if(!pCodePeepMatchLabels(peepBlock, pcs, pcd)) {
+      DFPRINTF((stderr," Failing because labels don't match\n"));
+      return 0;
+    }
+
+    if(PCW(pcd)->mustBeBitSkipInst & !(PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
+      // doesn't match because the wild pcode must be a bit skip
+      DFPRINTF((stderr," Failing match because bit skip is req\n"));
+      //pcd->print(stderr,pcd);
+      //pcs->print(stderr,pcs);
+      return 0;
+    } 
+
+    if(PCW(pcd)->mustNotBeBitSkipInst & (PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
+      // doesn't match because the wild pcode must *not* be a bit skip
+      DFPRINTF((stderr," Failing match because shouldn't be bit skip\n"));
+      //pcd->print(stderr,pcd);
+      //pcs->print(stderr,pcs);
+      return 0;
+    } 
+
+    if(PCW(pcd)->operand) {
+      PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
+      if(peepBlock->target.vars[index]) {
+       int i = (strcmp(peepBlock->target.vars[index],PCI(pcs)->pcop->name) == 0);
+#ifdef PCODE_DEBUG
+
+       if(i)
+         DFPRINTF((stderr," (matched)\n"));
+       else {
+         DFPRINTF((stderr," (no match: wild card operand mismatch\n"));
+         DFPRINTF((stderr,"  peepblock= %s,  pcodeop= %s\n",
+                 peepBlock->target.vars[index],
+                 PCI(pcs)->pcop->name));
+       }
+#endif
+       return i;
+      } else {
+       DFPRINTF((stderr," (matched %s\n",PCI(pcs)->pcop->name));
+       peepBlock->target.vars[index] = PCI(pcs)->pcop->name;
+       return 1;
+      }
+    }
+
+    pcs = pic16_findNextInstruction(pcs->next); 
+    if(pcs) {
+      //DFPRINTF((stderr," (next to match)\n"));
+      //pcs->print(stderr,pcs);
+    } else if(pcd->next) {
+      /* oops, we ran out of code, but there's more to the rule */
+      return 0;
+    }
+
+    return 1; /*  wild card matches */
+  }
+
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void pCodePeepClrVars(pCodePeep *pcp)
+{
+
+  int i;
+  if(!pcp)
+    return;
+/*
+  DFPRINTF((stderr," Clearing peep rule vars\n"));
+  DFPRINTF((stderr," %d %d %d  %d %d %d\n",
+           pcp->target.nvars,pcp->target.nops,pcp->target.nwildpCodes,
+           pcp->replace.nvars,pcp->replace.nops,pcp->replace.nwildpCodes));
+*/
+  for(i=0;i<pcp->target.nvars; i++)
+    pcp->target.vars[i] = NULL;
+  for(i=0;i<pcp->target.nops; i++)
+    pcp->target.wildpCodeOps[i] = NULL;
+  for(i=0;i<pcp->target.nwildpCodes; i++)
+    pcp->target.wildpCodes[i] = NULL;
+
+  for(i=0;i<pcp->replace.nvars; i++)
+    pcp->replace.vars[i] = NULL;
+  for(i=0;i<pcp->replace.nops; i++)
+    pcp->replace.wildpCodeOps[i] = NULL;
+  for(i=0;i<pcp->replace.nwildpCodes; i++)
+    pcp->replace.wildpCodes[i] = NULL;
+
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/*  pCodeInsertAfter - splice in the pCode chain starting with pc2 */
+/*                     into the pCode chain containing pc1         */
+/*-----------------------------------------------------------------*/
+void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2)
+{
+
+  if(!pc1 || !pc2)
+    return;
+
+  pc2->next = pc1->next;
+  if(pc1->next)
+    pc1->next->prev = pc2;
+
+  pc2->pb = pc1->pb;
+  pc2->prev = pc1;
+  pc1->next = pc2;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_pCodeOpCopy - copy a pcode operator                       */
+/*-----------------------------------------------------------------*/
+pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop)
+{
+  pCodeOp *pcopnew=NULL;
+
+  if(!pcop)
+    return NULL;
+
+  switch(pcop->type) { 
+  case PO_CRY:
+  case PO_BIT:
+    //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
+    pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
+    PCORB(pcopnew)->bit = PCORB(pcop)->bit;
+    PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
+
+    break;
+
+  case PO_WILD:
+    /* Here we expand the wild card into the appropriate type: */
+    /* By recursively calling pCodeOpCopy */
+    //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
+    if(PCOW(pcop)->matched)
+      pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->matched);
+    else {
+      // Probably a label
+      pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->subtype);
+      pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
+      //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
+    }
+
+    return pcopnew;
+    break;
+
+  case PO_LABEL:
+    //DFPRINTF((stderr,"pCodeOpCopy label\n"));
+    pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
+    PCOLAB(pcopnew)->key =  PCOLAB(pcop)->key;
+    break;
+
+  case PO_IMMEDIATE:
+    pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
+    PCOI(pcopnew)->index = PCOI(pcop)->index;
+    PCOI(pcopnew)->offset = PCOI(pcop)->offset;
+    PCOI(pcopnew)->_const = PCOI(pcop)->_const;
+    break;
+
+  case PO_LITERAL:
+    //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
+    pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
+    PCOL(pcopnew)->lit = PCOL(pcop)->lit;
+    break;
+
+#if 0 // mdubuc - To add
+  case PO_REL_ADDR:
+    break;
+#endif
+
+  case PO_GPR_BIT:
+
+    pcopnew = pic16_newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
+    PCOR(pcopnew)->r = PCOR(pcop)->r;
+    PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
+    DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
+    return pcopnew;
+    break;
+
+  case PO_GPR_REGISTER:
+  case PO_GPR_TEMP:
+  case PO_FSR0:
+  case PO_INDF0:
+    //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
+    pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
+    PCOR(pcopnew)->r = PCOR(pcop)->r;
+    PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
+    PCOR(pcopnew)->instance = PCOR(pcop)->instance;
+    DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
+    break;
+
+  case PO_DIR:
+    //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
+    pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
+    PCOR(pcopnew)->r = PCOR(pcop)->r;
+    PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
+    PCOR(pcopnew)->instance = PCOR(pcop)->instance;
+    break;
+  case PO_STATUS:
+    DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
+  case PO_BSR:
+    DFPRINTF((stderr,"pCodeOpCopy PO_BSR\n"));
+  case PO_SFR_REGISTER:
+  case PO_STR:
+  case PO_NONE:
+  case PO_W:
+  case PO_WREG:
+  case PO_INTCON:
+  case PO_PCL:
+  case PO_PCLATH:
+
+    //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
+    pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
+
+  }
+
+  pcopnew->type = pcop->type;
+  if(pcop->name)
+    pcopnew->name = Safe_strdup(pcop->name);
+  else
+    pcopnew->name = NULL;
+
+  return pcopnew;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* pCodeCopy - copy a pcode                                        */
+/*-----------------------------------------------------------------*/
+static pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
+{
+  pCodeInstruction *new_pci;
+
+  if(invert)
+    new_pci = PCI(pic16_newpCode(pci->inverted_op,pci->pcop));
+  else
+    new_pci = PCI(pic16_newpCode(pci->op,pci->pcop));
+
+  new_pci->pc.pb = pci->pc.pb;
+  new_pci->from = pci->from;
+  new_pci->to   = pci->to;
+  new_pci->label = pci->label;
+  new_pci->pcflow = pci->pcflow;
+
+  return PCODE(new_pci);
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static void pCodeDeleteChain(pCode *f,pCode *t)
+{
+  pCode *pc;
+
+
+  while(f && f!=t) {
+    DFPRINTF((stderr,"delete pCode:\n"));
+    pc = f->next;
+    //f->print(stderr,f);
+    //f->delete(f);  this dumps core...
+
+    f = pc;
+
+  }
+
+}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+int pic16_pCodePeepMatchRule(pCode *pc)
+{
+  pCodePeep *peepBlock;
+  pCode *pct, *pcin;
+  pCodeCSource *pc_cline=NULL;
+  _DLL *peeprules;
+  int matched;
+
+  peeprules = (_DLL *)peepSnippets;
+
+  while(peeprules) {
+    peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
+
+    if(!peepBlock || /*!peepBlock->target ||*/ !peepBlock->target.pb->pcHead) {
+      fprintf(stderr, "skipping rule because target pb is NULL\n");
+      goto next_rule;
+    }
+
+    pCodePeepClrVars(peepBlock);
+/*
+    pcin = pc;
+    if(IS_PCCOMMENT(pcin))
+      pc = pcin = pic16_findNextInstruction(pcin->next);
+*/
+    pcin = pc = pic16_findNextInstruction(pc);
+
+    pct = peepBlock->target.pb->pcHead;
+#ifdef PCODE_DEBUG
+    {
+      pCode *pcr = peepBlock->replace.pb->pcHead;
+      if(pcr) pct->print(stderr,pcr);
+    }
+#endif
+    matched = 0;
+    while(pct && pcin) {
+
+      if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
+       break;
+
+      pcin = pic16_findNextInstruction(pcin->next);
+      pct = pct->next;
+      //debug:
+      //DFPRINTF((stderr,"    matched\n"));
+
+      if(!pcin && pct) {
+       DFPRINTF((stderr," partial match... no more code\n"));
+       fprintf(stderr," partial match... no more code\n");
+       matched = 0; 
+      }
+      if(!pct) {
+       DFPRINTF((stderr," end of rule\n"));
+      }
+    }
+
+    if(matched && pcin) {
+
+      /* So far we matched the rule up to the point of the conditions .
+       * In other words, all of the opcodes match. Now we need to see
+       * if the post conditions are satisfied.
+       * First we check the 'postFalseCond'. This means that we check
+       * to see if any of the subsequent pCode's in the pCode chain 
+       * following the point just past where we have matched depend on
+       * the `postFalseCond' as input then we abort the match
+       */
+      DFPRINTF((stderr,"    matched rule so far, now checking conditions\n"));
+      //pcin->print(stderr,pcin);
+      
+      if (pcin && peepBlock->postFalseCond && 
+         (pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
+       matched = 0;
+
+      //fprintf(stderr," condition results = %d\n",pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond));
+
+
+      //if(!matched) fprintf(stderr,"failed on conditions\n");
+    }
+
+    if(matched) {
+
+      pCode *pcprev;
+      pCode *pcr;
+
+
+      /* We matched a rule! Now we have to go through and remove the
+        inefficient code with the optimized version */
+#ifdef PCODE_DEBUG
+      DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
+      printpCodeString(stderr,peepBlock->target.pb->pcHead,10);
+      DFPRINTF((stderr,"first thing matched\n"));
+      pc->print(stderr,pc);
+      if(pcin) {
+       DFPRINTF((stderr,"last thing matched\n"));
+       pcin->print(stderr,pcin);
+      }
+#endif
+
+
+      /* Unlink the original code */
+      pcprev = pc->prev;
+      pcprev->next = pcin;
+      if(pcin) 
+       pcin->prev = pc->prev;
+
+
+#if 0
+      {
+       /*     DEBUG    */
+       /* Converted the deleted pCodes into comments */
+
+       char buf[256];
+       pCodeCSource *pc_cline2=NULL;
+
+       buf[0] = ';';
+       buf[1] = '#';
+
+       while(pc &&  pc!=pcin) {
+
+         if(pc->type == PC_OPCODE && PCI(pc)->cline) {
+           if(pc_cline) {
+             pc_cline2->pc.next = PCODE(PCI(pc)->cline);
+             pc_cline2 = PCCS(pc_cline2->pc.next);
+           } else {
+             pc_cline = pc_cline2 = PCI(pc)->cline;
+             pc_cline->pc.seq = pc->seq;
+           }
+         }
+
+         pCode2str(&buf[2], 254, pc);
+         pic16_pCodeInsertAfter(pcprev, pic16_newpCodeCharP(buf));
+         pcprev = pcprev->next;
+         pc = pc->next;
+
+       }
+       if(pc_cline2)
+         pc_cline2->pc.next = NULL;
+      }
+#endif
+
+      if(pcin)
+       pCodeDeleteChain(pc,pcin);
+
+      /* Generate the replacement code */
+      pc = pcprev;
+      pcr = peepBlock->replace.pb->pcHead;  // This is the replacement code
+      while (pcr) {
+       pCodeOp *pcop=NULL;
+       
+       /* If the replace pcode is an instruction with an operand, */
+       /* then duplicate the operand (and expand wild cards in the process). */
+       if(pcr->type == PC_OPCODE) {
+         if(PCI(pcr)->pcop) {
+           /* The replacing instruction has an operand.
+            * Is it wild? */
+           if(PCI(pcr)->pcop->type == PO_WILD) {
+             int index = PCOW(PCI(pcr)->pcop)->id;
+             //DFPRINTF((stderr,"copying wildopcode\n"));
+             if(peepBlock->target.wildpCodeOps[index])
+               pcop = pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]);
+             else
+               DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
+           } else
+             pcop = pic16_pCodeOpCopy(PCI(pcr)->pcop);
+         }
+         //DFPRINTF((stderr,"inserting pCode\n"));
+         pic16_pCodeInsertAfter(pc, pic16_newpCode(PCI(pcr)->op,pcop));
+       } else if (pcr->type == PC_WILD) {
+         if(PCW(pcr)->invertBitSkipInst)
+           DFPRINTF((stderr,"We need to invert the bit skip instruction\n"));
+         pic16_pCodeInsertAfter(pc,
+                          pCodeInstructionCopy(PCI(peepBlock->target.wildpCodes[PCW(pcr)->id]),
+                                               PCW(pcr)->invertBitSkipInst));
+       } else if (pcr->type == PC_COMMENT) {
+         pic16_pCodeInsertAfter(pc, pic16_newpCodeCharP( ((pCodeComment *)(pcr))->comment));
+       }
+
+
+       pc = pc->next;
+#ifdef PCODE_DEBUG
+       DFPRINTF((stderr,"  NEW Code:"));
+       if(pc) pc->print(stderr,pc);
+#endif
+       pcr = pcr->next;
+      }
+
+      /* We have just replaced the inefficient code with the rule.
+       * Now, we need to re-add the C-source symbols if there are any */
+      pc = pcprev;
+      while(pc_cline ) {
+       
+       pc =  pic16_findNextInstruction(pc->next);
+       PCI(pc)->cline = pc_cline;
+       pc_cline = PCCS(pc_cline->pc.next);
+       
+      }
+
+      return 1;
+    }
+  next_rule:
+    peeprules = peeprules->next;
+  }
+  DFPRINTF((stderr," no rule matched\n"));
+
+  return 0;
+}
diff --git a/src/pic16/pcoderegs.c b/src/pic16/pcoderegs.c
new file mode 100644 (file)
index 0000000..26ed6cd
--- /dev/null
@@ -0,0 +1,844 @@
+/*-------------------------------------------------------------------------
+
+   pcoderegs.c - post code generation register optimizations
+
+   Written By -  Scott Dattalo scott@dattalo.com
+   Ported To PIC16 By -  m.dubuc@rogers.com
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+-------------------------------------------------------------------------*/
+
+/*
+  pcoderegs.c
+
+  The purpose of the code in this file is to optimize the register usage.
+
+*/
+#include <stdio.h>
+
+#include "common.h"   // Include everything in the SDCC src directory
+#include "newalloc.h"
+#include "ralloc.h"
+#include "device.h"
+#include "pcode.h"
+#include "pcoderegs.h"
+#include "pcodeflow.h"
+
+extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
+extern pCode * pic16_findPrevInstruction(pCode *pci);
+extern pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n);
+void pic16_unlinkpCode(pCode *pc);
+extern int pic16_pCodeSearchCondition(pCode *pc, unsigned int cond);
+
+static int total_registers_saved=0;
+static int register_optimization=1;
+
+/*-----------------------------------------------------------------*
+ * void AddRegToFlow(regs *reg, pCodeFlow *pcfl)
+ *-----------------------------------------------------------------*/
+/*
+void AddRegToFlow(regs *reg, pCodeFlow *pcfl)
+{
+
+  if(!reg || ! pcfl || !isPCFL(pcflow))
+    return;
+
+  if(!pcfl->registers) 
+    pcfl->registers =  newSet();
+
+}
+*/
+
+
+/*-----------------------------------------------------------------*
+ * 
+ *-----------------------------------------------------------------*/
+static void dbg_regusage(set *fregs)
+{
+  regs *reg;
+  pCode *pcfl;
+  pCode *pc;
+
+
+  for (reg = setFirstItem(fregs) ; reg ;
+       reg = setNextItem(fregs)) {
+
+    if(elementsInSet(reg->reglives.usedpCodes)) {
+    
+      fprintf (stderr, "%s  addr=0x%03x rIdx=0x%03x",
+              reg->name,
+              reg->address,
+              reg->rIdx);
+
+      pcfl = setFirstItem(reg->reglives.usedpFlows);
+      if(pcfl)
+       fprintf(stderr, "\n   used in seq");
+
+      while(pcfl) {
+       fprintf(stderr," 0x%03x",pcfl->seq);
+       pcfl = setNextItem(reg->reglives.usedpFlows);
+      }
+
+      pcfl = setFirstItem(reg->reglives.assignedpFlows);
+      if(pcfl)
+       fprintf(stderr, "\n   assigned in seq");
+
+      while(pcfl) {
+       fprintf(stderr," 0x%03x",pcfl->seq);
+       pcfl = setNextItem(reg->reglives.assignedpFlows);
+      }
+
+      pc = setFirstItem(reg->reglives.usedpCodes);
+      if(pc)
+       fprintf(stderr, "\n   used in instructions ");
+
+      while(pc) {
+       pcfl = PCODE(PCI(pc)->pcflow);
+       if(pcfl)
+         fprintf(stderr," 0x%03x:",pcfl->seq);
+       fprintf(stderr,"0x%03x",pc->seq);
+
+       pc = setNextItem(reg->reglives.usedpCodes);
+      }
+
+      fprintf(stderr, "\n");
+    }
+  }
+}
+
+/*-----------------------------------------------------------------*
+ * 
+ *-----------------------------------------------------------------*/
+static void dbg_dumpregusage(void)
+{
+
+  fprintf(stderr,"***  Register Usage  ***\n");
+  fprintf(stderr,"InternalRegs:\n");
+  dbg_regusage(pic16_dynInternalRegs);
+  fprintf(stderr,"AllocRegs:\n");
+  dbg_regusage(pic16_dynAllocRegs);
+  fprintf(stderr,"StackRegs:\n");
+  dbg_regusage(pic16_dynStackRegs);
+  fprintf(stderr,"DirectRegs:\n");
+  dbg_regusage(pic16_dynDirectRegs);
+  fprintf(stderr,"DirectBitRegs:\n");
+  dbg_regusage(pic16_dynDirectBitRegs);
+  fprintf(stderr,"ProcessorRegs:\n");
+  dbg_regusage(pic16_dynProcessorRegs);
+
+}
+
+
+/*-----------------------------------------------------------------*
+ * void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
+ *-----------------------------------------------------------------*/
+static void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
+{
+
+  pCode *pc=NULL;
+  pCode *pcprev=NULL;
+
+  regs *reg;
+
+  if(!pcfl)
+    return;
+
+
+  pc = pic16_findNextInstruction(pcfl->pc.next);
+
+  while(pic16_isPCinFlow(pc,PCODE(pcfl))) {
+
+
+    reg = pic16_getRegFromInstruction(pc);
+
+    if(reg) {
+/*
+      fprintf(stderr, "flow seq %d, inst seq %d  %s  ",PCODE(pcfl)->seq,pc->seq,reg->name);
+      fprintf(stderr, "addr = 0x%03x, type = %d  rIdx=0x%03x\n",
+             reg->address,reg->type,reg->rIdx);
+*/
+
+      addSetIfnotP(& (PCFL(pcfl)->registers), reg);
+
+      if((PCC_REGISTER | PCC_LITERAL) & PCI(pc)->inCond)
+       addSetIfnotP(& (reg->reglives.usedpFlows), pcfl);
+
+      if(PCC_REGISTER & PCI(pc)->outCond)
+       addSetIfnotP(& (reg->reglives.assignedpFlows), pcfl);
+
+      addSetIfnotP(& (reg->reglives.usedpCodes), pc);
+    }
+
+
+    pcprev = pc;
+    pc = pic16_findNextInstruction(pc->next);
+
+  }
+
+}
+
+/*-----------------------------------------------------------------*
+ * void pic16_pCodeRegMapLiveRanges(pBlock *pb) 
+ *-----------------------------------------------------------------*/
+void pic16_pCodeRegMapLiveRanges(pBlock *pb)
+{
+  pCode *pcflow;
+
+  for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
+       pcflow != NULL;
+       pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
+
+    if(!isPCFL(pcflow)) {
+      fprintf(stderr, "pCodeRegMapLiveRanges - pcflow is not a flow object ");
+      continue;
+    }
+    pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
+  }
+
+#if 0
+  for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
+       pcflow != NULL;
+       pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
+
+    regs *r = setFirstItem(PCFL(pcflow)->registers);
+    fprintf(stderr,"flow seq %d\n", pcflow->seq);
+
+    while (r) {
+      fprintf(stderr, "  %s\n",r->name);
+      r = setNextItem(PCFL(pcflow)->registers);
+
+    }
+
+  }
+#endif
+
+//  dbg_dumpregusage();
+
+}
+
+
+/*-----------------------------------------------------------------*
+ *
+ *-----------------------------------------------------------------*/
+static void Remove1pcode(pCode *pc, regs *reg)
+{
+  pCode *pcn=NULL;
+
+  if(!reg || !pc)
+    return;
+
+  deleteSetItem (&(reg->reglives.usedpCodes),pc);
+/*
+  fprintf(stderr,"removing instruction:\n");
+  pc->print(stderr,pc);
+*/
+  if(PCI(pc)->label) {
+    pcn = pic16_findNextInstruction(pc->next);
+
+    if(pcn)
+      PCI(pcn)->label = pic16_pBranchAppend(PCI(pcn)->label,PCI(pc)->label);
+  }
+
+  if(PCI(pc)->cline) {
+    if(!pcn)
+      pcn = pic16_findNextInstruction(pc->next);
+
+    if(pcn) {
+      if(PCI(pcn)->cline) {
+       //fprintf(stderr, "source line has been optimized completely out\n");
+       //pc->print(stderr,pc);
+      } else {
+       PCI(pcn)->cline = PCI(pc)->cline;
+      }
+    }
+  }
+
+  pc->destruct(pc);
+
+}
+
+/*-----------------------------------------------------------------*
+ * void RemoveRegsFromSet(set *regset)
+ *
+ *-----------------------------------------------------------------*/
+static void  RemoveRegsFromSet(set *regset)
+{
+  regs *reg;
+  int used;
+
+  while(regset) {
+    reg = regset->item;
+    regset = regset->next;
+
+    used = elementsInSet(reg->reglives.usedpCodes);
+
+    if(used <= 1) {
+
+      //fprintf(stderr," reg %s isfree=%d, wasused=%d\n",reg->name,reg->isFree,reg->wasUsed);
+      if(used == 0) {
+       //fprintf(stderr," getting rid of reg %s\n",reg->name);
+       reg->isFree = 1;
+       reg->wasUsed = 0;
+      } else {
+       pCode *pc;
+
+
+       pc = setFirstItem(reg->reglives.usedpCodes);
+
+       if(reg->type == REG_SFR) {
+         //fprintf(stderr, "not removing SFR reg %s even though used only once\n",reg->name);
+         continue;
+       }
+
+
+       if(isPCI(pc)) {
+         if(PCI(pc)->label) {
+           pCode *pcn = pic16_findNextInstruction(pc->next);
+
+           if(pcn && PCI(pcn)->label) {
+             //fprintf(stderr,"can't delete instruction with label...\n");
+             //pc->print(stderr,pc);
+             continue;
+           } 
+           /* Move the label to the next instruction */
+
+           PCI(pcn)->label = PCI(pc)->label;
+
+         }
+
+         if(isPCI_SKIP(pc)) {
+           regs *r = pic16_getRegFromInstruction(pc);
+           fprintf(stderr, "WARNING, a skip instruction is being optimized out\n");
+           pc->print(stderr,pc);
+           fprintf(stderr,"reg %s, type =%d\n",r->name, r->type);
+         }
+         //fprintf(stderr," removing reg %s because it is used only once\n",reg->name);
+         Remove1pcode(pc, reg);
+         /*
+           pic16_unlinkpCode(pc);
+           deleteSetItem (&(reg->reglives.usedpCodes),pc);
+         */
+         reg->isFree = 1;
+         reg->wasUsed = 0;
+         total_registers_saved++;  // debugging stats.
+       }
+      }
+    }
+
+  }
+}
+/*-----------------------------------------------------------------*
+ * void pic16_RemoveUnusedRegisters(void)
+ *
+ *-----------------------------------------------------------------*/
+void pic16_RemoveUnusedRegisters(void)
+{
+  /* First, get rid of registers that are used only one time */
+
+  //RemoveRegsFromSet(pic16_dynInternalRegs);
+  RemoveRegsFromSet(pic16_dynAllocRegs);
+  RemoveRegsFromSet(pic16_dynStackRegs);
+  /*
+    don't do DirectRegs yet - there's a problem with arrays
+  RemoveRegsFromSet(pic16_dynDirectRegs);
+  */
+  RemoveRegsFromSet(pic16_dynDirectBitRegs);
+
+  if(total_registers_saved) fprintf(stderr, " *** Saved %d registers ***\n", total_registers_saved);
+}
+
+
+/*-----------------------------------------------------------------*
+ *
+ *-----------------------------------------------------------------*/
+static void Remove2pcodes(pCode *pcflow, pCode *pc1, pCode *pc2, regs *reg, int can_free)
+{
+  if(!reg)
+    return;
+
+  if(pc1)
+    Remove1pcode(pc1, reg);
+
+  if(pc2) {
+    Remove1pcode(pc2, reg);
+    deleteSetItem (&(PCFL(pcflow)->registers), reg);
+
+    if(can_free) {
+      reg->isFree = 1;
+      reg->wasUsed = 0;
+    }
+
+  }
+
+  pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
+}
+
+/*-----------------------------------------------------------------*
+ *
+ *-----------------------------------------------------------------*/
+static int regUsedinRange(pCode *pc1, pCode *pc2, regs *reg)
+{
+  int i=0;
+  regs *testreg;
+
+  do {
+    testreg = pic16_getRegFromInstruction(pc1);
+    if(testreg && (testreg->rIdx == reg->rIdx)) {
+      return 1;
+    }
+
+    pc1 = pic16_findNextInstruction(pc1->next);
+
+  } while (pc1 && (pc1 != pc2) && (i++ < 100)) ;
+
+  if(i >= 100)
+    fprintf(stderr, "warning, regUsedinRange searched through too many pcodes\n");
+
+  return 0;
+}
+
+/*-----------------------------------------------------------------*
+ * void pCodeOptime2pCodes(pCode *pc1, pCode *pc2) 
+ *
+ * ADHOC pattern checking 
+ * Now look for specific sequences that are easy to optimize.
+ * Many of these sequences are characteristic of the compiler
+ * (i.e. it'd probably be a waste of time to apply these adhoc
+ * checks to hand written assembly.)
+ * 
+ *
+ *-----------------------------------------------------------------*/
+static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int can_free, int optimize_level)
+{
+  pCode *pct1, *pct2;
+  regs  *reg1, *reg2;
+
+  int t = total_registers_saved;
+
+  if(pc2->seq < pc1->seq) {
+    pct1 = pc2;
+    pc2 = pc1;
+    pc1 = pct1;
+  }
+/*
+  fprintf(stderr,"pCodeOptime2pCodes\n");
+  pc1->print(stderr,pc1);
+  pc2->print(stderr,pc2);
+*/
+  if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){
+
+    /*
+      clrf  reg
+      stuff...
+      movf  reg,w
+
+      can be replaced with
+
+      stuff...
+      movlw 0
+    */
+
+    pCode *newpc;
+    //fprintf(stderr, "   CLRF/MOVFW. instruction after MOVFW is:\n");
+    pct1 = pic16_findNextInstruction(pc2->next);
+
+    if(PCI(pct1)->op == POC_MOVWF) {
+      newpc = pic16_newpCode(POC_CLRF, PCI(pct1)->pcop);
+      pct1->destruct(pct1);
+    } else {
+      newpc = pic16_newpCode(POC_MOVLW, pic16_newpCodeOpLit(0));
+    }
+
+    pic16_pCodeInsertAfter(pc2, newpc);
+    PCI(newpc)->pcflow = PCFL(pcfl_used);
+    newpc->seq = pc2->seq;
+
+    Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
+    total_registers_saved++;  // debugging stats.
+
+  } else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){
+    //fprintf(stderr, "   CLRF/IORFW.\n");
+
+    pct2 = pic16_findNextInstruction(pc2->next);
+
+    if(pic16_pCodeSearchCondition(pct2, PCC_Z) > 0) {
+      pct2 = pic16_newpCode(POC_IORLW, pic16_newpCodeOpLit(0));
+      pct2->seq = pc2->seq;
+      PCI(pct2)->pcflow = PCFL(pcfl_used);
+      pic16_pCodeInsertAfter(pc1,pct2);
+    }
+    Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
+    total_registers_saved++;  // debugging stats.
+
+  }  else if(PCI(pc1)->op == POC_MOVWF) {
+
+    pct2 = pic16_findNextInstruction(pc2->next);
+
+    if(PCI(pc2)->op == POC_MOVFW) {
+      /*
+       fprintf(stderr, "   MOVWF/MOVFW. instruction after MOVFW is:\n");
+       pct2->print(stderr,pct2);
+      */
+
+      if(PCI(pct2)->op == POC_MOVWF) {
+       /*
+         Change:
+
+           movwf   reg
+
+           stuff...
+
+           movf    reg,w
+            movwf   reg2
+
+         To:
+
+           
+       */
+       reg2 = pic16_getRegFromInstruction(pct2);
+       //if(reg2 && !regUsedinRange(pc1,pc2,reg2) && (reg2->type != REG_SFR)) {
+       if(reg2 && !regUsedinRange(pc1,pc2,reg2)) {
+
+         if(pic16_pCodeSearchCondition(pct2, PCC_Z) < 1) {
+           pCode *pct3 = pic16_findNextInstruction(pct2->next);
+           pct2->seq = pc1->seq;
+           pic16_unlinkpCode(pct2);
+           pic16_pCodeInsertAfter(pic16_findPrevInstruction(pc1->prev),pct2);
+
+#define usesW(x)       ((x) && (isPCI(x)) && ( (PCI(x)->inCond & PCC_W) != 0))
+
+           if(usesW(pct3))
+             ; // Remove2pcodes(pcfl_used, pc1, NULL, reg, can_free);
+           else
+             Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
+
+           total_registers_saved++;  // debugging stats.
+           return 1;
+           } else {
+             //fprintf(stderr,"didn't optimize because Z bit is used\n");
+           }
+       }
+/*
+       fprintf(stderr, " couldn't optimize\n");
+       if(reg2)
+         fprintf(stderr, " %s is used in range\n",reg2->name);
+       else
+         fprintf(stderr, " reg2 is NULL\n");
+*/
+      }
+    }
+
+    pct1 = pic16_findPrevInstruction(pc1->prev);
+    if(pct1 && (PCI(pct1)->pcflow == PCI(pc1)->pcflow)) {
+
+      if ( (PCI(pct1)->op == POC_MOVFW) &&
+          (PCI(pc2)->op == POC_MOVFW)) {
+
+       reg1 = pic16_getRegFromInstruction(pct1);
+       if(reg1 && !regUsedinRange(pc1,pc2,reg1)) {
+         /*
+           fprintf(stderr, "   MOVF/MOVFW. \n");
+           fprintf(stderr, "     ...optimizing\n");
+         */
+
+         /*
+           Change:
+
+           movf   reg1,w
+           movwf  reg
+
+           stuff...
+           movf   reg,w
+
+           To:
+
+           stuff...
+
+           movf   reg1,w
+
+           Or, if we're not deleting the register then the "To" is:
+
+           stuff...
+
+           movf   reg1,w
+           movwf  reg
+
+
+         */
+         pct2 = pic16_newpCode(PCI(pc2)->op, PCI(pct1)->pcop);
+         pic16_pCodeInsertAfter(pc2, pct2);
+         PCI(pct2)->pcflow = PCFL(pcfl_used);
+         pct2->seq = pc2->seq;
+
+         if(can_free) {
+           Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
+         } else {
+           /* If we're not freeing the register then that means (probably)
+            * the register is needed somewhere else.*/
+           pic16_unlinkpCode(pc1);
+           pic16_pCodeInsertAfter(pct2, pc1);
+
+           Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free);
+         }
+
+         Remove2pcodes(pcfl_used, pct1, NULL, reg1, 0);
+         total_registers_saved++;  // debugging stats.
+
+       }
+      } else if ( (PCI(pct1)->op == POC_MOVWF) &&
+          (PCI(pc2)->op == POC_MOVFW)) {
+       //fprintf(stderr,"movwf MOVWF/MOVFW\n");
+       if(optimize_level > 1 && can_free) {
+         pct2 = pic16_newpCode(POC_MOVFW, PCI(pc1)->pcop);
+         pic16_pCodeInsertAfter(pc2, pct2);
+         Remove2pcodes(pcfl_used, pc1, pc2, reg, 1);
+         total_registers_saved++;  // debugging stats.
+       }
+      }
+
+
+    }
+
+  }
+
+  return (total_registers_saved != t);
+}
+
+/*-----------------------------------------------------------------*
+ * void pCodeRegOptimeRegUsage(pBlock *pb) 
+ *-----------------------------------------------------------------*/
+static void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level)
+{
+  regs *reg;
+  int used;
+  pCode *pc1=NULL, *pc2=NULL;
+
+
+  while(fregs) {
+    pCode *pcfl_used, *pcfl_assigned;
+
+    /* Step through the set by directly accessing the 'next' pointer.
+     * We could also step through by using the set API, but the 
+     * the (debug) calls to print instructions affect the state
+     * of the set pointers */
+
+    reg = fregs->item;
+    fregs = fregs->next;
+
+    if(reg->type == REG_SFR) {
+      //fprintf(stderr,"skipping SFR: %s\n",reg->name);
+      continue;
+    }
+
+    pcfl_used = setFirstItem(reg->reglives.usedpFlows);
+    pcfl_assigned = setFirstItem(reg->reglives.assignedpFlows);
+
+    used = elementsInSet(reg->reglives.usedpCodes);
+    if(used == 2) { 
+
+      /*
+       * In this section, all registers that are used in only in two 
+       * instructions are examined. If possible, they're optimized out.
+       */
+
+/*
+      fprintf (stderr, "OptimizeRegUsage: %s  addr=0x%03x rIdx=0x%03x type=%d used=%d\n",
+              reg->name,
+              reg->address,
+              reg->rIdx, reg->type, used);
+*/
+      pc1 = setFirstItem(reg->reglives.usedpCodes);
+      pc2 = setNextItem(reg->reglives.usedpCodes);
+
+      if(pcfl_used && pcfl_assigned) {
+
+       /* 
+          expected case - the register has been assigned a value and is
+          subsequently used 
+       */
+
+       //fprintf(stderr," used only twice\n");
+       if(pcfl_used->seq == pcfl_assigned->seq) {
+
+         //fprintf(stderr, "  and used in same flow\n");
+
+         pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 1,optimize_level);
+
+       } else {
+         // fprintf(stderr, "  and used in different flows\n");
+
+       }
+
+      } else if(pcfl_used) {
+
+       /*
+         register has been used twice without ever being assigned */
+       //fprintf(stderr,"WARNING %s: reg %s used without being assigned\n",__FUNCTION__,reg->name);
+
+      } else {
+       //fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);
+       Remove2pcodes(pcfl_assigned, pc1, pc2, reg, 1);
+       total_registers_saved++;  // debugging stats.
+      }
+    } else {
+
+      /* register has been used either once, or more than twice */
+
+      if(used && !pcfl_used && pcfl_assigned) {
+       pCode *pc;
+
+       //fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);
+
+       pc = setFirstItem(reg->reglives.usedpCodes);
+       while(pc) {
+
+         pcfl_assigned = PCODE(PCI(pc)->pcflow);
+         Remove1pcode(pc, reg);
+
+         deleteSetItem (&(PCFL(pcfl_assigned)->registers), reg);
+         /*
+         deleteSetItem (&(reg->reglives.usedpCodes),pc);
+         pc->destruct(pc);
+         */
+         pc = setNextItem(reg->reglives.usedpCodes);
+       }
+
+
+       reg->isFree = 1;
+       reg->wasUsed = 0;
+
+       total_registers_saved++;  // debugging stats.
+      } else if( (used > 2) && optimize_multi_uses) {
+
+       set *rset1=NULL;
+       set *rset2=NULL;
+       int searching=1;
+
+       pCodeFlow *pcfl1=NULL, *pcfl2=NULL;
+
+       /* examine the number of times this register is used */
+
+
+       rset1 = reg->reglives.usedpCodes;
+       while(rset1 && searching) {
+
+         pc1 = rset1->item;
+         rset2 = rset1->next;
+
+         if(pc1 && isPCI(pc1) &&  ( (pcfl1 = PCI(pc1)->pcflow) != NULL) ) {
+
+           //while(rset2 && searching) {
+           if(rset2) {
+
+             pc2 = rset2->item;
+             if(pc2 && isPCI(pc2)  &&  ( (pcfl2 = PCI(pc2)->pcflow) != NULL) )  {
+               if(pcfl2 == pcfl1) {
+
+                 if(pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 0,optimize_level))
+                   searching = 0;
+               }
+             }
+
+             //rset2 = rset2->next;
+             
+           }
+         }
+         rset1 = rset1->next;
+       }
+      }
+    }
+
+  }
+
+}
+/*-----------------------------------------------------------------*
+ * void pic16_pCodeRegOptimeRegUsage(pBlock *pb) 
+ *-----------------------------------------------------------------*/
+void pic16_pCodeRegOptimizeRegUsage(int level)
+{
+
+  int passes;
+  int saved = 0;
+  int t = total_registers_saved;
+
+  if(!register_optimization)
+    return;
+#define OPT_PASSES 4
+  passes = OPT_PASSES;
+
+  do {
+    saved = total_registers_saved;
+
+    /* Identify registers used in one flow sequence */
+    OptimizeRegUsage(pic16_dynAllocRegs,level, (OPT_PASSES-passes));
+    OptimizeRegUsage(pic16_dynStackRegs,level, (OPT_PASSES-passes));
+    OptimizeRegUsage(pic16_dynDirectRegs,0, (OPT_PASSES-passes));
+
+    if(total_registers_saved != saved)
+      fprintf(stderr, " *** pass %d, Saved %d registers, total saved %d ***\n", 
+             (1+OPT_PASSES-passes),total_registers_saved-saved,total_registers_saved);
+      
+    passes--;
+
+  } while( passes && ((total_registers_saved != saved) || (passes==OPT_PASSES-1)) );
+
+  if(total_registers_saved == t) 
+    fprintf(stderr, "No registers saved on this pass\n");
+
+
+/*
+  fprintf(stderr,"dynamically allocated regs:\n");
+  dbg_regusage(pic16_dynAllocRegs);
+  fprintf(stderr,"stack regs:\n");
+  dbg_regusage(pic16_dynStackRegs);
+  fprintf(stderr,"direct regs:\n");
+  dbg_regusage(pic16_dynDirectRegs);
+*/
+}
+
+
+/*-----------------------------------------------------------------*
+ * void RegsUnMapLiveRanges(set *regset)
+ *
+ *-----------------------------------------------------------------*/
+static void  RegsSetUnMapLiveRanges(set *regset)
+{
+  regs *reg;
+
+  while(regset) {
+    reg = regset->item;
+    regset = regset->next;
+
+    
+    deleteSet(&reg->reglives.usedpCodes);
+    deleteSet(&reg->reglives.usedpFlows);
+    deleteSet(&reg->reglives.assignedpFlows);
+
+  }
+
+}
+
+void  pic16_RegsUnMapLiveRanges(void)
+{
+
+  RegsSetUnMapLiveRanges(pic16_dynAllocRegs);
+  RegsSetUnMapLiveRanges(pic16_dynStackRegs);
+  RegsSetUnMapLiveRanges(pic16_dynDirectRegs);
+  RegsSetUnMapLiveRanges(pic16_dynProcessorRegs);
+  RegsSetUnMapLiveRanges(pic16_dynDirectBitRegs);
+  RegsSetUnMapLiveRanges(pic16_dynInternalRegs);
+
+}
diff --git a/src/pic16/pcoderegs.h b/src/pic16/pcoderegs.h
new file mode 100644 (file)
index 0000000..c37d72f
--- /dev/null
@@ -0,0 +1,42 @@
+/*-------------------------------------------------------------------------
+
+   pcoderegs.h - post code generation register optimizations
+
+   Written By -  Scott Dattalo scott@dattalo.com
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+-------------------------------------------------------------------------*/
+
+#ifndef __PCODEREGS_H__
+#define __PCODEREGS_H__
+
+/*************************************************
+
+  pCodeRegLives 
+
+  Records the set of registers used in a flow object.
+
+**************************************************/
+
+typedef struct pCodeRegLives {
+  set *usedpFlows;       /* set of pFlow objects that use this register */
+  set *assignedpFlows;   /* set of pFlow objects that assign values to this register */
+  set *usedpCodes;       /* set of all instructions that use this register */
+
+} pCodeRegLives;
+
+
+#endif //  __PCODEREGS_H__
diff --git a/src/pic16/peeph.def b/src/pic16/peeph.def
new file mode 100644 (file)
index 0000000..c0e7b81
--- /dev/null
@@ -0,0 +1,285 @@
+// PIC Port Peep rules
+//
+//
+// INTRODUCTION:
+//
+// The peep hole optimizer searchs the
+// the SDCC generated code for small snippets
+// that can be optimized. As a user, you have
+// control over this optimization process without
+// having to learn the SDCC source code. (However
+// you'll still need access to the source since
+// these rules are compiled into the source.)
+//
+// The way it works is you specify the target
+// snippet that you want replaced with a more 
+// efficient snippet that you write. Wild card
+// variables allow the rules to be parameterized.
+// 
+// In all of the SDCC ports, labels and operands
+// can be wild cards. However, in the PIC even the
+// instructions can be wild cards.
+//
+// EXAMPLE:
+//
+// Consider Peep Rule 1 as an example. This rule
+// replaces some code like:
+//
+//   skpz           ;i.e. btfss status,Z
+//    goto    lab1
+//   clrw
+//lab1:
+//
+// with:
+//
+//   skpnz     ;i.e. btfsc status,Z
+//    clrw
+//lab1
+//
+// However, the Rule has four wild cards.
+// The first allows the btfss instruction operator
+// be anything, not just the Z bit in status register.
+// The second wild card applies to a label.
+// The third wild card is for an instruction - any
+// single instruction can be substituted.
+// The fourth wild card is also an instruction. It's
+// just an instruction place holder associated with
+// a label (think of it as the PIC Port author's laziness
+// imposed upon the user).
+//
+//
+// CONDITIONS
+//
+// There are certain instances where a peep rule may not
+// be applicable. Consider this subtle example:
+//
+//     movwf    R0
+//     movf     R0,W
+//
+// It would seem that the second move is unnecessary. But
+// be careful! The movf instruction affects the 'Z' bit.
+// So if this sequence is followed by a btfsc status,Z, you
+// will have to leave the second move in.
+//
+// To get around this proble, the peep rule can be followed
+// by a conditon:  "if NZ". Which is to say, apply the rule
+// if Z bit is not needed in the code that follows. The optimizer
+// is smart enough to look more than one instruction past the
+// target block...
+//
+// Special commands
+//
+//
+//   _NOTBITSKIP_   %1   - Creates a wild card instruction that
+//                         will match all instructions except for
+//                         bit skip instructions (btfsc or btfss)
+//   _BITSKIP_  %1 - Creates a wild card instruction that only
+//                   will match a bit skip instruction (btfsc
+//                   or btfss)
+//   _INVERTBITSKIP_ %1  - For the wild card instruction %1, invert
+//                         the state of the bit skip. If %1 is not
+//                         a bit skip instruction, then there's an
+//                         error in the peep rule.
+//
+// 
+//
+
+
+// Peep 1 
+//   Converts 
+//
+//    btfss   reg1,bit
+//     goto   label
+//    incf    reg2,f
+//label
+//
+// Into:
+//
+//    btfsc   reg1,bit
+//     incf   reg2,f
+//label
+//
+// Notice that wild cards will allow any instruction
+// besides incf to be used in the above.
+//
+// Also, notice that this snippet is not valid if
+// it follows another skip
+
+replace restart {
+        _NOTBITSKIP_   %1
+       _BITSKIP_       %2
+        goto   %3
+       %4
+%3:    %5
+} by {
+       ;     peep 1 - test/jump to test/skip
+        %1
+       _INVERTBITSKIP_ %2
+       %4
+%3:    %5
+} 
+
+replace restart {
+        _NOTBITSKIP_   %1
+       _BITSKIP_       %2
+        goto   %3
+%4:    %5
+%3:    %6
+} by {
+       ;     peep 1b - test/jump to test/skip
+        %1
+       _INVERTBITSKIP_ %2
+%4:    %5
+%3:    %6
+} 
+
+
+//bogus test for pcode
+//replace restart {
+//     movf    %1,w    ;comment at end
+//%4:  movf    %1,w
+//     RETURN
+//     clrf    INDF0
+//     movlw   0xa5
+//     movf    fsr0,w
+//     incf    indf0,f
+//     %2
+//} by {
+//     ; peep test remove redundant move
+//%4:  movf    %1,w    ;another comment
+//     %2
+//} if AYBABTU %3
+
+
+// peep 2
+replace restart {
+       movwf   %1
+       movf    %1,w
+} by {
+       ;     peep 2 - Removed redundant move
+       movwf   %1
+} if NZ
+
+// peep 3
+replace restart {
+       decf    %1,f
+       movf    %1,w
+       btfss   _STATUS,z
+       goto    %2
+} by {
+       ;     peep 3 - decf/mov/skpz to decfsz
+       decfsz  %1,f
+        goto   %2
+}
+
+
+replace restart {
+       movf    %1,w
+       movf    %1,w
+} by {
+       ;     peep 4 - Removed redundant move
+       movf    %1,w
+}
+
+
+replace restart {
+       movlw   %1
+       movwf   %2
+       movlw   %1
+} by {
+       ;     peep 5 - Removed redundant move
+       movlw   %1
+       movwf   %2
+}
+
+replace restart {
+       movwf   %1
+       movwf   %1
+} by {
+       ;     peep 6 - Removed redundant move
+       movwf   %1
+}
+
+replace restart {
+       movlw   0
+       iorwf   %1,w
+} by {
+       ;     peep 7 - Removed redundant move
+       movf    %1,w
+}
+
+replace restart {
+       movf    %1,w
+       movwf   %2
+       decf    %2,f
+} by {
+       ;     peep 8 - Removed redundant move
+       decf    %1,w
+       movwf   %2
+}
+
+replace restart {
+       movwf   %1
+       movf    %2,w
+       xorwf   %1,w
+} by {
+       ;     peep 9a - Removed redundant move
+       movwf   %1
+       xorwf   %2,w
+}
+
+replace restart {
+       movwf   %1
+       movf    %2,w
+       iorwf   %1,w
+} by {
+       ;     peep 9b - Removed redundant move
+       movwf   %1
+       iorwf   %2,w
+}
+
+replace restart {
+       movf    %1,w
+       movwf   %2
+       movf    %2,w
+} by {
+       ;     peep 9c - Removed redundant move
+       movf    %1,w
+       movwf   %2
+}
+
+replace restart {
+       movwf   %1
+       movf    %1,w
+       movwf   %2
+} by {
+       ;     peep 9d - Removed redundant move
+       movwf   %1
+       movwf   %2
+} if NZ
+
+// From: Frieder Ferlemann
+
+replace restart {
+        iorlw   0
+} by {
+        ;     peep 10a - Removed unnecessary iorlw
+} if NZ
+
+// From: Frieder Ferlemann
+
+replace restart {
+        xorlw   0
+} by {
+        ;     peep 10b - Removed unnecessary xorlw
+} if NZ
+
+// From: Frieder Ferlemann
+
+replace restart {
+        movf    %1,w
+        movwf   %1
+} by {
+        ;     peep 11 - Removed redundant move
+        movf    %1,w
+}
diff --git a/src/pic16/pic.dsp b/src/pic16/pic.dsp
new file mode 100644 (file)
index 0000000..7de9799
--- /dev/null
@@ -0,0 +1,164 @@
+# Microsoft Developer Studio Project File - Name="pic" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=pic - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "pic.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "pic.mak" CFG="pic - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "pic - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "pic - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "pic - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MLd /W3 /Gm /GX /ZI /Od /I ".." /I "." /I "..\.." /I "..\..\support\util" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /FD /GZ /Zm500 /c
+# ADD CPP /nologo /MLd /W3 /Gm /GX /ZI /Od /I ".." /I "." /I "..\.." /I "..\..\support\util" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /FD /GZ /Zm500 /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"Debug\port.lib"
+# ADD LIB32 /nologo /out:"Debug\port.lib"
+
+!ELSEIF  "$(CFG)" == "pic - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /ML /W3 /GX /O2 /I ".." /I "." /I "..\.." /I "..\..\support\util" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /Zm500 /c
+# ADD CPP /nologo /ML /W3 /GX /O2 /I ".." /I "." /I "..\.." /I "..\..\support\util" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /Zm500 /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"Release\port.lib"
+# ADD LIB32 /nologo /out:"Release\port.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "pic - Win32 Debug"
+# Name "pic - Win32 Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\device.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\gen.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\genarith.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\glue.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pcode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pcodeflow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pcodepeep.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pcoderegs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ralloc.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\device.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\gen.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\glue.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\pcode.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\pcodeflow.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\pcoderegs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ralloc.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/src/pic16/pica.dsp b/src/pic16/pica.dsp
new file mode 100644 (file)
index 0000000..ec9c196
--- /dev/null
@@ -0,0 +1,90 @@
+# Microsoft Developer Studio Project File - Name="pica" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Generic Project" 0x010a
+
+CFG=pica - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "pica.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "pica.mak" CFG="pica - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "pica - Win32 Debug" (based on "Win32 (x86) Generic Project")
+!MESSAGE "pica - Win32 Release" (based on "Win32 (x86) Generic Project")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+MTL=midl.exe
+
+!IF  "$(CFG)" == "pica - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "pica - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Target_Dir ""
+
+!ENDIF 
+
+# Begin Target
+
+# Name "pica - Win32 Debug"
+# Name "pica - Win32 Release"
+# Begin Source File
+
+SOURCE=.\peeph.def
+
+!IF  "$(CFG)" == "pica - Win32 Debug"
+
+# Begin Custom Build
+InputPath=.\peeph.def
+
+"peeph.rul" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+       gawk -f ../SDCCpeeph.awk $(InputPath) >peeph.rul
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "pica - Win32 Release"
+
+# Begin Custom Build
+InputPath=.\peeph.def
+
+"peeph.rul" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+       gawk -f ../SDCCpeeph.awk $(InputPath) >peeph.rul
+
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# End Target
+# End Project
diff --git a/src/pic16/ralloc.c b/src/pic16/ralloc.c
new file mode 100644 (file)
index 0000000..638647f
--- /dev/null
@@ -0,0 +1,3882 @@
+/*------------------------------------------------------------------------
+
+  SDCCralloc.c - source file for register allocation. (8051) specific
+
+                Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+               Added Pic Port T.scott Dattalo scott@dattalo.com (2000)
+               Added Pic16 Port Martin Dubuc m.dubuc@rogers.com (2002)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+
+#include "common.h"
+#include "ralloc.h"
+#include "pcode.h"
+#include "gen.h"
+
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
+#endif
+
+/*-----------------------------------------------------------------*/
+/* At this point we start getting processor specific although      */
+/* some routines are non-processor specific & can be reused when   */
+/* targetting other processors. The decision for this will have    */
+/* to be made on a routine by routine basis                        */
+/* routines used to pack registers are most definitely not reusable */
+/* since the pack the registers depending strictly on the MCU      */
+/*-----------------------------------------------------------------*/
+
+static regs *typeRegWithIdx (int idx, int type, int fixed);
+extern void genpic16Code (iCode *);
+extern void pic16_assignConfigWordValue(int address, int value);
+
+/* Global data */
+static struct
+  {
+    bitVect *spiltSet;
+    set *stackSpil;
+    bitVect *regAssigned;
+    short blockSpil;
+    int slocNum;
+    bitVect *funcrUsed;                /* registers used in a function */
+    int stackExtend;
+    int dataExtend;
+  }
+_G;
+
+/* Shared with gen.c */
+int pic16_ptrRegReq;           /* one byte pointer register required */
+
+
+set *pic16_dynAllocRegs=NULL;
+set *pic16_dynStackRegs=NULL;
+set *pic16_dynProcessorRegs=NULL;
+set *pic16_dynDirectRegs=NULL;
+set *pic16_dynDirectBitRegs=NULL;
+set *pic16_dynInternalRegs=NULL;
+
+static hTab  *dynDirectRegNames= NULL;
+static hTab  *regHash = NULL;    /* a hash table containing ALL registers */
+
+static int dynrIdx=0x20;
+static int rDirectIdx=0;
+
+int pic16_nRegs = 128;   // = sizeof (regspic16) / sizeof (regs);
+
+int pic16_Gstack_base_addr=0; /* The starting address of registers that
+                        * are used to pass and return parameters */
+
+
+
+
+static void spillThis (symbol *);
+static int debug = 1;
+static FILE *debugF = NULL;
+/*-----------------------------------------------------------------*/
+/* debugLog - open a file for debugging information                */
+/*-----------------------------------------------------------------*/
+//static void debugLog(char *inst,char *fmt, ...)
+static void
+debugLog (char *fmt,...)
+{
+  static int append = 0;       // First time through, open the file without append.
+
+  char buffer[256];
+  //char *bufferP=buffer;
+  va_list ap;
+
+  if (!debug || !srcFileName)
+    return;
+
+
+  if (!debugF)
+    {
+      /* create the file name */
+      strcpy (buffer, srcFileName);
+      strcat (buffer, ".d");
+
+      if (!(debugF = fopen (buffer, (append ? "a+" : "w"))))
+       {
+         werror (E_FILE_OPEN_ERR, buffer);
+         exit (1);
+       }
+      append = 1;              // Next time debubLog is called, we'll append the debug info
+
+    }
+
+  va_start (ap, fmt);
+
+  vsprintf (buffer, fmt, ap);
+
+  fprintf (debugF, "%s", buffer);
+/*
+   while (isspace(*bufferP)) bufferP++;
+
+   if (bufferP && *bufferP) 
+   lineCurr = (lineCurr ?
+   connectLine(lineCurr,newLineNode(lb)) :
+   (lineHead = newLineNode(lb)));
+   lineCurr->isInline = _G.inLine;
+   lineCurr->isDebug  = _G.debugLine;
+ */
+  va_end (ap);
+
+}
+
+static void
+debugNewLine (void)
+{
+  if (debugF)
+    fputc ('\n', debugF);
+}
+/*-----------------------------------------------------------------*/
+/* debugLogClose - closes the debug log file (if opened)           */
+/*-----------------------------------------------------------------*/
+static void
+debugLogClose (void)
+{
+  if (debugF)
+    {
+      fclose (debugF);
+      debugF = NULL;
+    }
+}
+#define AOP(op) op->aop
+
+static char *
+debugAopGet (char *str, operand * op)
+{
+  if (str)
+    debugLog (str);
+
+  printOperand (op, debugF);
+  debugNewLine ();
+
+  return NULL;
+
+}
+
+static char *
+decodeOp (unsigned int op)
+{
+
+  if (op < 128 && op > ' ')
+    {
+      buffer[0] = (op & 0xff);
+      buffer[1] = 0;
+      return buffer;
+    }
+
+  switch (op)
+    {
+    case IDENTIFIER:
+      return "IDENTIFIER";
+    case TYPE_NAME:
+      return "TYPE_NAME";
+    case CONSTANT:
+      return "CONSTANT";
+    case STRING_LITERAL:
+      return "STRING_LITERAL";
+    case SIZEOF:
+      return "SIZEOF";
+    case PTR_OP:
+      return "PTR_OP";
+    case INC_OP:
+      return "INC_OP";
+    case DEC_OP:
+      return "DEC_OP";
+    case LEFT_OP:
+      return "LEFT_OP";
+    case RIGHT_OP:
+      return "RIGHT_OP";
+    case LE_OP:
+      return "LE_OP";
+    case GE_OP:
+      return "GE_OP";
+    case EQ_OP:
+      return "EQ_OP";
+    case NE_OP:
+      return "NE_OP";
+    case AND_OP:
+      return "AND_OP";
+    case OR_OP:
+      return "OR_OP";
+    case MUL_ASSIGN:
+      return "MUL_ASSIGN";
+    case DIV_ASSIGN:
+      return "DIV_ASSIGN";
+    case MOD_ASSIGN:
+      return "MOD_ASSIGN";
+    case ADD_ASSIGN:
+      return "ADD_ASSIGN";
+    case SUB_ASSIGN:
+      return "SUB_ASSIGN";
+    case LEFT_ASSIGN:
+      return "LEFT_ASSIGN";
+    case RIGHT_ASSIGN:
+      return "RIGHT_ASSIGN";
+    case AND_ASSIGN:
+      return "AND_ASSIGN";
+    case XOR_ASSIGN:
+      return "XOR_ASSIGN";
+    case OR_ASSIGN:
+      return "OR_ASSIGN";
+    case TYPEDEF:
+      return "TYPEDEF";
+    case EXTERN:
+      return "EXTERN";
+    case STATIC:
+      return "STATIC";
+    case AUTO:
+      return "AUTO";
+    case REGISTER:
+      return "REGISTER";
+    case CODE:
+      return "CODE";
+    case EEPROM:
+      return "EEPROM";
+    case INTERRUPT:
+      return "INTERRUPT";
+    case SFR:
+      return "SFR";
+    case AT:
+      return "AT";
+    case SBIT:
+      return "SBIT";
+    case REENTRANT:
+      return "REENTRANT";
+    case USING:
+      return "USING";
+    case XDATA:
+      return "XDATA";
+    case DATA:
+      return "DATA";
+    case IDATA:
+      return "IDATA";
+    case PDATA:
+      return "PDATA";
+    case VAR_ARGS:
+      return "VAR_ARGS";
+    case CRITICAL:
+      return "CRITICAL";
+    case NONBANKED:
+      return "NONBANKED";
+    case BANKED:
+      return "BANKED";
+    case CHAR:
+      return "CHAR";
+    case SHORT:
+      return "SHORT";
+    case INT:
+      return "INT";
+    case LONG:
+      return "LONG";
+    case SIGNED:
+      return "SIGNED";
+    case UNSIGNED:
+      return "UNSIGNED";
+    case FLOAT:
+      return "FLOAT";
+    case DOUBLE:
+      return "DOUBLE";
+    case CONST:
+      return "CONST";
+    case VOLATILE:
+      return "VOLATILE";
+    case VOID:
+      return "VOID";
+    case BIT:
+      return "BIT";
+    case STRUCT:
+      return "STRUCT";
+    case UNION:
+      return "UNION";
+    case ENUM:
+      return "ENUM";
+    case ELIPSIS:
+      return "ELIPSIS";
+    case RANGE:
+      return "RANGE";
+    case FAR:
+      return "FAR";
+    case CASE:
+      return "CASE";
+    case DEFAULT:
+      return "DEFAULT";
+    case IF:
+      return "IF";
+    case ELSE:
+      return "ELSE";
+    case SWITCH:
+      return "SWITCH";
+    case WHILE:
+      return "WHILE";
+    case DO:
+      return "DO";
+    case FOR:
+      return "FOR";
+    case GOTO:
+      return "GOTO";
+    case CONTINUE:
+      return "CONTINUE";
+    case BREAK:
+      return "BREAK";
+    case RETURN:
+      return "RETURN";
+    case INLINEASM:
+      return "INLINEASM";
+    case IFX:
+      return "IFX";
+    case ADDRESS_OF:
+      return "ADDRESS_OF";
+    case GET_VALUE_AT_ADDRESS:
+      return "GET_VALUE_AT_ADDRESS";
+    case SPIL:
+      return "SPIL";
+    case UNSPIL:
+      return "UNSPIL";
+    case GETHBIT:
+      return "GETHBIT";
+    case BITWISEAND:
+      return "BITWISEAND";
+    case UNARYMINUS:
+      return "UNARYMINUS";
+    case IPUSH:
+      return "IPUSH";
+    case IPOP:
+      return "IPOP";
+    case PCALL:
+      return "PCALL";
+    case ENDFUNCTION:
+      return "ENDFUNCTION";
+    case JUMPTABLE:
+      return "JUMPTABLE";
+    case RRC:
+      return "RRC";
+    case RLC:
+      return "RLC";
+    case CAST:
+      return "CAST";
+    case CALL:
+      return "CALL";
+    case PARAM:
+      return "PARAM  ";
+    case NULLOP:
+      return "NULLOP";
+    case BLOCK:
+      return "BLOCK";
+    case LABEL:
+      return "LABEL";
+    case RECEIVE:
+      return "RECEIVE";
+    case SEND:
+      return "SEND";
+    }
+  sprintf (buffer, "unkown op %d %c", op, op & 0xff);
+  return buffer;
+}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static char *
+debugLogRegType (short type)
+{
+
+  switch (type)
+    {
+    case REG_GPR:
+      return "REG_GPR";
+    case REG_PTR:
+      return "REG_PTR";
+    case REG_CND:
+      return "REG_CND";
+    }
+
+  sprintf (buffer, "unknown reg type %d", type);
+  return buffer;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static int regname2key(char const *name)
+{
+  int key = 0;
+
+  if(!name)
+    return 0;
+
+  while(*name) {
+
+    key += (*name++) + 1;
+
+  }
+
+  return ( (key + (key >> 4) + (key>>8)) & 0x3f);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* newReg - allocate and init memory for a new register            */
+/*-----------------------------------------------------------------*/
+static regs* newReg(short type, short pc_type, int rIdx, char *name, int size, int alias)
+{
+
+  regs *dReg;
+
+  dReg = Safe_calloc(1,sizeof(regs));
+  dReg->type = type;
+  dReg->pc_type = pc_type;
+  dReg->rIdx = rIdx;
+  if(name) 
+    dReg->name = Safe_strdup(name);
+  else {
+    sprintf(buffer,"r0x%02X", dReg->rIdx);
+    if(type == REG_STK)
+      *buffer = 's';
+    dReg->name = Safe_strdup(buffer);
+  }
+  //fprintf(stderr,"newReg: %s, rIdx = 0x%02x\n",dReg->name,rIdx);
+  dReg->isFree = 0;
+  dReg->wasUsed = 1;
+  if(type == REG_SFR)
+    dReg->isFixed = 1;
+  else
+    dReg->isFixed = 0;
+
+  dReg->isMapped = 0;
+  dReg->isEmitted = 0;
+  dReg->address = 0;
+  dReg->size = size;
+  dReg->alias = alias;
+  dReg->reg_alias = NULL;
+  dReg->reglives.usedpFlows = newSet();
+  dReg->reglives.assignedpFlows = newSet();
+
+  hTabAddItem(&dynDirectRegNames, regname2key(name), dReg);
+
+  return dReg;
+}
+
+/*-----------------------------------------------------------------*/
+/* regWithIdx - Search through a set of registers that matches idx */
+/*-----------------------------------------------------------------*/
+static regs *
+regWithIdx (set *dRegs, int idx, int fixed)
+{
+  regs *dReg;
+
+  for (dReg = setFirstItem(dRegs) ; dReg ; 
+       dReg = setNextItem(dRegs)) {
+
+    if(idx == dReg->rIdx && (fixed == dReg->isFixed)) {
+      return dReg;
+    }
+  }
+
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* regFindFree - Search for a free register in a set of registers  */
+/*-----------------------------------------------------------------*/
+static regs *
+regFindFree (set *dRegs)
+{
+  regs *dReg;
+
+  for (dReg = setFirstItem(dRegs) ; dReg ; 
+       dReg = setNextItem(dRegs)) {
+
+    if(dReg->isFree)
+      return dReg;
+  }
+
+  return NULL;
+}
+/*-----------------------------------------------------------------*/
+/* pic16_initStack - allocate registers for a pseudo stack               */
+/*-----------------------------------------------------------------*/
+void pic16_initStack(int base_address, int size)
+{
+
+  int i;
+
+  pic16_Gstack_base_addr = base_address;
+  //fprintf(stderr,"initStack");
+
+  for(i = 0; i<size; i++)
+    addSet(&pic16_dynStackRegs,newReg(REG_STK, PO_GPR_TEMP,base_address++,NULL,1,0));
+}
+
+/*-----------------------------------------------------------------*
+ *-----------------------------------------------------------------*/
+regs *
+pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias)
+{
+
+  //fprintf(stderr,"pic16_allocProcessorRegister %s addr =0x%x\n",name,rIdx);
+  return addSet(&pic16_dynProcessorRegs,newReg(REG_SFR, po_type, rIdx, name,1,alias));
+}
+
+/*-----------------------------------------------------------------*
+ *-----------------------------------------------------------------*/
+
+regs *
+pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias)
+{
+  regs * reg = newReg(REG_GPR, po_type, rIdx, name,1,alias);
+
+  //fprintf(stderr,"pic16_allocInternalRegister %s addr =0x%x\n",name,rIdx);
+  if(reg) {
+    reg->wasUsed = 0;
+    return addSet(&pic16_dynInternalRegs,reg);
+  }
+
+  return NULL;
+}
+/*-----------------------------------------------------------------*/
+/* allocReg - allocates register of given type                     */
+/*-----------------------------------------------------------------*/
+static regs *
+allocReg (short type)
+{
+
+  debugLog ("%s of type %s\n", __FUNCTION__, debugLogRegType (type));
+  //fprintf(stderr,"allocReg\n");
+
+
+  return addSet(&pic16_dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0));
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/* pic16_dirregWithName - search for register by name                    */
+/*-----------------------------------------------------------------*/
+regs *
+pic16_dirregWithName (char *name)
+{
+  int hkey;
+  regs *reg;
+
+  if(!name)
+    return NULL;
+
+  /* hash the name to get a key */
+
+  hkey = regname2key(name);
+
+  reg = hTabFirstItemWK(dynDirectRegNames, hkey);
+
+  while(reg) {
+
+    if(STRCASECMP(reg->name, name) == 0) {
+      return(reg);
+    }
+
+    reg = hTabNextItemWK (dynDirectRegNames);
+  
+  }
+
+  return NULL; // name wasn't found in the hash table
+}
+
+static int IS_CONFIG_ADDRESS(int address)
+{
+
+  return address >= 0x300000 && address <= 0x300000d;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_allocDirReg - allocates register of given type                  */
+/*-----------------------------------------------------------------*/
+regs *
+pic16_allocDirReg (operand *op )
+{
+
+  regs *reg;
+  char *name;
+
+  if(!IS_SYMOP(op)) {
+    debugLog ("%s BAD, op is NULL\n", __FUNCTION__);
+    return NULL;
+  }
+
+  name = OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name;
+
+  /* If the symbol is at a fixed address, then remove the leading underscore
+   * from the name. This is hack to allow the .asm include file named registers
+   * to match the .c declared register names */
+
+  //if (SPEC_ABSA ( OP_SYM_ETYPE(op)) && (*name == '_'))
+  //name++;
+
+  debugLog ("%s symbol name %s\n", __FUNCTION__,name);
+  {
+    if(SPEC_CONST ( OP_SYM_ETYPE(op)) && (IS_CHAR ( OP_SYM_ETYPE(op)) )) {
+      debugLog(" %d  const char\n",__LINE__);
+      debugLog(" value = %s \n",SPEC_CVAL( OP_SYM_ETYPE(op)));
+    }
+
+    debugLog("  %d  storage class %d \n",__LINE__,SPEC_SCLS( OP_SYM_ETYPE(op)));
+    if (IS_CODE ( OP_SYM_ETYPE(op)) )
+      debugLog(" %d  code space\n",__LINE__);
+
+    if (IS_INTEGRAL ( OP_SYM_ETYPE(op)) )
+      debugLog(" %d  integral\n",__LINE__);
+    if (IS_LITERAL ( OP_SYM_ETYPE(op)) )
+      debugLog(" %d  literal\n",__LINE__);
+    if (IS_SPEC ( OP_SYM_ETYPE(op)) )
+      debugLog(" %d  specifier\n",__LINE__);
+    debugAopGet(NULL, op);
+  }
+
+  if (IS_CODE ( OP_SYM_ETYPE(op)) )
+    return NULL;
+
+  /* First, search the hash table to see if there is a register with this name */
+  if (SPEC_ABSA ( OP_SYM_ETYPE(op)) && !(IS_BITVAR (OP_SYM_ETYPE(op))) ) {
+    reg = regWithIdx (pic16_dynProcessorRegs, SPEC_ADDR ( OP_SYM_ETYPE(op)), 1);
+/*
+    if(!reg) 
+      fprintf(stderr,"ralloc %s is at fixed address but not a processor reg, addr=0x%x\n",
+             name, SPEC_ADDR ( OP_SYM_ETYPE(op)));
+    else
+      fprintf(stderr,"ralloc %s at fixed address has already been declared, addr=0x%x\n",
+             name, SPEC_ADDR ( OP_SYM_ETYPE(op)));
+*/
+  } else {
+    //fprintf(stderr,"ralloc:%d %s \n", __LINE__,name);
+    
+    reg = pic16_dirregWithName(name);
+  }
+
+  if(!reg) {
+    int address = 0;
+
+    /* if this is at an absolute address, then get the address. */
+    if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
+      address = SPEC_ADDR ( OP_SYM_ETYPE(op));
+      //fprintf(stderr,"reg %s is at an absolute address: 0x%03x\n",name,address);
+    }
+
+    /* Register wasn't found in hash, so let's create
+     * a new one and put it in the hash table AND in the 
+     * dynDirectRegNames set */
+    if(!IS_CONFIG_ADDRESS(address)) {
+      //fprintf(stderr,"allocating new reg %s\n",name);
+
+      reg = newReg(REG_GPR, PO_DIR, rDirectIdx++, name,getSize (OP_SYMBOL (op)->type),0 );
+      debugLog ("  -- added %s to hash, size = %d\n", name,reg->size);
+
+      //hTabAddItem(&dynDirectRegNames, regname2key(name), reg);
+
+      if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
+
+       //fprintf(stderr, " ralloc.c at fixed address: %s - changing to REG_SFR\n",name);
+       reg->type = REG_SFR;
+      }
+
+      if (IS_BITVAR (OP_SYM_ETYPE(op))) {
+       addSet(&pic16_dynDirectBitRegs, reg);
+       reg->isBitField = 1;
+      } else
+       addSet(&pic16_dynDirectRegs, reg);
+
+    } else {
+      debugLog ("  -- %s is declared at address 0x30000x\n",name);
+
+    }
+  }
+
+  if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
+    reg->isFixed = 1;
+    reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op));
+    debugLog ("  -- and it is at a fixed address 0x%02x\n",reg->address);
+  }
+
+  return reg;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_allocRegByName - allocates register of given type                  */
+/*-----------------------------------------------------------------*/
+regs *
+pic16_allocRegByName (char *name, int size)
+{
+
+  regs *reg;
+
+  if(!name) {
+    fprintf(stderr, "%s - allocating a NULL register\n",__FUNCTION__);
+    exit(1);
+  }
+
+  /* First, search the hash table to see if there is a register with this name */
+  reg = pic16_dirregWithName(name);
+
+  if(!reg) {
+
+    /* Register wasn't found in hash, so let's create
+     * a new one and put it in the hash table AND in the 
+     * dynDirectRegNames set */
+    //fprintf (stderr,"%s symbol name %s\n", __FUNCTION__,name);
+    reg = newReg(REG_GPR, PO_DIR, rDirectIdx++, name,size,0 );
+
+    debugLog ("  -- added %s to hash, size = %d\n", name,reg->size);
+
+    //hTabAddItem(&dynDirectRegNames, regname2key(name), reg);
+    addSet(&pic16_dynDirectRegs, reg);
+  }
+
+  return reg;
+}
+
+/*-----------------------------------------------------------------*/
+/* RegWithIdx - returns pointer to register with index number       */
+/*-----------------------------------------------------------------*/
+static regs *
+typeRegWithIdx (int idx, int type, int fixed)
+{
+
+  regs *dReg;
+
+  debugLog ("%s - requesting index = 0x%x\n", __FUNCTION__,idx);
+
+  switch (type) {
+
+  case REG_GPR:
+    if( (dReg = regWithIdx ( pic16_dynAllocRegs, idx, fixed)) != NULL) {
+
+      debugLog ("Found a Dynamic Register!\n");
+      return dReg;
+    }
+    if( (dReg = regWithIdx ( pic16_dynDirectRegs, idx, fixed)) != NULL ) {
+      debugLog ("Found a Direct Register!\n");
+      return dReg;
+    }
+
+    break;
+  case REG_STK:
+    if( (dReg = regWithIdx ( pic16_dynStackRegs, idx, fixed)) != NULL ) {
+      debugLog ("Found a Stack Register!\n");
+      return dReg;
+    }
+    break;
+  case REG_SFR:
+    if( (dReg = regWithIdx ( pic16_dynProcessorRegs, idx, fixed)) != NULL ) {
+      debugLog ("Found a Processor Register!\n");
+      return dReg;
+    }
+
+  case REG_CND:
+  case REG_PTR:
+  default:
+    break;
+  }
+
+
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_regWithIdx - returns pointer to register with index number*/
+/*-----------------------------------------------------------------*/
+regs *
+pic16_regWithIdx (int idx)
+{
+  regs *dReg;
+
+  if( (dReg = typeRegWithIdx(idx,REG_GPR,0)) != NULL)
+    return dReg;
+
+  if( (dReg = typeRegWithIdx(idx,REG_SFR,0)) != NULL)
+    return dReg;
+
+  if( (dReg = typeRegWithIdx(idx,REG_STK,0)) != NULL)
+    return dReg;
+
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* pic16_regWithIdx - returns pointer to register with index number       */
+/*-----------------------------------------------------------------*/
+regs *
+pic16_allocWithIdx (int idx)
+{
+
+  regs *dReg;
+
+  debugLog ("%s - allocating with index = 0x%x\n", __FUNCTION__,idx);
+
+  if( (dReg = regWithIdx ( pic16_dynAllocRegs, idx,0)) != NULL) {
+
+    debugLog ("Found a Dynamic Register!\n");
+  } else if( (dReg = regWithIdx ( pic16_dynStackRegs, idx,0)) != NULL ) {
+    debugLog ("Found a Stack Register!\n");
+  } else if( (dReg = regWithIdx ( pic16_dynProcessorRegs, idx,0)) != NULL ) {
+    debugLog ("Found a Processor Register!\n");
+  } else if( (dReg = regWithIdx ( pic16_dynInternalRegs, idx,0)) != NULL ) {
+    debugLog ("Found an Internal Register!\n");
+  } else {
+    
+    debugLog ("Dynamic Register not found\n");
+
+
+    //fprintf(stderr,"%s %d - requested register: 0x%x\n",__FUNCTION__,__LINE__,idx);
+    werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+           "regWithIdx not found");
+    exit (1);
+
+  }
+
+  dReg->wasUsed = 1;
+  dReg->isFree = 0;
+
+  return dReg;
+}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+regs *
+pic16_findFreeReg(short type)
+{
+  //  int i;
+  regs* dReg;
+
+  switch (type) {
+  case REG_GPR:
+    if((dReg = regFindFree(pic16_dynAllocRegs)) != NULL)
+      return dReg;
+    return addSet(&pic16_dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0));
+
+  case REG_STK:
+
+    if((dReg = regFindFree(pic16_dynStackRegs)) != NULL)
+      return dReg;
+
+    return NULL;
+
+  case REG_PTR:
+  case REG_CND:
+  case REG_SFR:
+  default:
+    return NULL;
+  }
+}
+/*-----------------------------------------------------------------*/
+/* freeReg - frees a register                                      */
+/*-----------------------------------------------------------------*/
+static void
+freeReg (regs * reg)
+{
+  debugLog ("%s\n", __FUNCTION__);
+  reg->isFree = 1;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* nFreeRegs - returns number of free registers                    */
+/*-----------------------------------------------------------------*/
+static int
+nFreeRegs (int type)
+{
+  /* dynamically allocate as many as we need and worry about
+   * fitting them into a PIC later */
+
+  return 100;
+#if 0
+  int i;
+  int nfr = 0;
+
+  debugLog ("%s\n", __FUNCTION__);
+  for (i = 0; i < pic16_nRegs; i++)
+    if (regspic16[i].isFree && regspic16[i].type == type)
+      nfr++;
+  return nfr;
+#endif
+}
+
+/*-----------------------------------------------------------------*/
+/* nfreeRegsType - free registers with type                         */
+/*-----------------------------------------------------------------*/
+static int
+nfreeRegsType (int type)
+{
+  int nfr;
+  debugLog ("%s\n", __FUNCTION__);
+  if (type == REG_PTR)
+    {
+      if ((nfr = nFreeRegs (type)) == 0)
+       return nFreeRegs (REG_GPR);
+    }
+
+  return nFreeRegs (type);
+}
+
+static void writeSetUsedRegs(FILE *of, set *dRegs)
+{
+
+  regs *dReg;
+
+  for (dReg = setFirstItem(dRegs) ; dReg ; 
+       dReg = setNextItem(dRegs)) {
+
+    if(dReg->wasUsed)
+      fprintf (of, "\t%s\n",dReg->name);
+  }
+
+}
+extern void pic16_assignFixedRegisters(set *regset);
+extern void pic16_assignRelocatableRegisters(set *regset,int used);
+extern void pic16_dump_map(void);
+extern void pic16_dump_cblock(FILE *of);
+
+
+static void packBits(set *bregs)
+{
+  set *regset;
+  regs *breg;
+  regs *bitfield=NULL;
+  regs *relocbitfield=NULL;
+  int bit_no=0;
+  int byte_no=-1;
+  char buffer[20];
+
+
+  for (regset = bregs ; regset ;
+       regset = regset->next) {
+
+    breg = regset->item;
+    breg->isBitField = 1;
+    //fprintf(stderr,"bit reg: %s\n",breg->name);
+
+    if(breg->isFixed) {
+      //fprintf(stderr,"packing bit at fixed address = 0x%03x\n",breg->address);
+
+      bitfield = typeRegWithIdx (breg->address >> 3, -1 , 1);
+      breg->rIdx = breg->address & 7;
+      breg->address >>= 3;
+
+      if(!bitfield) {
+       sprintf (buffer, "fbitfield%02x", breg->address);
+       //fprintf(stderr,"new bit field\n");
+       bitfield = newReg(REG_SFR, PO_GPR_BIT,breg->address,buffer,1,0);
+       bitfield->isBitField = 1;
+       bitfield->isFixed = 1;
+       bitfield->address = breg->address;
+       addSet(&pic16_dynDirectRegs,bitfield);
+       //hTabAddItem(&dynDirectRegNames, regname2key(buffer), bitfield);
+      } else {
+       //fprintf(stderr,"  which is occupied by %s (addr = %d)\n",bitfield->name,bitfield->address);
+       ;
+      }
+      breg->reg_alias = bitfield;
+      bitfield = NULL;
+
+    } else {
+      if(!relocbitfield || bit_no >7) {
+       byte_no++;
+       bit_no=0;
+       sprintf (buffer, "bitfield%d", byte_no);
+       //fprintf(stderr,"new relocatable bit field\n");
+       relocbitfield = newReg(REG_GPR, PO_GPR_BIT,rDirectIdx++,buffer,1,0);
+       relocbitfield->isBitField = 1;
+       addSet(&pic16_dynDirectRegs,relocbitfield);
+       //hTabAddItem(&dynDirectRegNames, regname2key(buffer), relocbitfield);
+
+      }
+
+      breg->reg_alias = relocbitfield;
+      breg->address = rDirectIdx;   /* byte_no; */
+      breg->rIdx = bit_no++;
+    }
+  }
+      
+}
+
+
+
+static void bitEQUs(FILE *of, set *bregs)
+{
+  regs *breg,*bytereg;
+  int bit_no=0;
+
+  //fprintf(stderr," %s\n",__FUNCTION__);
+  for (breg = setFirstItem(bregs) ; breg ;
+       breg = setNextItem(bregs)) {
+
+    //fprintf(stderr,"bit reg: %s\n",breg->name);
+
+    bytereg = breg->reg_alias;
+    if(bytereg)
+      fprintf (of, "%s\tEQU\t( (%s<<3)+%d)\n",
+              breg->name,
+              bytereg->name,
+              breg->rIdx & 0x0007);
+
+    else {
+      fprintf(stderr, "bit field is not assigned to a register\n");
+      fprintf (of, "%s\tEQU\t( (bitfield%d<<3)+%d)\n",
+              breg->name,
+              bit_no>>3,
+              bit_no & 0x0007);
+
+      bit_no++;
+    }
+  }
+      
+}
+
+static void aliasEQUs(FILE *of, set *fregs, int use_rIdx)
+{
+  regs *reg;
+
+
+  for (reg = setFirstItem(fregs) ; reg ;
+       reg = setNextItem(fregs)) {
+
+    if(!reg->isEmitted && reg->wasUsed) {
+      if(use_rIdx) {
+        if (reg->type != REG_SFR) {
+         fprintf (of, "%s\tEQU\t0x%03x\n",
+                  reg->name,
+                  reg->rIdx);
+        }
+      }
+      else
+       fprintf (of, "%s\tEQU\t0x%03x\n",
+                reg->name,
+                reg->address);
+    }
+  }
+      
+}
+
+void pic16_writeUsedRegs(FILE *of) 
+{
+  packBits(pic16_dynDirectBitRegs);
+
+
+  pic16_assignFixedRegisters(pic16_dynAllocRegs);
+  pic16_assignFixedRegisters(pic16_dynStackRegs);
+  pic16_assignFixedRegisters(pic16_dynDirectRegs);
+
+  pic16_assignRelocatableRegisters(pic16_dynInternalRegs,0);
+  pic16_assignRelocatableRegisters(pic16_dynAllocRegs,0);
+  pic16_assignRelocatableRegisters(pic16_dynStackRegs,0);
+  pic16_assignRelocatableRegisters(pic16_dynDirectRegs,0);
+
+  //pic16_dump_map();
+
+  pic16_dump_cblock(of);
+  bitEQUs(of,pic16_dynDirectBitRegs);
+  aliasEQUs(of,pic16_dynAllocRegs,0);
+  aliasEQUs(of,pic16_dynDirectRegs,0);
+  aliasEQUs(of,pic16_dynStackRegs,0);
+  aliasEQUs(of,pic16_dynProcessorRegs,1);
+
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* allDefsOutOfRange - all definitions are out of a range          */
+/*-----------------------------------------------------------------*/
+static bool
+allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
+{
+  int i;
+
+  debugLog ("%s\n", __FUNCTION__);
+  if (!defs)
+    return TRUE;
+
+  for (i = 0; i < defs->size; i++)
+    {
+      iCode *ic;
+
+      if (bitVectBitValue (defs, i) &&
+         (ic = hTabItemWithKey (iCodehTab, i)) &&
+         (ic->seq >= fseq && ic->seq <= toseq))
+
+       return FALSE;
+
+    }
+
+  return TRUE;
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* computeSpillable - given a point find the spillable live ranges */
+/*-----------------------------------------------------------------*/
+static bitVect *
+computeSpillable (iCode * ic)
+{
+  bitVect *spillable;
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* spillable live ranges are those that are live at this 
+     point . the following categories need to be subtracted
+     from this set. 
+     a) - those that are already spilt
+     b) - if being used by this one
+     c) - defined by this one */
+
+  spillable = bitVectCopy (ic->rlive);
+  spillable =
+    bitVectCplAnd (spillable, _G.spiltSet);    /* those already spilt */
+  spillable =
+    bitVectCplAnd (spillable, ic->uses);       /* used in this one */
+  bitVectUnSetBit (spillable, ic->defKey);
+  spillable = bitVectIntersect (spillable, _G.regAssigned);
+  return spillable;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* noSpilLoc - return true if a variable has no spil location      */
+/*-----------------------------------------------------------------*/
+static int
+noSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  debugLog ("%s\n", __FUNCTION__);
+  return (sym->usl.spillLoc ? 0 : 1);
+}
+
+/*-----------------------------------------------------------------*/
+/* hasSpilLoc - will return 1 if the symbol has spil location      */
+/*-----------------------------------------------------------------*/
+static int
+hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  debugLog ("%s\n", __FUNCTION__);
+  return (sym->usl.spillLoc ? 1 : 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* directSpilLoc - will return 1 if the splilocation is in direct  */
+/*-----------------------------------------------------------------*/
+static int
+directSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  debugLog ("%s\n", __FUNCTION__);
+  if (sym->usl.spillLoc &&
+      (IN_DIRSPACE (SPEC_OCLS (sym->usl.spillLoc->etype))))
+    return 1;
+  else
+    return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* hasSpilLocnoUptr - will return 1 if the symbol has spil location */
+/*                    but is not used as a pointer                 */
+/*-----------------------------------------------------------------*/
+static int
+hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  debugLog ("%s\n", __FUNCTION__);
+  return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* rematable - will return 1 if the remat flag is set              */
+/*-----------------------------------------------------------------*/
+static int
+rematable (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  debugLog ("%s\n", __FUNCTION__);
+  return sym->remat;
+}
+
+/*-----------------------------------------------------------------*/
+/* notUsedInRemaining - not used or defined in remain of the block */
+/*-----------------------------------------------------------------*/
+static int
+notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  debugLog ("%s\n", __FUNCTION__);
+  return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
+         allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
+}
+
+/*-----------------------------------------------------------------*/
+/* allLRs - return true for all                                    */
+/*-----------------------------------------------------------------*/
+static int
+allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  debugLog ("%s\n", __FUNCTION__);
+  return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* liveRangesWith - applies function to a given set of live range  */
+/*-----------------------------------------------------------------*/
+static set *
+liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
+               eBBlock * ebp, iCode * ic)
+{
+  set *rset = NULL;
+  int i;
+
+  debugLog ("%s\n", __FUNCTION__);
+  if (!lrs || !lrs->size)
+    return NULL;
+
+  for (i = 1; i < lrs->size; i++)
+    {
+      symbol *sym;
+      if (!bitVectBitValue (lrs, i))
+       continue;
+
+      /* if we don't find it in the live range 
+         hash table we are in serious trouble */
+      if (!(sym = hTabItemWithKey (liveRanges, i)))
+       {
+         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                 "liveRangesWith could not find liveRange");
+         exit (1);
+       }
+
+      if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
+       addSetHead (&rset, sym);
+    }
+
+  return rset;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* leastUsedLR - given a set determines which is the least used    */
+/*-----------------------------------------------------------------*/
+static symbol *
+leastUsedLR (set * sset)
+{
+  symbol *sym = NULL, *lsym = NULL;
+
+  debugLog ("%s\n", __FUNCTION__);
+  sym = lsym = setFirstItem (sset);
+
+  if (!lsym)
+    return NULL;
+
+  for (; lsym; lsym = setNextItem (sset))
+    {
+
+      /* if usage is the same then prefer
+         the spill the smaller of the two */
+      if (lsym->used == sym->used)
+       if (getSize (lsym->type) < getSize (sym->type))
+         sym = lsym;
+
+      /* if less usage */
+      if (lsym->used < sym->used)
+       sym = lsym;
+
+    }
+
+  setToNull ((void **) &sset);
+  sym->blockSpil = 0;
+  return sym;
+}
+
+/*-----------------------------------------------------------------*/
+/* noOverLap - will iterate through the list looking for over lap  */
+/*-----------------------------------------------------------------*/
+static int
+noOverLap (set * itmpStack, symbol * fsym)
+{
+  symbol *sym;
+  debugLog ("%s\n", __FUNCTION__);
+
+
+  for (sym = setFirstItem (itmpStack); sym;
+       sym = setNextItem (itmpStack))
+    {
+      if (sym->liveTo > fsym->liveFrom)
+       return 0;
+
+    }
+
+  return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* isFree - will return 1 if the a free spil location is found     */
+/*-----------------------------------------------------------------*/
+static
+DEFSETFUNC (isFree)
+{
+  symbol *sym = item;
+  V_ARG (symbol **, sloc);
+  V_ARG (symbol *, fsym);
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* if already found */
+  if (*sloc)
+    return 0;
+
+  /* if it is free && and the itmp assigned to
+     this does not have any overlapping live ranges
+     with the one currently being assigned and
+     the size can be accomodated  */
+  if (sym->isFree &&
+      noOverLap (sym->usl.itmpStack, fsym) &&
+      getSize (sym->type) >= getSize (fsym->type))
+    {
+      *sloc = sym;
+      return 1;
+    }
+
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* spillLRWithPtrReg :- will spil those live ranges which use PTR  */
+/*-----------------------------------------------------------------*/
+static void
+spillLRWithPtrReg (symbol * forSym)
+{
+  symbol *lrsym;
+  regs *r0, *r1;
+  int k;
+
+  debugLog ("%s\n", __FUNCTION__);
+  if (!_G.regAssigned ||
+      bitVectIsZero (_G.regAssigned))
+    return;
+
+  r0 = pic16_regWithIdx (R0_IDX);
+  r1 = pic16_regWithIdx (R1_IDX);
+
+  /* for all live ranges */
+  for (lrsym = hTabFirstItem (liveRanges, &k); lrsym;
+       lrsym = hTabNextItem (liveRanges, &k))
+    {
+      int j;
+
+      /* if no registers assigned to it or
+         spilt */
+      /* if it does not overlap with this then 
+         not need to spill it */
+
+      if (lrsym->isspilt || !lrsym->nRegs ||
+         (lrsym->liveTo < forSym->liveFrom))
+       continue;
+
+      /* go thru the registers : if it is either
+         r0 or r1 then spil it */
+      for (j = 0; j < lrsym->nRegs; j++)
+       if (lrsym->regs[j] == r0 ||
+           lrsym->regs[j] == r1)
+         {
+           spillThis (lrsym);
+           break;
+         }
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* createStackSpil - create a location on the stack to spil        */
+/*-----------------------------------------------------------------*/
+static symbol *
+createStackSpil (symbol * sym)
+{
+  symbol *sloc = NULL;
+  int useXstack, model, noOverlay;
+
+  char slocBuffer[30];
+  debugLog ("%s\n", __FUNCTION__);
+
+  /* first go try and find a free one that is already 
+     existing on the stack */
+  if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
+    {
+      /* found a free one : just update & return */
+      sym->usl.spillLoc = sloc;
+      sym->stackSpil = 1;
+      sloc->isFree = 0;
+      addSetHead (&sloc->usl.itmpStack, sym);
+      return sym;
+    }
+
+  /* could not then have to create one , this is the hard part
+     we need to allocate this on the stack : this is really a
+     hack!! but cannot think of anything better at this time */
+
+  if (sprintf (slocBuffer, "sloc%d", _G.slocNum++) >= sizeof (slocBuffer))
+    {
+      fprintf (stderr, "kkkInternal error: slocBuffer overflowed: %s:%d\n",
+              __FILE__, __LINE__);
+      exit (1);
+    }
+
+  sloc = newiTemp (slocBuffer);
+
+  /* set the type to the spilling symbol */
+  sloc->type = copyLinkChain (sym->type);
+  sloc->etype = getSpec (sloc->type);
+  SPEC_SCLS (sloc->etype) = S_DATA;
+  SPEC_EXTR (sloc->etype) = 0;
+  SPEC_STAT (sloc->etype) = 0;
+
+  /* we don't allow it to be allocated`
+     onto the external stack since : so we
+     temporarily turn it off ; we also
+     turn off memory model to prevent
+     the spil from going to the external storage
+     and turn off overlaying 
+   */
+
+  useXstack = options.useXstack;
+  model = options.model;
+  noOverlay = options.noOverlay;
+  options.noOverlay = 1;
+  options.model = options.useXstack = 0;
+
+  allocLocal (sloc);
+
+  options.useXstack = useXstack;
+  options.model = model;
+  options.noOverlay = noOverlay;
+  sloc->isref = 1;             /* to prevent compiler warning */
+
+  /* if it is on the stack then update the stack */
+  if (IN_STACK (sloc->etype))
+    {
+      currFunc->stack += getSize (sloc->type);
+      _G.stackExtend += getSize (sloc->type);
+    }
+  else
+    _G.dataExtend += getSize (sloc->type);
+
+  /* add it to the _G.stackSpil set */
+  addSetHead (&_G.stackSpil, sloc);
+  sym->usl.spillLoc = sloc;
+  sym->stackSpil = 1;
+
+  /* add it to the set of itempStack set 
+     of the spill location */
+  addSetHead (&sloc->usl.itmpStack, sym);
+  return sym;
+}
+
+/*-----------------------------------------------------------------*/
+/* isSpiltOnStack - returns true if the spil location is on stack  */
+/*-----------------------------------------------------------------*/
+static bool
+isSpiltOnStack (symbol * sym)
+{
+  sym_link *etype;
+
+  debugLog ("%s\n", __FUNCTION__);
+  if (!sym)
+    return FALSE;
+
+  if (!sym->isspilt)
+    return FALSE;
+
+/*     if (sym->_G.stackSpil) */
+/*      return TRUE; */
+
+  if (!sym->usl.spillLoc)
+    return FALSE;
+
+  etype = getSpec (sym->usl.spillLoc->type);
+  if (IN_STACK (etype))
+    return TRUE;
+
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* spillThis - spils a specific operand                            */
+/*-----------------------------------------------------------------*/
+static void
+spillThis (symbol * sym)
+{
+  int i;
+  debugLog ("%s : %s\n", __FUNCTION__, sym->rname);
+
+  /* if this is rematerializable or has a spillLocation
+     we are okay, else we need to create a spillLocation
+     for it */
+  if (!(sym->remat || sym->usl.spillLoc))
+    createStackSpil (sym);
+
+
+  /* mark it has spilt & put it in the spilt set */
+  sym->isspilt = 1;
+  _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
+
+  bitVectUnSetBit (_G.regAssigned, sym->key);
+
+  for (i = 0; i < sym->nRegs; i++)
+
+    if (sym->regs[i])
+      {
+       freeReg (sym->regs[i]);
+       sym->regs[i] = NULL;
+      }
+
+  /* if spilt on stack then free up r0 & r1 
+     if they could have been assigned to some
+     LIVE ranges */
+  if (!pic16_ptrRegReq && isSpiltOnStack (sym))
+    {
+      pic16_ptrRegReq++;
+      spillLRWithPtrReg (sym);
+    }
+
+  if (sym->usl.spillLoc && !sym->remat)
+    sym->usl.spillLoc->allocreq = 1;
+  return;
+}
+
+/*-----------------------------------------------------------------*/
+/* selectSpil - select a iTemp to spil : rather a simple procedure */
+/*-----------------------------------------------------------------*/
+static symbol *
+selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
+{
+  bitVect *lrcs = NULL;
+  set *selectS;
+  symbol *sym;
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* get the spillable live ranges */
+  lrcs = computeSpillable (ic);
+
+  /* get all live ranges that are rematerizable */
+  if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
+    {
+
+      /* return the least used of these */
+      return leastUsedLR (selectS);
+    }
+
+  /* get live ranges with spillLocations in direct space */
+  if ((selectS = liveRangesWith (lrcs, directSpilLoc, ebp, ic)))
+    {
+      sym = leastUsedLR (selectS);
+      strcpy (sym->rname, (sym->usl.spillLoc->rname[0] ?
+                          sym->usl.spillLoc->rname :
+                          sym->usl.spillLoc->name));
+      sym->spildir = 1;
+      /* mark it as allocation required */
+      sym->usl.spillLoc->allocreq = 1;
+      return sym;
+    }
+
+  /* if the symbol is local to the block then */
+  if (forSym->liveTo < ebp->lSeq)
+    {
+
+      /* check if there are any live ranges allocated
+         to registers that are not used in this block */
+      if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
+       {
+         sym = leastUsedLR (selectS);
+         /* if this is not rematerializable */
+         if (!sym->remat)
+           {
+             _G.blockSpil++;
+             sym->blockSpil = 1;
+           }
+         return sym;
+       }
+
+      /* check if there are any live ranges that not
+         used in the remainder of the block */
+      if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
+       {
+         sym = leastUsedLR (selectS);
+         if (!sym->remat)
+           {
+             sym->remainSpil = 1;
+             _G.blockSpil++;
+           }
+         return sym;
+       }
+    }
+
+  /* find live ranges with spillocation && not used as pointers */
+  if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
+    {
+
+      sym = leastUsedLR (selectS);
+      /* mark this as allocation required */
+      sym->usl.spillLoc->allocreq = 1;
+      return sym;
+    }
+
+  /* find live ranges with spillocation */
+  if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
+    {
+
+      sym = leastUsedLR (selectS);
+      sym->usl.spillLoc->allocreq = 1;
+      return sym;
+    }
+
+  /* couldn't find then we need to create a spil
+     location on the stack , for which one? the least
+     used ofcourse */
+  if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
+    {
+
+      /* return a created spil location */
+      sym = createStackSpil (leastUsedLR (selectS));
+      sym->usl.spillLoc->allocreq = 1;
+      return sym;
+    }
+
+  /* this is an extreme situation we will spill
+     this one : happens very rarely but it does happen */
+  spillThis (forSym);
+  return forSym;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* spilSomething - spil some variable & mark registers as free     */
+/*-----------------------------------------------------------------*/
+static bool
+spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
+{
+  symbol *ssym;
+  int i;
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* get something we can spil */
+  ssym = selectSpil (ic, ebp, forSym);
+
+  /* mark it as spilt */
+  ssym->isspilt = 1;
+  _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
+
+  /* mark it as not register assigned &
+     take it away from the set */
+  bitVectUnSetBit (_G.regAssigned, ssym->key);
+
+  /* mark the registers as free */
+  for (i = 0; i < ssym->nRegs; i++)
+    if (ssym->regs[i])
+      freeReg (ssym->regs[i]);
+
+  /* if spilt on stack then free up r0 & r1 
+     if they could have been assigned to as gprs */
+  if (!pic16_ptrRegReq && isSpiltOnStack (ssym))
+    {
+      pic16_ptrRegReq++;
+      spillLRWithPtrReg (ssym);
+    }
+
+  /* if this was a block level spil then insert push & pop 
+     at the start & end of block respectively */
+  if (ssym->blockSpil)
+    {
+      iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
+      /* add push to the start of the block */
+      addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
+                                   ebp->sch->next : ebp->sch));
+      nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
+      /* add pop to the end of the block */
+      addiCodeToeBBlock (ebp, nic, NULL);
+    }
+
+  /* if spilt because not used in the remainder of the
+     block then add a push before this instruction and
+     a pop at the end of the block */
+  if (ssym->remainSpil)
+    {
+
+      iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
+      /* add push just before this instruction */
+      addiCodeToeBBlock (ebp, nic, ic);
+
+      nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
+      /* add pop to the end of the block */
+      addiCodeToeBBlock (ebp, nic, NULL);
+    }
+
+  if (ssym == forSym)
+    return FALSE;
+  else
+    return TRUE;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegPtr - will try for PTR if not a GPR type if not spil      */
+/*-----------------------------------------------------------------*/
+static regs *
+getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym)
+{
+  regs *reg;
+
+  debugLog ("%s\n", __FUNCTION__);
+tryAgain:
+  /* try for a ptr type */
+  if ((reg = allocReg (REG_PTR)))
+    return reg;
+
+  /* try for gpr type */
+  if ((reg = allocReg (REG_GPR)))
+    return reg;
+
+  /* we have to spil */
+  if (!spilSomething (ic, ebp, sym))
+    return NULL;
+
+  /* this looks like an infinite loop but 
+     in really selectSpil will abort  */
+  goto tryAgain;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegGpr - will try for GPR if not spil                        */
+/*-----------------------------------------------------------------*/
+static regs *
+getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
+{
+  regs *reg;
+
+  debugLog ("%s\n", __FUNCTION__);
+tryAgain:
+  /* try for gpr type */
+  if ((reg = allocReg (REG_GPR)))
+    return reg;
+
+  if (!pic16_ptrRegReq)
+    if ((reg = allocReg (REG_PTR)))
+      return reg;
+
+  /* we have to spil */
+  if (!spilSomething (ic, ebp, sym))
+    return NULL;
+
+  /* this looks like an infinite loop but 
+     in really selectSpil will abort  */
+  goto tryAgain;
+}
+
+/*-----------------------------------------------------------------*/
+/* symHasReg - symbol has a given register                         */
+/*-----------------------------------------------------------------*/
+static bool
+symHasReg (symbol * sym, regs * reg)
+{
+  int i;
+
+  debugLog ("%s\n", __FUNCTION__);
+  for (i = 0; i < sym->nRegs; i++)
+    if (sym->regs[i] == reg)
+      return TRUE;
+
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* deassignLRs - check the live to and if they have registers & are */
+/*               not spilt then free up the registers              */
+/*-----------------------------------------------------------------*/
+static void
+deassignLRs (iCode * ic, eBBlock * ebp)
+{
+  symbol *sym;
+  int k;
+  symbol *result;
+
+  debugLog ("%s\n", __FUNCTION__);
+  for (sym = hTabFirstItem (liveRanges, &k); sym;
+       sym = hTabNextItem (liveRanges, &k))
+    {
+
+      symbol *psym = NULL;
+      /* if it does not end here */
+      if (sym->liveTo > ic->seq)
+       continue;
+
+      /* if it was spilt on stack then we can 
+         mark the stack spil location as free */
+      if (sym->isspilt)
+       {
+         if (sym->stackSpil)
+           {
+             sym->usl.spillLoc->isFree = 1;
+             sym->stackSpil = 0;
+           }
+         continue;
+       }
+
+      if (!bitVectBitValue (_G.regAssigned, sym->key))
+       continue;
+
+      /* special case check if this is an IFX &
+         the privious one was a pop and the 
+         previous one was not spilt then keep track
+         of the symbol */
+      if (ic->op == IFX && ic->prev &&
+         ic->prev->op == IPOP &&
+         !ic->prev->parmPush &&
+         !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
+       psym = OP_SYMBOL (IC_LEFT (ic->prev));
+
+      if (sym->nRegs)
+       {
+         int i = 0;
+
+         bitVectUnSetBit (_G.regAssigned, sym->key);
+
+         /* if the result of this one needs registers
+            and does not have it then assign it right
+            away */
+         if (IC_RESULT (ic) &&
+             !(SKIP_IC2 (ic) ||        /* not a special icode */
+               ic->op == JUMPTABLE ||
+               ic->op == IFX ||
+               ic->op == IPUSH ||
+               ic->op == IPOP ||
+               ic->op == RETURN ||
+               POINTER_SET (ic)) &&
+             (result = OP_SYMBOL (IC_RESULT (ic))) &&  /* has a result */
+             result->liveTo > ic->seq &&       /* and will live beyond this */
+             result->liveTo <= ebp->lSeq &&    /* does not go beyond this block */
+             result->regType == sym->regType &&        /* same register types */
+             result->nRegs &&  /* which needs registers */
+             !result->isspilt &&       /* and does not already have them */
+             !result->remat &&
+             !bitVectBitValue (_G.regAssigned, result->key) &&
+         /* the number of free regs + number of regs in this LR
+            can accomodate the what result Needs */
+             ((nfreeRegsType (result->regType) +
+               sym->nRegs) >= result->nRegs)
+           )
+           {
+
+             for (i = 0; i < max (sym->nRegs, result->nRegs); i++)
+               if (i < sym->nRegs)
+                 result->regs[i] = sym->regs[i];
+               else
+                 result->regs[i] = getRegGpr (ic, ebp, result);
+
+             _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
+
+           }
+
+         /* free the remaining */
+         for (; i < sym->nRegs; i++)
+           {
+             if (psym)
+               {
+                 if (!symHasReg (psym, sym->regs[i]))
+                   freeReg (sym->regs[i]);
+               }
+             else
+               freeReg (sym->regs[i]);
+           }
+       }
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* reassignLR - reassign this to registers                         */
+/*-----------------------------------------------------------------*/
+static void
+reassignLR (operand * op)
+{
+  symbol *sym = OP_SYMBOL (op);
+  int i;
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* not spilt any more */
+  sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
+  bitVectUnSetBit (_G.spiltSet, sym->key);
+
+  _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+
+  _G.blockSpil--;
+
+  for (i = 0; i < sym->nRegs; i++)
+    sym->regs[i]->isFree = 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* willCauseSpill - determines if allocating will cause a spill    */
+/*-----------------------------------------------------------------*/
+static int
+willCauseSpill (int nr, int rt)
+{
+  debugLog ("%s\n", __FUNCTION__);
+  /* first check if there are any avlb registers
+     of te type required */
+  if (rt == REG_PTR)
+    {
+      /* special case for pointer type 
+         if pointer type not avlb then 
+         check for type gpr */
+      if (nFreeRegs (rt) >= nr)
+       return 0;
+      if (nFreeRegs (REG_GPR) >= nr)
+       return 0;
+    }
+  else
+    {
+      if (pic16_ptrRegReq)
+       {
+         if (nFreeRegs (rt) >= nr)
+           return 0;
+       }
+      else
+       {
+         if (nFreeRegs (REG_PTR) +
+             nFreeRegs (REG_GPR) >= nr)
+           return 0;
+       }
+    }
+
+  debugLog (" ... yep it will (cause a spill)\n");
+  /* it will cause a spil */
+  return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* positionRegs - the allocator can allocate same registers to res- */
+/* ult and operand, if this happens make sure they are in the same */
+/* position as the operand otherwise chaos results                 */
+/*-----------------------------------------------------------------*/
+static void
+positionRegs (symbol * result, symbol * opsym, int lineno)
+{
+  int count = min (result->nRegs, opsym->nRegs);
+  int i, j = 0, shared = 0;
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* if the result has been spilt then cannot share */
+  if (opsym->isspilt)
+    return;
+again:
+  shared = 0;
+  /* first make sure that they actually share */
+  for (i = 0; i < count; i++)
+    {
+      for (j = 0; j < count; j++)
+       {
+         if (result->regs[i] == opsym->regs[j] && i != j)
+           {
+             shared = 1;
+             goto xchgPositions;
+           }
+       }
+    }
+xchgPositions:
+  if (shared)
+    {
+      regs *tmp = result->regs[i];
+      result->regs[i] = result->regs[j];
+      result->regs[j] = tmp;
+      goto again;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* serialRegAssign - serially allocate registers to the variables  */
+/*-----------------------------------------------------------------*/
+static void
+serialRegAssign (eBBlock ** ebbs, int count)
+{
+  int i;
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* for all blocks */
+  for (i = 0; i < count; i++)
+    {
+
+      iCode *ic;
+
+      if (ebbs[i]->noPath &&
+         (ebbs[i]->entryLabel != entryLabel &&
+          ebbs[i]->entryLabel != returnLabel))
+       continue;
+
+      /* of all instructions do */
+      for (ic = ebbs[i]->sch; ic; ic = ic->next)
+       {
+
+         debugLog ("  op: %s\n", decodeOp (ic->op));
+
+         /* if this is an ipop that means some live
+            range will have to be assigned again */
+         if (ic->op == IPOP)
+           reassignLR (IC_LEFT (ic));
+
+         /* if result is present && is a true symbol */
+         if (IC_RESULT (ic) && ic->op != IFX &&
+             IS_TRUE_SYMOP (IC_RESULT (ic)))
+           OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
+
+         /* take away registers from live
+            ranges that end at this instruction */
+         deassignLRs (ic, ebbs[i]);
+
+         /* some don't need registers */
+         if (SKIP_IC2 (ic) ||
+             ic->op == JUMPTABLE ||
+             ic->op == IFX ||
+             ic->op == IPUSH ||
+             ic->op == IPOP ||
+             (IC_RESULT (ic) && POINTER_SET (ic)))
+           continue;
+
+         /* now we need to allocate registers
+            only for the result */
+         if (IC_RESULT (ic))
+           {
+             symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+             bitVect *spillable;
+             int willCS;
+             int j;
+             int ptrRegSet = 0;
+
+             /* if it does not need or is spilt 
+                or is already assigned to registers
+                or will not live beyond this instructions */
+             if (!sym->nRegs ||
+                 sym->isspilt ||
+                 bitVectBitValue (_G.regAssigned, sym->key) ||
+                 sym->liveTo <= ic->seq)
+               continue;
+
+             /* if some liverange has been spilt at the block level
+                and this one live beyond this block then spil this
+                to be safe */
+             if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
+               {
+                 spillThis (sym);
+                 continue;
+               }
+             /* if trying to allocate this will cause
+                a spill and there is nothing to spill 
+                or this one is rematerializable then
+                spill this one */
+             willCS = willCauseSpill (sym->nRegs, sym->regType);
+             spillable = computeSpillable (ic);
+             if (sym->remat ||
+                 (willCS && bitVectIsZero (spillable)))
+               {
+
+                 spillThis (sym);
+                 continue;
+
+               }
+
+             /* if it has a spillocation & is used less than
+                all other live ranges then spill this */
+               if (willCS) {
+                   if (sym->usl.spillLoc) {
+                       symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
+                                                                        allLRs, ebbs[i], ic));
+                       if (leastUsed && leastUsed->used > sym->used) {
+                           spillThis (sym);
+                           continue;
+                       }
+                   } else {
+                       /* if none of the liveRanges have a spillLocation then better
+                          to spill this one than anything else already assigned to registers */
+                       if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
+                           /* if this is local to this block then we might find a block spil */
+                           if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
+                               spillThis (sym);
+                               continue;
+                           }
+                       }
+                   }
+               }
+
+             if (ic->op == RECEIVE)
+               debugLog ("When I get clever, I'll optimize the receive logic\n");
+
+             /* if we need ptr regs for the right side
+                then mark it */
+             if (POINTER_GET (ic) && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
+                 <= (unsigned) PTRSIZE)
+               {
+                 pic16_ptrRegReq++;
+                 ptrRegSet = 1;
+               }
+             /* else we assign registers to it */
+             _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+
+             debugLog ("  %d - \n", __LINE__);
+             if(debugF) 
+               bitVectDebugOn(_G.regAssigned, debugF);
+
+             for (j = 0; j < sym->nRegs; j++)
+               {
+                 if (sym->regType == REG_PTR)
+                   sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
+                 else
+                   sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+
+                 /* if the allocation falied which means
+                    this was spilt then break */
+                 if (!sym->regs[j])
+                   break;
+               }
+             debugLog ("  %d - \n", __LINE__);
+
+             /* if it shares registers with operands make sure
+                that they are in the same position */
+             if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
+                 OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
+               positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+                             OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
+             /* do the same for the right operand */
+             if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
+                 OP_SYMBOL (IC_RIGHT (ic))->nRegs && ic->op != '=')
+               positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+                             OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
+
+             debugLog ("  %d - \n", __LINE__);
+             if (ptrRegSet)
+               {
+                 debugLog ("  %d - \n", __LINE__);
+                 pic16_ptrRegReq--;
+                 ptrRegSet = 0;
+               }
+
+           }
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* rUmaskForOp :- returns register mask for an operand             */
+/*-----------------------------------------------------------------*/
+static bitVect *
+rUmaskForOp (operand * op)
+{
+  bitVect *rumask;
+  symbol *sym;
+  int j;
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* only temporaries are assigned registers */
+  if (!IS_ITEMP (op))
+    return NULL;
+
+  sym = OP_SYMBOL (op);
+
+  /* if spilt or no registers assigned to it
+     then nothing */
+  if (sym->isspilt || !sym->nRegs)
+    return NULL;
+
+  rumask = newBitVect (pic16_nRegs);
+
+  for (j = 0; j < sym->nRegs; j++)
+    {
+      rumask = bitVectSetBit (rumask,
+                             sym->regs[j]->rIdx);
+    }
+
+  return rumask;
+}
+
+/*-----------------------------------------------------------------*/
+/* regsUsedIniCode :- returns bit vector of registers used in iCode */
+/*-----------------------------------------------------------------*/
+static bitVect *
+regsUsedIniCode (iCode * ic)
+{
+  bitVect *rmask = newBitVect (pic16_nRegs);
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* do the special cases first */
+  if (ic->op == IFX)
+    {
+      rmask = bitVectUnion (rmask,
+                           rUmaskForOp (IC_COND (ic)));
+      goto ret;
+    }
+
+  /* for the jumptable */
+  if (ic->op == JUMPTABLE)
+    {
+      rmask = bitVectUnion (rmask,
+                           rUmaskForOp (IC_JTCOND (ic)));
+
+      goto ret;
+    }
+
+  /* of all other cases */
+  if (IC_LEFT (ic))
+    rmask = bitVectUnion (rmask,
+                         rUmaskForOp (IC_LEFT (ic)));
+
+
+  if (IC_RIGHT (ic))
+    rmask = bitVectUnion (rmask,
+                         rUmaskForOp (IC_RIGHT (ic)));
+
+  if (IC_RESULT (ic))
+    rmask = bitVectUnion (rmask,
+                         rUmaskForOp (IC_RESULT (ic)));
+
+ret:
+  return rmask;
+}
+
+/*-----------------------------------------------------------------*/
+/* createRegMask - for each instruction will determine the regsUsed */
+/*-----------------------------------------------------------------*/
+static void
+createRegMask (eBBlock ** ebbs, int count)
+{
+  int i;
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* for all blocks */
+  for (i = 0; i < count; i++)
+    {
+      iCode *ic;
+
+      if (ebbs[i]->noPath &&
+         (ebbs[i]->entryLabel != entryLabel &&
+          ebbs[i]->entryLabel != returnLabel))
+       continue;
+
+      /* for all instructions */
+      for (ic = ebbs[i]->sch; ic; ic = ic->next)
+       {
+
+         int j;
+
+         if (SKIP_IC2 (ic) || !ic->rlive)
+           continue;
+
+         /* first mark the registers used in this
+            instruction */
+         ic->rUsed = regsUsedIniCode (ic);
+         _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
+
+         /* now create the register mask for those 
+            registers that are in use : this is a
+            super set of ic->rUsed */
+         ic->rMask = newBitVect (pic16_nRegs + 1);
+
+         /* for all live Ranges alive at this point */
+         for (j = 1; j < ic->rlive->size; j++)
+           {
+             symbol *sym;
+             int k;
+
+             /* if not alive then continue */
+             if (!bitVectBitValue (ic->rlive, j))
+               continue;
+
+             /* find the live range we are interested in */
+             if (!(sym = hTabItemWithKey (liveRanges, j)))
+               {
+                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                         "createRegMask cannot find live range");
+                 exit (0);
+               }
+
+             /* if no register assigned to it */
+             if (!sym->nRegs || sym->isspilt)
+               continue;
+
+             /* for all the registers allocated to it */
+             for (k = 0; k < sym->nRegs; k++)
+               if (sym->regs[k])
+                 ic->rMask =
+                   bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
+           }
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* rematStr - returns the rematerialized string for a remat var    */
+/*-----------------------------------------------------------------*/
+static symbol *
+rematStr (symbol * sym)
+{
+  char *s = buffer;
+  iCode *ic = sym->rematiCode;
+  symbol *psym = NULL;
+
+  debugLog ("%s\n", __FUNCTION__);
+
+  //printf ("%s\n", s);
+
+  /* if plus or minus print the right hand side */
+
+  if (ic->op == '+' || ic->op == '-') {
+       
+    iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+
+    sprintf (s, "(%s %c 0x%04x)",
+            OP_SYMBOL (IC_LEFT (ric))->rname,
+            ic->op,
+            (int) operandLitValue (IC_RIGHT (ic)));
+
+
+    //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
+
+    psym = newSymbol (OP_SYMBOL (IC_LEFT (ric))->rname, 1);
+    psym->offset = (int) operandLitValue (IC_RIGHT (ic));
+
+    return psym;
+  }
+
+  sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+  psym = newSymbol (OP_SYMBOL (IC_LEFT (ic))->rname, 1);
+
+  //printf ("ralloc.c:%d %s\n", __LINE__,buffer);
+  return psym;
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* rematStr - returns the rematerialized string for a remat var    */
+/*-----------------------------------------------------------------*/
+static char *
+rematStr (symbol * sym)
+{
+  char *s = buffer;
+  iCode *ic = sym->rematiCode;
+
+  debugLog ("%s\n", __FUNCTION__);
+  while (1)
+    {
+
+      printf ("%s\n", s);
+      /* if plus or minus print the right hand side */
+/*
+   if (ic->op == '+' || ic->op == '-') {
+   sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
+   ic->op );
+   s += strlen(s);
+   ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
+   continue ;
+   }
+ */
+      if (ic->op == '+' || ic->op == '-')
+       {
+         iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+         sprintf (s, "(%s %c 0x%04x)",
+                  OP_SYMBOL (IC_LEFT (ric))->rname,
+                  ic->op,
+                  (int) operandLitValue (IC_RIGHT (ic)));
+
+         //s += strlen(s);
+         //ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
+         //continue ;
+         //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
+         return buffer;
+       }
+
+      /* we reached the end */
+      sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+      break;
+    }
+
+  printf ("%s\n", buffer);
+  return buffer;
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* regTypeNum - computes the type & number of registers required   */
+/*-----------------------------------------------------------------*/
+static void
+regTypeNum ()
+{
+  symbol *sym;
+  int k;
+  iCode *ic;
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* for each live range do */
+  for (sym = hTabFirstItem (liveRanges, &k); sym;
+       sym = hTabNextItem (liveRanges, &k)) {
+
+    debugLog ("  %d - %s\n", __LINE__, sym->rname);
+
+    /* if used zero times then no registers needed */
+    if ((sym->liveTo - sym->liveFrom) == 0)
+      continue;
+
+
+    /* if the live range is a temporary */
+    if (sym->isitmp) {
+
+      debugLog ("  %d - itemp register\n", __LINE__);
+
+      /* if the type is marked as a conditional */
+      if (sym->regType == REG_CND)
+       continue;
+
+      /* if used in return only then we don't 
+        need registers */
+      if (sym->ruonly || sym->accuse) {
+       if (IS_AGGREGATE (sym->type) || sym->isptr)
+         sym->type = aggrToPtr (sym->type, FALSE);
+       debugLog ("  %d - no reg needed - used as a return\n", __LINE__);
+
+       continue;
+      }
+
+      /* if the symbol has only one definition &
+        that definition is a get_pointer and the
+        pointer we are getting is rematerializable and
+        in "data" space */
+
+      if (bitVectnBitsOn (sym->defs) == 1 &&
+         (ic = hTabItemWithKey (iCodehTab,
+                                bitVectFirstBit (sym->defs))) &&
+         POINTER_GET (ic) &&
+         !sym->noSpilLoc &&
+         !IS_BITVAR (sym->etype)) {
+       
+
+       debugLog ("  %d - \n", __LINE__);
+
+       /* if remat in data space */
+       if (OP_SYMBOL (IC_LEFT (ic))->remat &&
+           DCL_TYPE (aggrToPtr (sym->type, FALSE)) == POINTER) {
+
+         /* create a psuedo symbol & force a spil */
+         //X symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
+         symbol *psym = rematStr (OP_SYMBOL (IC_LEFT (ic)));
+         psym->type = sym->type;
+         psym->etype = sym->etype;
+         strcpy (psym->rname, psym->name);
+         sym->isspilt = 1;
+         sym->usl.spillLoc = psym;
+         continue;
+       }
+
+       /* if in data space or idata space then try to
+          allocate pointer register */
+
+      }
+
+      /* if not then we require registers */
+      sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
+                   getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
+                   getSize (sym->type));
+
+
+    if(IS_PTR_CONST (sym->type)) {
+      debugLog ("  %d const pointer type requires %d registers, changing to 2\n",__LINE__,sym->nRegs);
+      sym->nRegs = 2;
+    }
+
+      if (sym->nRegs > 4) {
+       fprintf (stderr, "allocated more than 4 or 0 registers for type ");
+       printTypeChain (sym->type, stderr);
+       fprintf (stderr, "\n");
+      }
+
+      /* determine the type of register required */
+      if (sym->nRegs == 1 &&
+         IS_PTR (sym->type) &&
+         sym->uptr)
+       sym->regType = REG_PTR;
+      else
+       sym->regType = REG_GPR;
+
+
+      debugLog ("  reg name %s,  reg type %s\n", sym->rname, debugLogRegType (sym->regType));
+
+    }
+    else
+      /* for the first run we don't provide */
+      /* registers for true symbols we will */
+      /* see how things go                  */
+      sym->nRegs = 0;
+  }
+
+}
+static DEFSETFUNC (markRegFree)
+{
+  ((regs *)item)->isFree = 1;
+
+  return 0;
+}
+
+DEFSETFUNC (pic16_deallocReg)
+{
+  fprintf(stderr,"deallocting register %s\n",((regs *)item)->name);
+  ((regs *)item)->isFree = 1;
+  ((regs *)item)->wasUsed = 0;
+
+  return 0;
+}
+/*-----------------------------------------------------------------*/
+/* freeAllRegs - mark all registers as free                        */
+/*-----------------------------------------------------------------*/
+void
+pic16_freeAllRegs ()
+{
+  //  int i;
+
+  debugLog ("%s\n", __FUNCTION__);
+
+  applyToSet(pic16_dynAllocRegs,markRegFree);
+  applyToSet(pic16_dynStackRegs,markRegFree);
+
+/*
+  for (i = 0; i < pic16_nRegs; i++)
+    regspic16[i].isFree = 1;
+*/
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void
+pic16_deallocateAllRegs ()
+{
+  //  int i;
+
+  debugLog ("%s\n", __FUNCTION__);
+
+  applyToSet(pic16_dynAllocRegs,pic16_deallocReg);
+
+/*
+  for (i = 0; i < pic16_nRegs; i++) {
+    if(regspic16[i].pc_type == PO_GPR_TEMP) {
+      regspic16[i].isFree = 1;
+      regspic16[i].wasUsed = 0;
+    }
+  }
+*/
+}
+
+
+/*-----------------------------------------------------------------*/
+/* deallocStackSpil - this will set the stack pointer back         */
+/*-----------------------------------------------------------------*/
+static
+DEFSETFUNC (deallocStackSpil)
+{
+  symbol *sym = item;
+
+  debugLog ("%s\n", __FUNCTION__);
+  deallocLocal (sym);
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* farSpacePackable - returns the packable icode for far variables */
+/*-----------------------------------------------------------------*/
+static iCode *
+farSpacePackable (iCode * ic)
+{
+  iCode *dic;
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* go thru till we find a definition for the
+     symbol on the right */
+  for (dic = ic->prev; dic; dic = dic->prev)
+    {
+
+      /* if the definition is a call then no */
+      if ((dic->op == CALL || dic->op == PCALL) &&
+         IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+       {
+         return NULL;
+       }
+
+      /* if shift by unknown amount then not */
+      if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) &&
+         IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+       return NULL;
+
+      /* if pointer get and size > 1 */
+      if (POINTER_GET (dic) &&
+         getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
+       return NULL;
+
+      if (POINTER_SET (dic) &&
+         getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
+       return NULL;
+
+      /* if any three is a true symbol in far space */
+      if (IC_RESULT (dic) &&
+         IS_TRUE_SYMOP (IC_RESULT (dic)) &&
+         isOperandInFarSpace (IC_RESULT (dic)))
+       return NULL;
+
+      if (IC_RIGHT (dic) &&
+         IS_TRUE_SYMOP (IC_RIGHT (dic)) &&
+         isOperandInFarSpace (IC_RIGHT (dic)) &&
+         !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
+       return NULL;
+
+      if (IC_LEFT (dic) &&
+         IS_TRUE_SYMOP (IC_LEFT (dic)) &&
+         isOperandInFarSpace (IC_LEFT (dic)) &&
+         !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
+       return NULL;
+
+      if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic)))
+       {
+         if ((dic->op == LEFT_OP ||
+              dic->op == RIGHT_OP ||
+              dic->op == '-') &&
+             IS_OP_LITERAL (IC_RIGHT (dic)))
+           return NULL;
+         else
+           return dic;
+       }
+    }
+
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForAssign - register reduction for assignment           */
+/*-----------------------------------------------------------------*/
+static int
+packRegsForAssign (iCode * ic, eBBlock * ebp)
+{
+
+  iCode *dic, *sic;
+
+  debugLog ("%s\n", __FUNCTION__);
+
+  debugAopGet ("  result:", IC_RESULT (ic));
+  debugAopGet ("  left:", IC_LEFT (ic));
+  debugAopGet ("  right:", IC_RIGHT (ic));
+
+  /* if this is at an absolute address, then get the address. */
+  if (SPEC_ABSA ( OP_SYM_ETYPE(IC_RESULT(ic))) ) {
+    if(IS_CONFIG_ADDRESS( SPEC_ADDR ( OP_SYM_ETYPE(IC_RESULT(ic))))) {
+      debugLog ("  %d - found config word declaration\n", __LINE__);
+      if(IS_VALOP(IC_RIGHT(ic))) {
+       debugLog ("  setting config word to %x\n", 
+                 (int) floatFromVal (IC_RIGHT(ic)->operand.valOperand));
+       pic16_assignConfigWordValue(  SPEC_ADDR ( OP_SYM_ETYPE(IC_RESULT(ic))),
+                               (int) floatFromVal (IC_RIGHT(ic)->operand.valOperand));
+      }
+
+      /* remove the assignment from the iCode chain. */
+
+      remiCodeFromeBBlock (ebp, ic);
+      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+      hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+
+      return 1;
+
+    }
+  }
+
+  if (!IS_ITEMP (IC_RESULT (ic))) {
+    pic16_allocDirReg(IC_RESULT (ic));
+    debugLog ("  %d - result is not temp\n", __LINE__);
+  }
+/*
+  if (IC_LEFT (ic) && !IS_ITEMP (IC_LEFT (ic))) {
+    debugLog ("  %d - left is not temp, allocating\n", __LINE__);
+    pic16_allocDirReg(IC_LEFT (ic));
+  }
+*/
+
+  if (!IS_ITEMP (IC_RIGHT (ic))) {
+    debugLog ("  %d - not packing - right is not temp\n", __LINE__);
+    pic16_allocDirReg(IC_RIGHT (ic));
+    return 0;
+  }
+
+  if (OP_SYMBOL (IC_RIGHT (ic))->isind ||
+      OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
+    {
+      debugLog ("  %d - not packing - right side fails \n", __LINE__);
+      return 0;
+    }
+
+  /* if the true symbol is defined in far space or on stack
+     then we should not since this will increase register pressure */
+  if (isOperandInFarSpace (IC_RESULT (ic)))
+    {
+      if ((dic = farSpacePackable (ic)))
+       goto pack;
+      else
+       return 0;
+
+    }
+  /* find the definition of iTempNN scanning backwards if we find a 
+     a use of the true symbol before we find the definition then 
+     we cannot pack */
+  for (dic = ic->prev; dic; dic = dic->prev)
+    {
+
+      /* if there is a function call and this is
+         a parameter & not my parameter then don't pack it */
+      if ((dic->op == CALL || dic->op == PCALL) &&
+         (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
+          !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
+       {
+         debugLog ("  %d - \n", __LINE__);
+         dic = NULL;
+         break;
+       }
+
+      if (SKIP_IC2 (dic))
+       continue;
+
+      if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
+         IS_OP_VOLATILE (IC_RESULT (dic)))
+       {
+         debugLog ("  %d - dic is VOLATILE \n", __LINE__);
+         dic = NULL;
+         break;
+       }
+
+      if (IS_SYMOP (IC_RESULT (dic)) &&
+         IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+       {
+         /* A previous result was assigned to the same register - we'll our definition */
+         debugLog ("  %d - dic result key == ic right key -- pointer set=%c\n",
+                   __LINE__, ((POINTER_SET (dic)) ? 'Y' : 'N'));
+         if (POINTER_SET (dic))
+           dic = NULL;
+
+         break;
+       }
+
+      if (IS_SYMOP (IC_RIGHT (dic)) &&
+         (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
+          IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
+       {
+         debugLog ("  %d - dic right key == ic rightor result key\n", __LINE__);
+         dic = NULL;
+         break;
+       }
+
+      if (IS_SYMOP (IC_LEFT (dic)) &&
+         (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
+          IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
+       {
+         debugLog ("  %d - dic left key == ic rightor result key\n", __LINE__);
+         dic = NULL;
+         break;
+       }
+
+      if (POINTER_SET (dic) &&
+         IC_RESULT (dic)->key == IC_RESULT (ic)->key)
+       {
+         debugLog ("  %d - dic result key == ic result key -- pointer set=Y\n",
+                   __LINE__);
+         dic = NULL;
+         break;
+       }
+    }
+
+  if (!dic)
+    return 0;                  /* did not find */
+
+  /* if the result is on stack or iaccess then it must be
+     the same atleast one of the operands */
+  if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
+      OP_SYMBOL (IC_RESULT (ic))->iaccess)
+    {
+
+      /* the operation has only one symbol
+         operator then we can pack */
+      if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) ||
+         (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
+       goto pack;
+
+      if (!((IC_LEFT (dic) &&
+            IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
+           (IC_RIGHT (dic) &&
+            IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
+       return 0;
+    }
+pack:
+  debugLog ("  packing. removing %s\n", OP_SYMBOL (IC_RIGHT (ic))->rname);
+  debugLog ("  replacing with %s\n", OP_SYMBOL (IC_RESULT (dic))->rname);
+  /* found the definition */
+  /* replace the result with the result of */
+  /* this assignment and remove this assignment */
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+  IC_RESULT (dic) = IC_RESULT (ic);
+
+  if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
+    {
+      OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
+    }
+  /* delete from liverange table also 
+     delete from all the points inbetween and the new
+     one */
+  for (sic = dic; sic != ic; sic = sic->next)
+    {
+      bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
+      if (IS_ITEMP (IC_RESULT (dic)))
+       bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
+    }
+
+  remiCodeFromeBBlock (ebp, ic);
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+  hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+  OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+  return 1;
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* findAssignToSym : scanning backwards looks for first assig found */
+/*-----------------------------------------------------------------*/
+static iCode *
+findAssignToSym (operand * op, iCode * ic)
+{
+  iCode *dic;
+
+  debugLog ("%s\n", __FUNCTION__);
+  for (dic = ic->prev; dic; dic = dic->prev)
+    {
+
+      /* if definition by assignment */
+      if (dic->op == '=' &&
+         !POINTER_SET (dic) &&
+         IC_RESULT (dic)->key == op->key
+/*          &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) */
+       )
+       {
+
+         /* we are interested only if defined in far space */
+         /* or in stack space in case of + & - */
+
+         /* if assigned to a non-symbol then return
+            true */
+         if (!IS_SYMOP (IC_RIGHT (dic)))
+           break;
+
+         /* if the symbol is in far space then
+            we should not */
+         if (isOperandInFarSpace (IC_RIGHT (dic)))
+           return NULL;
+
+         /* for + & - operations make sure that
+            if it is on the stack it is the same
+            as one of the three operands */
+         if ((ic->op == '+' || ic->op == '-') &&
+             OP_SYMBOL (IC_RIGHT (dic))->onStack)
+           {
+
+             if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
+                 IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
+                 IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
+               return NULL;
+           }
+
+         break;
+
+       }
+
+      /* if we find an usage then we cannot delete it */
+      if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
+       return NULL;
+
+      if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
+       return NULL;
+
+      if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
+       return NULL;
+    }
+
+  /* now make sure that the right side of dic
+     is not defined between ic & dic */
+  if (dic)
+    {
+      iCode *sic = dic->next;
+
+      for (; sic != ic; sic = sic->next)
+       if (IC_RESULT (sic) &&
+           IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
+         return NULL;
+    }
+
+  return dic;
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForSupport :- reduce some registers for support calls   */
+/*-----------------------------------------------------------------*/
+static int
+packRegsForSupport (iCode * ic, eBBlock * ebp)
+{
+  int change = 0;
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* for the left & right operand :- look to see if the
+     left was assigned a true symbol in far space in that
+     case replace them */
+  if (IS_ITEMP (IC_LEFT (ic)) &&
+      OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
+    {
+      iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
+      iCode *sic;
+
+      if (!dic)
+       goto right;
+
+      debugAopGet ("removing left:", IC_LEFT (ic));
+
+      /* found it we need to remove it from the
+         block */
+      for (sic = dic; sic != ic; sic = sic->next)
+       bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
+
+      IC_LEFT (ic)->operand.symOperand =
+       IC_RIGHT (dic)->operand.symOperand;
+      IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+      remiCodeFromeBBlock (ebp, dic);
+      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+      hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+      change++;
+    }
+
+  /* do the same for the right operand */
+right:
+  if (!change &&
+      IS_ITEMP (IC_RIGHT (ic)) &&
+      OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
+    {
+      iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
+      iCode *sic;
+
+      if (!dic)
+       return change;
+
+      /* if this is a subtraction & the result
+         is a true symbol in far space then don't pack */
+      if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
+       {
+         sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
+         if (IN_FARSPACE (SPEC_OCLS (etype)))
+           return change;
+       }
+
+      debugAopGet ("removing right:", IC_RIGHT (ic));
+
+      /* found it we need to remove it from the
+         block */
+      for (sic = dic; sic != ic; sic = sic->next)
+       bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
+
+      IC_RIGHT (ic)->operand.symOperand =
+       IC_RIGHT (dic)->operand.symOperand;
+      IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+
+      remiCodeFromeBBlock (ebp, dic);
+      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+      hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+      change++;
+    }
+
+  return change;
+}
+
+#define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
+
+
+/*-----------------------------------------------------------------*/
+/* packRegsForOneuse : - will reduce some registers for single Use */
+/*-----------------------------------------------------------------*/
+static iCode *
+packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
+{
+  bitVect *uses;
+  iCode *dic, *sic;
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* if returning a literal then do nothing */
+  if (!IS_SYMOP (op))
+    return NULL;
+
+  /* only upto 2 bytes since we cannot predict
+     the usage of b, & acc */
+  if (getSize (operandType (op)) > (pic16_fReturnSizePic - 2) &&
+      ic->op != RETURN &&
+      ic->op != SEND)
+    return NULL;
+
+  /* this routine will mark the a symbol as used in one 
+     instruction use only && if the definition is local 
+     (ie. within the basic block) && has only one definition &&
+     that definition is either a return value from a 
+     function or does not contain any variables in
+     far space */
+  uses = bitVectCopy (OP_USES (op));
+  bitVectUnSetBit (uses, ic->key);     /* take away this iCode */
+  if (!bitVectIsZero (uses))   /* has other uses */
+    return NULL;
+
+  /* if it has only one defintion */
+  if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+    return NULL;               /* has more than one definition */
+
+  /* get that definition */
+  if (!(dic =
+       hTabItemWithKey (iCodehTab,
+                        bitVectFirstBit (OP_DEFS (op)))))
+    return NULL;
+
+  /* found the definition now check if it is local */
+  if (dic->seq < ebp->fSeq ||
+      dic->seq > ebp->lSeq)
+    return NULL;               /* non-local */
+
+  /* now check if it is the return from
+     a function call */
+  if (dic->op == CALL || dic->op == PCALL)
+    {
+      if (ic->op != SEND && ic->op != RETURN &&
+         !POINTER_SET(ic) && !POINTER_GET(ic))
+       {
+         OP_SYMBOL (op)->ruonly = 1;
+         return dic;
+       }
+      dic = dic->next;
+    }
+
+
+  /* otherwise check that the definition does
+     not contain any symbols in far space */
+  if (isOperandInFarSpace (IC_LEFT (dic)) ||
+      isOperandInFarSpace (IC_RIGHT (dic)) ||
+      IS_OP_RUONLY (IC_LEFT (ic)) ||
+      IS_OP_RUONLY (IC_RIGHT (ic)))
+    {
+      return NULL;
+    }
+
+  /* if pointer set then make sure the pointer
+     is one byte */
+  if (POINTER_SET (dic) &&
+      !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
+    return NULL;
+
+  if (POINTER_GET (dic) &&
+      !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
+    return NULL;
+
+  sic = dic;
+
+  /* also make sure the intervenening instructions
+     don't have any thing in far space */
+  for (dic = dic->next; dic && dic != ic; dic = dic->next)
+    {
+
+      /* if there is an intervening function call then no */
+      if (dic->op == CALL || dic->op == PCALL)
+       return NULL;
+      /* if pointer set then make sure the pointer
+         is one byte */
+      if (POINTER_SET (dic) &&
+         !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
+       return NULL;
+
+      if (POINTER_GET (dic) &&
+         !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
+       return NULL;
+
+      /* if address of & the result is remat then okay */
+      if (dic->op == ADDRESS_OF &&
+         OP_SYMBOL (IC_RESULT (dic))->remat)
+       continue;
+
+      /* if operand has size of three or more & this
+         operation is a '*','/' or '%' then 'b' may
+         cause a problem */
+      if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
+         getSize (operandType (op)) >= 3)
+       return NULL;
+
+      /* if left or right or result is in far space */
+      if (isOperandInFarSpace (IC_LEFT (dic)) ||
+         isOperandInFarSpace (IC_RIGHT (dic)) ||
+         isOperandInFarSpace (IC_RESULT (dic)) ||
+         IS_OP_RUONLY (IC_LEFT (dic)) ||
+         IS_OP_RUONLY (IC_RIGHT (dic)) ||
+         IS_OP_RUONLY (IC_RESULT (dic)))
+       {
+         return NULL;
+       }
+    }
+
+  OP_SYMBOL (op)->ruonly = 1;
+  return sic;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* isBitwiseOptimizable - requirements of JEAN LOUIS VERN          */
+/*-----------------------------------------------------------------*/
+static bool
+isBitwiseOptimizable (iCode * ic)
+{
+  sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
+  sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
+
+  debugLog ("%s\n", __FUNCTION__);
+  /* bitwise operations are considered optimizable
+     under the following conditions (Jean-Louis VERN) 
+
+     x & lit
+     bit & bit
+     bit & x
+     bit ^ bit
+     bit ^ x
+     x   ^ lit
+     x   | lit
+     bit | bit
+     bit | x
+   */
+  if (IS_LITERAL (rtype) ||
+      (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForAccUse - pack registers for acc use                  */
+/*-----------------------------------------------------------------*/
+static void
+packRegsForAccUse (iCode * ic)
+{
+  iCode *uic;
+
+  debugLog ("%s\n", __FUNCTION__);
+
+  /* if this is an aggregate, e.g. a one byte char array */
+  if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
+    return;
+  }
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
+
+  /* if + or - then it has to be one byte result */
+  if ((ic->op == '+' || ic->op == '-')
+      && getSize (operandType (IC_RESULT (ic))) > 1)
+    return;
+
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
+  /* if shift operation make sure right side is not a literal */
+  if (ic->op == RIGHT_OP &&
+      (isOperandLiteral (IC_RIGHT (ic)) ||
+       getSize (operandType (IC_RESULT (ic))) > 1))
+    return;
+
+  if (ic->op == LEFT_OP &&
+      (isOperandLiteral (IC_RIGHT (ic)) ||
+       getSize (operandType (IC_RESULT (ic))) > 1))
+    return;
+
+  if (IS_BITWISE_OP (ic) &&
+      getSize (operandType (IC_RESULT (ic))) > 1)
+    return;
+
+
+  /* has only one definition */
+  if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
+    return;
+
+  /* has only one use */
+  if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
+    return;
+
+  /* and the usage immediately follows this iCode */
+  if (!(uic = hTabItemWithKey (iCodehTab,
+                              bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
+    return;
+
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
+  if (ic->next != uic)
+    return;
+
+  /* if it is a conditional branch then we definitely can */
+  if (uic->op == IFX)
+    goto accuse;
+
+  if (uic->op == JUMPTABLE)
+    return;
+
+  /* if the usage is not is an assignment
+     or an arithmetic / bitwise / shift operation then not */
+  if (POINTER_SET (uic) &&
+      getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
+    return;
+
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
+  if (uic->op != '=' &&
+      !IS_ARITHMETIC_OP (uic) &&
+      !IS_BITWISE_OP (uic) &&
+      uic->op != LEFT_OP &&
+      uic->op != RIGHT_OP)
+    return;
+
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
+  /* if used in ^ operation then make sure right is not a 
+     literl */
+  if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
+    return;
+
+  /* if shift operation make sure right side is not a literal */
+  if (uic->op == RIGHT_OP &&
+      (isOperandLiteral (IC_RIGHT (uic)) ||
+       getSize (operandType (IC_RESULT (uic))) > 1))
+    return;
+
+  if (uic->op == LEFT_OP &&
+      (isOperandLiteral (IC_RIGHT (uic)) ||
+       getSize (operandType (IC_RESULT (uic))) > 1))
+    return;
+
+  /* make sure that the result of this icode is not on the
+     stack, since acc is used to compute stack offset */
+  if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
+      OP_SYMBOL (IC_RESULT (uic))->onStack)
+    return;
+
+  /* if either one of them in far space then we cannot */
+  if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
+       isOperandInFarSpace (IC_LEFT (uic))) ||
+      (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
+       isOperandInFarSpace (IC_RIGHT (uic))))
+    return;
+
+  /* if the usage has only one operand then we can */
+  if (IC_LEFT (uic) == NULL ||
+      IC_RIGHT (uic) == NULL)
+    goto accuse;
+
+  /* make sure this is on the left side if not
+     a '+' since '+' is commutative */
+  if (ic->op != '+' &&
+      IC_LEFT (uic)->key != IC_RESULT (ic)->key)
+    return;
+
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
+  /* if one of them is a literal then we can */
+  if ( ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
+       (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic))))  &&
+       (getSize (operandType (IC_RESULT (uic))) <= 1))
+    {
+      OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
+      return;
+    }
+
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
+  /* if the other one is not on stack then we can */
+  if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
+      (IS_ITEMP (IC_RIGHT (uic)) ||
+       (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
+       !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
+    goto accuse;
+
+  if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
+      (IS_ITEMP (IC_LEFT (uic)) ||
+       (IS_TRUE_SYMOP (IC_LEFT (uic)) &&
+       !OP_SYMBOL (IC_LEFT (uic))->onStack)))
+    goto accuse;
+
+  return;
+
+accuse:
+  debugLog ("%s - Yes we are using the accumulator\n", __FUNCTION__);
+  OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* packForPush - hueristics to reduce iCode for pushing            */
+/*-----------------------------------------------------------------*/
+static void
+packForReceive (iCode * ic, eBBlock * ebp)
+{
+  iCode *dic;
+
+  debugLog ("%s\n", __FUNCTION__);
+  debugAopGet ("  result:", IC_RESULT (ic));
+  debugAopGet ("  left:", IC_LEFT (ic));
+  debugAopGet ("  right:", IC_RIGHT (ic));
+
+  if (!ic->next)
+    return;
+
+  for (dic = ic->next; dic; dic = dic->next)
+    {
+
+
+
+      if (IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key))
+       debugLog ("    used on left\n");
+      if (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key)
+       debugLog ("    used on right\n");
+      if (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key)
+       debugLog ("    used on result\n");
+
+      if ((IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key)) ||
+         (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key))
+       return;
+
+    }
+
+  debugLog ("  hey we can remove this unnecessary assign\n");
+}
+/*-----------------------------------------------------------------*/
+/* packForPush - hueristics to reduce iCode for pushing            */
+/*-----------------------------------------------------------------*/
+static void
+packForPush (iCode * ic, eBBlock * ebp)
+{
+  iCode *dic;
+
+  debugLog ("%s\n", __FUNCTION__);
+  if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
+    return;
+
+  /* must have only definition & one usage */
+  if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
+      bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
+    return;
+
+  /* find the definition */
+  if (!(dic = hTabItemWithKey (iCodehTab,
+                              bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
+    return;
+
+  if (dic->op != '=' || POINTER_SET (dic))
+    return;
+
+  /* we now we know that it has one & only one def & use
+     and the that the definition is an assignment */
+  IC_LEFT (ic) = IC_RIGHT (dic);
+
+  remiCodeFromeBBlock (ebp, dic);
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+  hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+}
+
+static void printSymType(char * str, sym_link *sl)
+{
+  debugLog ("    %s Symbol type: ",str);
+  printTypeChain( sl, debugF);
+  debugLog ("\n");
+
+}
+
+/*-----------------------------------------------------------------*/
+/* some debug code to print the symbol S_TYPE. Note that
+ * the function checkSClass in src/SDCCsymt.c dinks with
+ * the S_TYPE in ways the PIC port doesn't fully like...*/
+/*-----------------------------------------------------------------*/
+static void isData(sym_link *sl)
+{
+  FILE *of = stderr;
+
+  if(!sl)
+    return;
+
+  if(debugF)
+    of = debugF;
+
+  for ( ; sl; sl=sl->next) {
+    if(!IS_DECL(sl) ) {
+      switch (SPEC_SCLS(sl)) {
+       
+      case S_DATA: fprintf (of, "data "); break;
+      case S_XDATA: fprintf (of, "xdata "); break;
+      case S_SFR: fprintf (of, "sfr "); break;
+      case S_SBIT: fprintf (of, "sbit "); break;
+      case S_CODE: fprintf (of, "code "); break;
+      case S_IDATA: fprintf (of, "idata "); break;
+      case S_PDATA: fprintf (of, "pdata "); break;
+      case S_LITERAL: fprintf (of, "literal "); break;
+      case S_STACK: fprintf (of, "stack "); break;
+      case S_XSTACK: fprintf (of, "xstack "); break;
+      case S_BIT: fprintf (of, "bit "); break;
+      case S_EEPROM: fprintf (of, "eeprom "); break;
+      default: break;
+      }
+
+    }
+
+  }
+    
+}
+/*-----------------------------------------------------------------*/
+/* packRegisters - does some transformations to reduce register    */
+/*                   pressure                                      */
+/*-----------------------------------------------------------------*/
+static void
+packRegisters (eBBlock * ebp)
+{
+  iCode *ic;
+  int change = 0;
+
+  debugLog ("%s\n", __FUNCTION__);
+
+  while (1) {
+
+    change = 0;
+
+    /* look for assignments of the form */
+    /* iTempNN = TRueSym (someoperation) SomeOperand */
+    /*       ....                       */
+    /* TrueSym := iTempNN:1             */
+    for (ic = ebp->sch; ic; ic = ic->next)
+      {
+
+       /* find assignment of the form TrueSym := iTempNN:1 */
+       if (ic->op == '=' && !POINTER_SET (ic))
+         change += packRegsForAssign (ic, ebp);
+       /* debug stuff */
+       if (ic->op == '=')
+         {
+           if (POINTER_SET (ic))
+             debugLog ("pointer is set\n");
+           debugAopGet ("  result:", IC_RESULT (ic));
+           debugAopGet ("  left:", IC_LEFT (ic));
+           debugAopGet ("  right:", IC_RIGHT (ic));
+         }
+
+      }
+
+    if (!change)
+      break;
+  }
+
+  for (ic = ebp->sch; ic; ic = ic->next) {
+
+    if(IS_SYMOP ( IC_LEFT(ic))) {
+      sym_link *etype = getSpec (operandType (IC_LEFT (ic)));
+
+      debugAopGet ("  left:", IC_LEFT (ic));
+      if(IS_PTR_CONST(OP_SYMBOL(IC_LEFT(ic))->type))
+       debugLog ("    is a pointer\n");
+
+      if(IS_OP_VOLATILE(IC_LEFT(ic)))
+       debugLog ("    is volatile\n");
+
+      isData(etype);
+
+      printSymType("   ", OP_SYMBOL(IC_LEFT(ic))->type);
+    }
+
+    if(IS_SYMOP ( IC_RIGHT(ic))) {
+      debugAopGet ("  right:", IC_RIGHT (ic));
+      printSymType("    ", OP_SYMBOL(IC_RIGHT(ic))->type);
+    }
+
+    if(IS_SYMOP ( IC_RESULT(ic))) {
+      debugAopGet ("  result:", IC_RESULT (ic));
+      printSymType("     ", OP_SYMBOL(IC_RESULT(ic))->type);
+    }
+
+    if (POINTER_SET (ic))
+       debugLog ("  %d - Pointer set\n", __LINE__);
+
+
+    /* if this is an itemp & result of a address of a true sym 
+       then mark this as rematerialisable   */
+    if (ic->op == ADDRESS_OF &&
+       IS_ITEMP (IC_RESULT (ic)) &&
+       IS_TRUE_SYMOP (IC_LEFT (ic)) &&
+       bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+       !OP_SYMBOL (IC_LEFT (ic))->onStack)
+      {
+
+       debugLog ("  %d - %s. result is rematerializable\n", __LINE__,__FUNCTION__);
+
+       OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+       OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+       OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+
+      }
+
+    /* if straight assignment then carry remat flag if
+       this is the only definition */
+    if (ic->op == '=' &&
+       !POINTER_SET (ic) &&
+       IS_SYMOP (IC_RIGHT (ic)) &&
+       OP_SYMBOL (IC_RIGHT (ic))->remat &&
+       bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
+      {
+       debugLog ("  %d - %s. straight rematerializable\n", __LINE__,__FUNCTION__);
+
+       OP_SYMBOL (IC_RESULT (ic))->remat =
+         OP_SYMBOL (IC_RIGHT (ic))->remat;
+       OP_SYMBOL (IC_RESULT (ic))->rematiCode =
+         OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+      }
+
+    /* if this is a +/- operation with a rematerizable 
+       then mark this as rematerializable as well */
+    if ((ic->op == '+' || ic->op == '-') &&
+       (IS_SYMOP (IC_LEFT (ic)) &&
+        IS_ITEMP (IC_RESULT (ic)) &&
+        OP_SYMBOL (IC_LEFT (ic))->remat &&
+        bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+        IS_OP_LITERAL (IC_RIGHT (ic))))
+      {
+       debugLog ("  %d - %s. rematerializable because op is +/-\n", __LINE__,__FUNCTION__);
+       //int i = 
+       operandLitValue (IC_RIGHT (ic));
+       OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+       OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+       OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+      }
+
+    /* mark the pointer usages */
+    if (POINTER_SET (ic))
+      {
+       OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
+       debugLog ("  marking as a pointer (set) =>");
+       debugAopGet ("  result:", IC_RESULT (ic));
+      }
+    if (POINTER_GET (ic))
+      {
+       OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+       debugLog ("  marking as a pointer (get) =>");
+       debugAopGet ("  left:", IC_LEFT (ic));
+      }
+
+    if (!SKIP_IC2 (ic))
+      {
+       /* if we are using a symbol on the stack
+          then we should say pic16_ptrRegReq */
+       if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
+         pic16_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
+                              OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0);
+       else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
+         pic16_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ||
+                              OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0);
+       else
+         {
+           if (IS_SYMOP (IC_LEFT (ic)))
+             pic16_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ||
+                                  OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0);
+           if (IS_SYMOP (IC_RIGHT (ic)))
+             pic16_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ||
+                                  OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0);
+           if (IS_SYMOP (IC_RESULT (ic)))
+             pic16_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ||
+                                  OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0);
+         }
+
+       debugLog ("  %d - pointer reg req = %d\n", __LINE__,pic16_ptrRegReq);
+
+      }
+
+    /* if the condition of an if instruction
+       is defined in the previous instruction then
+       mark the itemp as a conditional */
+    if ((IS_CONDITIONAL (ic) ||
+        ((ic->op == BITWISEAND ||
+          ic->op == '|' ||
+          ic->op == '^') &&
+         isBitwiseOptimizable (ic))) &&
+       ic->next && ic->next->op == IFX &&
+       isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
+       OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
+      {
+
+       debugLog ("  %d\n", __LINE__);
+       OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
+       continue;
+      }
+
+    /* reduce for support function calls */
+    if (ic->supportRtn || ic->op == '+' || ic->op == '-')
+      packRegsForSupport (ic, ebp);
+
+    /* if a parameter is passed, it's in W, so we may not
+       need to place a copy in a register */
+    if (ic->op == RECEIVE)
+      packForReceive (ic, ebp);
+
+    /* some cases the redundant moves can
+       can be eliminated for return statements */
+    if ((ic->op == RETURN || ic->op == SEND) &&
+       !isOperandInFarSpace (IC_LEFT (ic)) &&
+       !options.model)
+      packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+
+    /* if pointer set & left has a size more than
+       one and right is not in far space */
+    if (POINTER_SET (ic) &&
+       !isOperandInFarSpace (IC_RIGHT (ic)) &&
+       !OP_SYMBOL (IC_RESULT (ic))->remat &&
+       !IS_OP_RUONLY (IC_RIGHT (ic)) &&
+       getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
+
+      packRegsForOneuse (ic, IC_RESULT (ic), ebp);
+
+    /* if pointer get */
+    if (POINTER_GET (ic) &&
+       !isOperandInFarSpace (IC_RESULT (ic)) &&
+       !OP_SYMBOL (IC_LEFT (ic))->remat &&
+       !IS_OP_RUONLY (IC_RESULT (ic)) &&
+       getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
+
+      packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+
+
+    /* if this is cast for intergral promotion then
+       check if only use of  the definition of the 
+       operand being casted/ if yes then replace
+       the result of that arithmetic operation with 
+       this result and get rid of the cast */
+    if (ic->op == CAST) {
+       
+      sym_link *fromType = operandType (IC_RIGHT (ic));
+      sym_link *toType = operandType (IC_LEFT (ic));
+
+      debugLog ("  %d - casting\n", __LINE__);
+
+      if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
+         getSize (fromType) != getSize (toType)) {
+           
+
+       iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
+       if (dic) {
+               
+         if (IS_ARITHMETIC_OP (dic)) {
+                   
+           bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+           IC_RESULT (dic) = IC_RESULT (ic);
+           remiCodeFromeBBlock (ebp, ic);
+           bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+           hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+           OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+           ic = ic->prev;
+         }  else
+               
+           OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
+       }
+      } else {
+
+       /* if the type from and type to are the same
+          then if this is the only use then packit */
+       if (compareType (operandType (IC_RIGHT (ic)),
+                        operandType (IC_LEFT (ic))) == 1) {
+               
+         iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
+         if (dic) {
+                   
+           bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+           IC_RESULT (dic) = IC_RESULT (ic);
+           bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+           remiCodeFromeBBlock (ebp, ic);
+           hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+           OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+           ic = ic->prev;
+         }
+       }
+      }
+    }
+
+    /* pack for PUSH 
+       iTempNN := (some variable in farspace) V1
+       push iTempNN ;
+       -------------
+       push V1
+    */
+    if (ic->op == IPUSH)
+      {
+       packForPush (ic, ebp);
+      }
+
+
+    /* pack registers for accumulator use, when the
+       result of an arithmetic or bit wise operation
+       has only one use, that use is immediately following
+       the defintion and the using iCode has only one
+       operand or has two operands but one is literal &
+       the result of that operation is not on stack then
+       we can leave the result of this operation in acc:b
+       combination */
+    if ((IS_ARITHMETIC_OP (ic)
+
+        || IS_BITWISE_OP (ic)
+
+        || ic->op == LEFT_OP || ic->op == RIGHT_OP
+
+        ) &&
+       IS_ITEMP (IC_RESULT (ic)) &&
+       getSize (operandType (IC_RESULT (ic))) <= 2)
+
+      packRegsForAccUse (ic);
+
+  }
+}
+
+static void
+dumpEbbsToDebug (eBBlock ** ebbs, int count)
+{
+  int i;
+
+  if (!debug || !debugF)
+    return;
+
+  for (i = 0; i < count; i++)
+    {
+      fprintf (debugF, "\n----------------------------------------------------------------\n");
+      fprintf (debugF, "Basic Block %s : loop Depth = %d noPath = %d , lastinLoop = %d\n",
+              ebbs[i]->entryLabel->name,
+              ebbs[i]->depth,
+              ebbs[i]->noPath,
+              ebbs[i]->isLastInLoop);
+      fprintf (debugF, "depth 1st num %d : bbnum = %d 1st iCode = %d , last iCode = %d\n",
+              ebbs[i]->dfnum,
+              ebbs[i]->bbnum,
+              ebbs[i]->fSeq,
+              ebbs[i]->lSeq);
+      fprintf (debugF, "visited %d : hasFcall = %d\n",
+              ebbs[i]->visited,
+              ebbs[i]->hasFcall);
+
+      fprintf (debugF, "\ndefines bitVector :");
+      bitVectDebugOn (ebbs[i]->defSet, debugF);
+      fprintf (debugF, "\nlocal defines bitVector :");
+      bitVectDebugOn (ebbs[i]->ldefs, debugF);
+      fprintf (debugF, "\npointers Set bitvector :");
+      bitVectDebugOn (ebbs[i]->ptrsSet, debugF);
+      fprintf (debugF, "\nin pointers Set bitvector :");
+      bitVectDebugOn (ebbs[i]->inPtrsSet, debugF);
+      fprintf (debugF, "\ninDefs Set bitvector :");
+      bitVectDebugOn (ebbs[i]->inDefs, debugF);
+      fprintf (debugF, "\noutDefs Set bitvector :");
+      bitVectDebugOn (ebbs[i]->outDefs, debugF);
+      fprintf (debugF, "\nusesDefs Set bitvector :");
+      bitVectDebugOn (ebbs[i]->usesDefs, debugF);
+      fprintf (debugF, "\n----------------------------------------------------------------\n");
+      printiCChain (ebbs[i]->sch, debugF);
+    }
+}
+/*-----------------------------------------------------------------*/
+/* pic16_assignRegisters - assigns registers to each live range as need  */
+/*-----------------------------------------------------------------*/
+void
+pic16_assignRegisters (eBBlock ** ebbs, int count)
+{
+  iCode *ic;
+  int i;
+
+  debugLog ("<><><><><><><><><><><><><><><><><>\nstarting\t%s:%s", __FILE__, __FUNCTION__);
+  debugLog ("\nebbs before optimizing:\n");
+  dumpEbbsToDebug (ebbs, count);
+
+  setToNull ((void *) &_G.funcrUsed);
+  pic16_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
+
+
+  /* change assignments this will remove some
+     live ranges reducing some register pressure */
+  for (i = 0; i < count; i++)
+    packRegisters (ebbs[i]);
+
+  {
+    regs *reg;
+    int hkey;
+    int i=0;
+
+    debugLog("dir registers allocated so far:\n");
+    reg = hTabFirstItem(dynDirectRegNames, &hkey);
+
+    while(reg) {
+      debugLog("  -- #%d reg = %s  key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
+      reg = hTabNextItem(dynDirectRegNames, &hkey);
+    }
+
+  }
+
+  if (options.dump_pack)
+    dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
+
+  /* first determine for each live range the number of 
+     registers & the type of registers required for each */
+  regTypeNum ();
+
+  /* and serially allocate registers */
+  serialRegAssign (ebbs, count);
+
+  /* if stack was extended then tell the user */
+  if (_G.stackExtend)
+    {
+/*      werror(W_TOOMANY_SPILS,"stack", */
+/*             _G.stackExtend,currFunc->name,""); */
+      _G.stackExtend = 0;
+    }
+
+  if (_G.dataExtend)
+    {
+/*      werror(W_TOOMANY_SPILS,"data space", */
+/*             _G.dataExtend,currFunc->name,""); */
+      _G.dataExtend = 0;
+    }
+
+  /* after that create the register mask
+     for each of the instruction */
+  createRegMask (ebbs, count);
+
+  /* redo that offsets for stacked automatic variables */
+  redoStackOffsets ();
+
+  if (options.dump_rassgn)
+    dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+
+  /* now get back the chain */
+  ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
+
+  debugLog ("ebbs after optimizing:\n");
+  dumpEbbsToDebug (ebbs, count);
+
+
+  genpic16Code (ic);
+
+  /* free up any _G.stackSpil locations allocated */
+  applyToSet (_G.stackSpil, deallocStackSpil);
+  _G.slocNum = 0;
+  setToNull ((void **) &_G.stackSpil);
+  setToNull ((void **) &_G.spiltSet);
+  /* mark all registers as free */
+  //pic16_freeAllRegs ();
+
+  debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n");
+  debugLogClose ();
+  return;
+}
diff --git a/src/pic16/ralloc.h b/src/pic16/ralloc.h
new file mode 100644 (file)
index 0000000..cf91c04
--- /dev/null
@@ -0,0 +1,127 @@
+/*-------------------------------------------------------------------------
+
+  SDCCralloc.h - header file register allocation
+
+                Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+               PIC port   - T. Scott Dattalo scott@dattalo.com (2000)
+               PIC16 port   - Martin Dubuc m.dubuc@rogers.com (2002)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+#include "SDCCicode.h"
+#include "SDCCBBlock.h"
+#ifndef SDCCRALLOC_H
+#define SDCCRALLOC_H 1
+
+#include "pcoderegs.h"
+
+
+enum
+  {
+    R2_IDX = 0, R3_IDX, R4_IDX,
+    R5_IDX, R6_IDX, R7_IDX,
+    R0_IDX, R1_IDX, X8_IDX,
+    X9_IDX, X10_IDX, X11_IDX,
+    X12_IDX, CND_IDX
+  };
+
+enum {
+ REG_PTR=1,
+ REG_GPR,
+ REG_CND,
+ REG_SFR,
+ REG_STK,
+ REG_TMP
+};
+//#define REG_PTR 0x01
+//#define REG_GPR 0x02
+//#define REG_CND 0x04
+//#define REG_SFR 0x08
+//#define REG_STK 0x10  /* Use a register as a psuedo stack */
+//#define REG_TMP 0x20  
+
+/* definition for the registers */
+typedef struct regs
+  {
+    short type;                        /* can have value 
+                                * REG_GPR, REG_PTR or REG_CND 
+                                * This like the "meta-type" */
+    short pc_type;              /* pcode type */
+    short rIdx;                        /* index into register table */
+    //    short otype;        
+    char *name;                        /* name */
+
+    unsigned isFree:1;         /* is currently unassigned  */
+    unsigned wasUsed:1;                /* becomes true if register has been used */
+    unsigned isFixed:1;         /* True if address can't change */
+    unsigned isMapped:1;        /* The Register's address has been mapped to physical RAM */
+    unsigned isBitField:1;      /* True if reg is type bit OR is holder for several bits */
+    unsigned isEmitted:1;       /* True if the reg has been written to a .asm file */
+    unsigned address;           /* reg's address if isFixed | isMapped is true */
+    unsigned size;              /* 0 for byte, 1 for int, 4 for long */
+    unsigned alias;             /* Alias mask if register appears in multiple banks */
+    struct regs *reg_alias;     /* If more than one register share the same address 
+                                * then they'll point to each other. (primarily for bits)*/
+    pCodeRegLives reglives; /* live range mapping */
+  }
+regs;
+extern regs regspic16[];
+extern int pic16_nRegs;
+extern int pic16_Gstack_base_addr;
+
+/*
+  As registers are created, they're added to a set (based on the
+  register type). Here are the sets of registers that are supported
+  in the PIC port:
+*/
+extern set *pic16_dynAllocRegs;
+extern set *pic16_dynStackRegs;
+extern set *pic16_dynProcessorRegs;
+extern set *pic16_dynDirectRegs;
+extern set *pic16_dynDirectBitRegs;
+extern set *pic16_dynInternalRegs;
+
+
+regs *pic16_regWithIdx (int);
+regs *pic16_dirregWithName (char *name );
+void  pic16_freeAllRegs ();
+void  pic16_deallocateAllRegs ();
+regs *pic16_findFreeReg(short type);
+regs *pic16_allocWithIdx (int idx);
+
+regs *pic16_allocDirReg (operand *op );
+regs *pic16_allocRegByName (char *name, int size );
+
+/* Define register address that are constant across PIC16 family */
+#define IDX_INDF0   0xfef
+#define IDX_TMR0    0xfd6
+#define IDX_PCL     0xff9
+#define IDX_STATUS  0xfd8
+#define IDX_FSR0    0xfe9
+#define IDX_PORTA   0xf80
+#define IDX_PORTB   0xf81
+#define IDX_PCLATH  0xffa
+#define IDX_INTCON  0xff2
+#define IDX_WREG    0xfe8
+
+#define IDX_KZ      0x7fff   /* Known zero - actually just a general purpose reg. */
+#define IDX_WSAVE   0x7ffe
+#define IDX_SSAVE   0x7ffd
+
+#endif