* .version: changed version to 2.5.4
authortecodev <tecodev@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 27 Oct 2005 19:32:46 +0000 (19:32 +0000)
committertecodev <tecodev@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 27 Oct 2005 19:32:46 +0000 (19:32 +0000)
* doc/sdccman.lyx: changed version to 2.5.4, added some remarks to PIC14
* device/lib/pic/libsdcc/{_mulint.c,_mullong.c}: use unsigned literals,
  (_divschar.c,divuchar.c,_mulchar.c,_modschar.c,_moduchar): NEW,
    arithmetics support routines
* device/lib/pic/Makefile.rules: have assembler sources preprocessed
* device/lib/Makefile.in: also create installdir for pic

* src/SDCCopt.c (cnvToFcall): mark support routines `extern' for
  pic14 port as well
* src/pic/device.c (dump_sfr): rewritten to delegate register
  placement to the linker (use `extern sym' rather than sym EQU addr),
  (validAddress): fixed to check last specified address
* src/pic/gen.c (aopForSym): added code to deal with array (useless?),
  (popGetLit): truncate literal value to 8 bit,
  (popGet): moved assert to more appropriate place
  (popGetExternal): create pCode operand from and mark the according
    symbol as being `extern'
  (popGetAddr): added sanity check on immediate's offset, provide
    GPOINTER tag on demand
  (aopPut): fixed for immediates,
  (mov2w_op): move operand's address or contents to WREG (depending on
    operand type), safer variant of mov2w,
  (movwf,call_libraryfunc): NEW, handy abbreviations,
  (get_argument_pcop,get_return_val_pcop,pass_argument,
  get_returnvalue): interface for accessing function parameters and
    return values,
  (assignResultValuei,genRet): use new parameter/return value interface
  (pic14_getDataSize): back to old version handling generic pointers,
  (pic14_toBoolean,genNot,genCpl,genCmpEq,genOrOp): heavily rewritten,
    provided implementation and/or fixed old one,
  (genMultOneByte,genDivOneByte,genModOneByte): implemented as library
    calls, removed legacy 8051 reference code
  (AccLsh,AccRsh): rewritten and fixed to deal with signed operands
  (loadSignToC): NEW, move the operands sign bit to CARRY,
  (genGenericShift): NEW, replaces genLeftShift, genRightShift and
    genRightShiftSigned, accepts negative shift counts,
  (setup_fsr): load FSR and adjust IRP (indirect memory access),
  (emitPtrByteGet,emitPtrByteSet): rewritten, now works with
    generic pointers, __data pointers and __code pointers,
  (genUnpackBits,genPackBits): rewritten to work with generic pointers
    and signed bitfields, limit bitfields to 8 bit,
  (genDataPointerGet): fixed number of bytes read,
  (genGenPointerGet,genConstPointerGet): fixed bitfield access,
  (genPointerGet,genPointerSet): fixed handling of __code pointers,
    pointers to constant data are no longer assumed to point to __code
    space, removed invalid pointer types,
  (bitpatternFromVal): retrieve the PICs representation of an integer
    or float literal,
  (genDataPointerSet): fixed assigning to po_immediate operands,
  (genGenPointerSet): implemented as library call,
  (genIfx): fixed incorrect condition,
  (genAddrOf): limit generic pointers' addresses to 2 bytes,
    provide GPOINTER tag according to destination's storage class,
  (genCast): added code to handle casting to generic pointers, added
    sign-/zero extension of the result
  (aop_isLitLike,op_isLitLike): fixed handling of immediates
* src/pic/gen.h: added macros to access IRP bit in STATUS register
* src/pic/genarith.c (genAddLit): use min(result's,left's) size, sign
  extend the result
* src/pic/glue.c (is_shared_address,is_shared): check whether a given
  address/register resides in the shared banks
  (emitSymbolToFile): improved to handle global and `pinned' symbols,
    put all variables into separate sections (have the linker arrange
    them)
  (picglue): put init code and interrupt handlers in separate sections
* src/pic/main.c: added port specific options table, modified to PORT
  structure to make GPOINTERs 3 byte, added pic14_options
  (_pic14_do_link): private linking routine (update paths to libraries,
    add libsdcc.lib by default)
* src/pic/main.h: declare pic14_options
* src/pic/pcode.c: fixed instructions i/o relations,
  (RegCond): reverted to correct version,
  (newpCodeOpLit): truncate literals to 8 bit,
  (genericPrint): added debug output,
  (getRegFromInstruction): fixed for various operand types, simplified
  (BuildFlow): fixed broken handling of isntructions with labels
  (LinkFlow): start at last instruction in flow (skip trailing comments),
    pass the flow on to the next instruction after CALL
  (pCodeReplace): NEW, replace a pCode and move meta data to the new one
  (insertPCodeInstruction): fixed inserting after a skip instruction,
  (DoBankSelect): fixed for labeled instructions
  (OptimizepBlock): honor --nopeep switch
  (AnalyzeFlow,ReuseReg): prevent crash on source files with no function
* src/pic/pcodepeep.c (pCodePeepMatchRule): prevent NULL pointer accesses
* src/pic/pcoderegs.c (regIsLocal): NEW, check visibility of a register
  (pCodeOptime2pCodes): allow disabling this optimization via
    --no-pcode-opt due seldomly occuring bugs, fixed some conditions
    but is still buggy), started implementation of a dataflow based
    pCode optimization (CSE + dead code elimination)
  (pCodeRegMapLiveRangesInFlow): removed bogus inCond
* src/pic/ralloc.c (initStack): renamed stack registers to STK%d, the new
  names are independant of the stack location and therefore portable across
  devices

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3914 4a8a32a2-be11-0410-ad9d-d568d2c75423

36 files changed:
.version
ChangeLog
device/lib/Makefile.in
device/lib/pic/Makefile.rules
device/lib/pic/NEWS [new file with mode: 0644]
device/lib/pic/README [new file with mode: 0644]
device/lib/pic/TEMPLATE.S [new file with mode: 0644]
device/lib/pic/libsdcc/_divschar.c [new file with mode: 0644]
device/lib/pic/libsdcc/_divuchar.c [new file with mode: 0644]
device/lib/pic/libsdcc/_gptrget1.S [new file with mode: 0644]
device/lib/pic/libsdcc/_gptrget2.S [new file with mode: 0644]
device/lib/pic/libsdcc/_gptrget3.S [new file with mode: 0644]
device/lib/pic/libsdcc/_gptrget4.S [new file with mode: 0644]
device/lib/pic/libsdcc/_gptrput1.S [new file with mode: 0644]
device/lib/pic/libsdcc/_gptrput2.S [new file with mode: 0644]
device/lib/pic/libsdcc/_gptrput3.S [new file with mode: 0644]
device/lib/pic/libsdcc/_gptrput4.S [new file with mode: 0644]
device/lib/pic/libsdcc/_modschar.c [new file with mode: 0644]
device/lib/pic/libsdcc/_moduchar.c [new file with mode: 0644]
device/lib/pic/libsdcc/_mulchar.c [new file with mode: 0644]
device/lib/pic/libsdcc/_mulint.c
device/lib/pic/libsdcc/_mullong.c
device/lib/pic/libsdcc/macros.inc [new file with mode: 0644]
doc/sdccman.lyx
src/SDCCopt.c
src/pic/device.c
src/pic/gen.c
src/pic/gen.h
src/pic/genarith.c
src/pic/glue.c
src/pic/main.c
src/pic/main.h
src/pic/pcode.c
src/pic/pcodepeep.c
src/pic/pcoderegs.c
src/pic/ralloc.c

index aedc15bb0c6e24f27eedf7684532f8039cabb92c..fe16b348d97f7a5d8d995ebbd9712fe708f7423e 100644 (file)
--- a/.version
+++ b/.version
@@ -1 +1 @@
-2.5.3
+2.5.4
index ca4c42a553f855e759762645fa29df75d864be00..c11a086f6badda559d7038ad8e0bea36a99e162e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,100 @@
+2005-10-27 Raphael Neider <rneider AT web.de>
+
+       * .version: changed version to 2.5.4
+       * doc/sdccman.lyx: changed version to 2.5.4, added some remarks to PIC14
+       * device/lib/pic/libsdcc/{_mulint.c,_mullong.c}: use unsigned literals,
+         (_divschar.c,divuchar.c,_mulchar.c,_modschar.c,_moduchar): NEW,
+           arithmetics support routines
+       * device/lib/pic/Makefile.rules: have assembler sources preprocessed
+       * device/lib/Makefile.in: also create installdir for pic
+       
+       * src/SDCCopt.c (cnvToFcall): mark support routines `extern' for
+         pic14 port as well
+       * src/pic/device.c (dump_sfr): rewritten to delegate register
+         placement to the linker (use `extern sym' rather than sym EQU addr),
+         (validAddress): fixed to check last specified address
+       * src/pic/gen.c (aopForSym): added code to deal with array (useless?),
+         (popGetLit): truncate literal value to 8 bit,
+         (popGet): moved assert to more appropriate place
+         (popGetExternal): create pCode operand from and mark the according
+           symbol as being `extern'
+         (popGetAddr): added sanity check on immediate's offset, provide
+           GPOINTER tag on demand
+         (aopPut): fixed for immediates,
+         (mov2w_op): move operand's address or contents to WREG (depending on
+           operand type), safer variant of mov2w,
+         (movwf,call_libraryfunc): NEW, handy abbreviations,
+         (get_argument_pcop,get_return_val_pcop,pass_argument,
+         get_returnvalue): interface for accessing function parameters and
+           return values,
+         (assignResultValuei,genRet): use new parameter/return value interface
+         (pic14_getDataSize): back to old version handling generic pointers,
+         (pic14_toBoolean,genNot,genCpl,genCmpEq,genOrOp): heavily rewritten,
+           provided implementation and/or fixed old one,
+         (genMultOneByte,genDivOneByte,genModOneByte): implemented as library
+           calls, removed legacy 8051 reference code
+         (AccLsh,AccRsh): rewritten and fixed to deal with signed operands
+         (loadSignToC): NEW, move the operands sign bit to CARRY,
+         (genGenericShift): NEW, replaces genLeftShift, genRightShift and
+           genRightShiftSigned, accepts negative shift counts,
+         (setup_fsr): load FSR and adjust IRP (indirect memory access),
+         (emitPtrByteGet,emitPtrByteSet): rewritten, now works with
+           generic pointers, __data pointers and __code pointers,
+         (genUnpackBits,genPackBits): rewritten to work with generic pointers
+           and signed bitfields, limit bitfields to 8 bit,
+         (genDataPointerGet): fixed number of bytes read,
+         (genGenPointerGet,genConstPointerGet): fixed bitfield access,
+         (genPointerGet,genPointerSet): fixed handling of __code pointers,
+           pointers to constant data are no longer assumed to point to __code
+           space, removed invalid pointer types,
+         (bitpatternFromVal): retrieve the PICs representation of an integer
+           or float literal,
+         (genDataPointerSet): fixed assigning to po_immediate operands,
+         (genGenPointerSet): implemented as library call,
+         (genIfx): fixed incorrect condition,
+         (genAddrOf): limit generic pointers' addresses to 2 bytes,
+           provide GPOINTER tag according to destination's storage class,
+         (genCast): added code to handle casting to generic pointers, added
+           sign-/zero extension of the result
+         (aop_isLitLike,op_isLitLike): fixed handling of immediates
+       * src/pic/gen.h: added macros to access IRP bit in STATUS register
+       * src/pic/genarith.c (genAddLit): use min(result's,left's) size, sign
+         extend the result
+       * src/pic/glue.c (is_shared_address,is_shared): check whether a given
+         address/register resides in the shared banks
+         (emitSymbolToFile): improved to handle global and `pinned' symbols,
+           put all variables into separate sections (have the linker arrange
+           them)
+         (picglue): put init code and interrupt handlers in separate sections
+       * src/pic/main.c: added port specific options table, modified to PORT
+         structure to make GPOINTERs 3 byte, added pic14_options
+         (_pic14_do_link): private linking routine (update paths to libraries,
+           add libsdcc.lib by default)
+       * src/pic/main.h: declare pic14_options
+       * src/pic/pcode.c: fixed instructions i/o relations,
+         (RegCond): reverted to correct version,
+         (newpCodeOpLit): truncate literals to 8 bit,
+         (genericPrint): added debug output,
+         (getRegFromInstruction): fixed for various operand types, simplified
+         (BuildFlow): fixed broken handling of isntructions with labels
+         (LinkFlow): start at last instruction in flow (skip trailing comments),
+           pass the flow on to the next instruction after CALL
+         (pCodeReplace): NEW, replace a pCode and move meta data to the new one
+         (insertPCodeInstruction): fixed inserting after a skip instruction,
+         (DoBankSelect): fixed for labeled instructions
+         (OptimizepBlock): honor --nopeep switch
+         (AnalyzeFlow,ReuseReg): prevent crash on source files with no function
+       * src/pic/pcodepeep.c (pCodePeepMatchRule): prevent NULL pointer accesses
+       * src/pic/pcoderegs.c (regIsLocal): NEW, check visibility of a register
+         (pCodeOptime2pCodes): allow disabling this optimization via
+           --no-pcode-opt due seldomly occuring bugs, fixed some conditions
+           but is still buggy), started implementation of a dataflow based
+           pCode optimization (CSE + dead code elimination)
+         (pCodeRegMapLiveRangesInFlow): removed bogus inCond
+       * src/pic/ralloc.c (initStack): renamed stack registers to STK%d, the new
+         names are independant of the stack location and therefore portable across
+         devices
+
 2005-10-27 Maarten Brock <sourceforge.brock AT dse.nl>
 
        * src/mcs51/ralloc.c (bitType): added to detect bit variables,
index c5f4395de5e6f19a143dc7cfb5b2e38c3a643983..2c61f94641f12c6a9066e7a5b70254580b626caf 100644 (file)
@@ -248,7 +248,7 @@ model-pic16:
 objects-pic16: build-dir port-specific-objects-pic16 clean_intermediate-pic16
        cd $(PORTDIR); ls *$(OEXT) > $(PORT).lib
 
-# yes, we do reuse the objects-pic16 for pic14
+# yes, we do reuse the *-pic16 rules for pic14
 model-pic14:
        if [ "`grep pic ../../ports.build | grep -v pic16`" = pic ]; then \
          $(MAKE) MODELFLAGS="-mpic14" PORT=pic OEXT=.lib objects-pic16; \
@@ -315,6 +315,7 @@ installdirs:
        [ -d $(sdcc_libdir)/ds400 ] || mkdir -p $(sdcc_libdir)/ds400
        [ -d $(sdcc_libdir)/hc08 ] || mkdir -p $(sdcc_libdir)/hc08
        [ -d $(sdcc_libdir)/pic16 ] || mkdir -p $(sdcc_libdir)/pic16
+       [ -d $(sdcc_libdir)/pic ] || mkdir -p $(sdcc_libdir)/pic
        mkdir -p $(sdcc_libdir)/src
 
 # Creating dependencies
index 1f2978124a924e0cbb69c34dcccfec784ea2a372..4555a7295bec8cf04507b67d089f54dc1ff0e18e 100644 (file)
@@ -20,7 +20,9 @@ $(topsrcdir)/$(builddir)/%.d : %.c
 # assemble
 $(topsrcdir)/$(builddir)/%.o : %.S
        @echo "[  AS   ] ==> $(patsubst $(topsrcdir)/%,%,$@)";
-       $(Q)$(AS) $(ASFLAGS) -o "$@" -c "$<";
+       $(Q)$(CPP) $(CPPFLAGS) -P -o "$*.Spp" "$<";
+       $(Q)$(AS) $(ASFLAGS) -o "$@" -c "$*.Spp";
+       $(Q)$(RM) "$*.Spp";
 
 # compile
 $(topsrcdir)/$(builddir)/%.o : %.c
diff --git a/device/lib/pic/NEWS b/device/lib/pic/NEWS
new file mode 100644 (file)
index 0000000..31d82b2
--- /dev/null
@@ -0,0 +1,45 @@
+--- 2005-10-27  Raphael Neider
+
+Generic pointer support routines and additional arithmetic halpers
+have been added to the library.
+
+Although the compiled library should be portable across (all?)
+pic14 devices, I recommend selecting the desired target chip
+by setting the ARCH variable to the desired target chip in
+  - Makefile.common    (AFTER having run ./configure)  OR
+  - Makefile.common.in (BEFORE running ./configure)
+in order to maximize performance (smaller devices ignore
+BANKSEL directives, i.e. updates to the IRP bit).
+
+--- 2005-09-23  Raphael Neider
+
+The pic14 library is split into several parts:
+
+* common part
+  The common part reuses the (hardware independant) sources found 
+  under device/lib/ (currently not used).
+* pic14 specific part
+  The pic14 specific library routines are found in subdirectories of
+  device/lib/pic/ and provide specialized implementations better
+  suited for the pic14 architecture and additional functions not
+  found in (or not reused from) the common sources.
+* device specific part
+  This part is planned to support specific I/O sub-devices not
+  common to all pic14 chips. This part is currently absent...
+
+The SDCC/pic14 library has been created by
+       Raphael Neider (2005), rneider@web.de
+
+It is currently maintained by
+       Raphael Neider, rneider@web.de
+
+The pic14 and the device specific parts (whose sources are found
+in device/lib/pic/) are to be licensed nuder the terms of the
+GNU Lesser General Public License (LGPL). See COPYING for details.
+The sources from the common part are licensed as indicated in each
+file.
+
+Requests for enhancements, additions or modifications should be posted
+at the SDCC user's or developer's mailing list or directly be sent to
+the current maintainer of the library as indicated above.
+
diff --git a/device/lib/pic/README b/device/lib/pic/README
new file mode 100644 (file)
index 0000000..28179c2
--- /dev/null
@@ -0,0 +1,20 @@
+README for the SDCC/pic14 library
+
+Building the library
+====================
+1. Edit ./Makefile.in and update the ARCH variable to match your
+   device. It should be safe to keep the default setting (p18f877),
+   but performance improvements might be possible in specifying the
+   actual target chip there.
+   
+2. Run './configure'
+
+3. Run 'make clean'
+
+4. Run 'make all'
+
+Prerequisites
+=============
+* a recently new GNU Make (tested with 3.80)
+* current gputils (tested with 0.13.2)
+* SDCC with enabled 14 bit PIC backend (tested with 2.5.4)
diff --git a/device/lib/pic/TEMPLATE.S b/device/lib/pic/TEMPLATE.S
new file mode 100644 (file)
index 0000000..23ab7f4
--- /dev/null
@@ -0,0 +1,27 @@
+; -------------------------------------------------------------------------
+;  TEMPLATE.S : template for creating library assembler sources
+;
+;      Written By      Raphael Neider, rneider@web.de (2005)
+;
+;  This library is free software; you can redistribute it and/or
+;  modify it under the terms of the GNU Library General Public
+;  License as published by the Free Software Foundation; either
+;  version 2 of the License, or (at your option) any later version.
+;
+;  This library 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
+;  Library General Public License for more details.
+;
+;  You should have received a copy of the GNU Library General Public
+;  License along with this library; if not, write to the 
+;  Free Software Foundation, Inc., 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!
+;
+;  $Id$
+;  ------------------------------------------------------------------------
+
diff --git a/device/lib/pic/libsdcc/_divschar.c b/device/lib/pic/libsdcc/_divschar.c
new file mode 100644 (file)
index 0000000..233b181
--- /dev/null
@@ -0,0 +1,48 @@
+/* ---------------------------------------------------------------------------
+   _divschar.c : 8 bit division routines for pic14 devices
+
+       Written By      Raphael Neider, rneider@web.de (2005)
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the 
+   Free Software Foundation, Inc., 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!
+
+   $Id$
+   ------------------------------------------------------------------------ */
+
+extern unsigned char _divuchar (unsigned char a, unsigned char b);
+
+signed char
+_divschar (signed char a, signed char b)
+{
+  if (a < 0) {
+    /* a < 0 */
+    if (b < 0)
+      return _divuchar ((unsigned int)-a, (unsigned int)-b);
+    else
+      return -_divuchar ((unsigned int)-a, (unsigned int)b);
+  } else {
+    /* a >= 0 */
+    if (b < 0)
+      return -_divuchar ((unsigned int)a, (unsigned int)-b);
+    else
+      return _divuchar ((unsigned int)a, (unsigned int)b);
+  }
+  /* we never reach here */
+}
+
diff --git a/device/lib/pic/libsdcc/_divuchar.c b/device/lib/pic/libsdcc/_divuchar.c
new file mode 100644 (file)
index 0000000..f82baea
--- /dev/null
@@ -0,0 +1,57 @@
+/* ---------------------------------------------------------------------------
+   _divuchar.c : 8 bit division routines for pic14 devices
+
+       Written By      Raphael Neider, rneider@web.de (2005)
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the 
+   Free Software Foundation, Inc., 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!
+
+   $Id$
+   ------------------------------------------------------------------------ */
+
+unsigned char
+_divuchar (unsigned char a, unsigned char b)
+{
+  unsigned char result = 0;
+  unsigned char mask = 0x01;
+
+  /* prevent endless loop (division by zero exception?!?) */
+  if (!b) return (unsigned char)-1;
+
+  /* it would suffice to make b >= a, but that test is
+   * more complex and will fail if a has its MSB set */
+  while (!(b & (1UL << (8*sizeof(unsigned char)-1)))) {
+    b <<= 1;
+    mask <<= 1;
+  } // while
+
+  /* now add up the powers of two (of b) that "fit" into a */
+  /* we might stop if (a == 0), but that's an additional test in every iteration... */
+  while (mask) {
+    if (a >= b) {
+      result += mask;
+      a -= b;
+    } // if
+    b >>= 1;
+    mask >>= 1;
+  } // while
+
+  return result;
+}
+
diff --git a/device/lib/pic/libsdcc/_gptrget1.S b/device/lib/pic/libsdcc/_gptrget1.S
new file mode 100644 (file)
index 0000000..81355d2
--- /dev/null
@@ -0,0 +1,72 @@
+; -------------------------------------------------------------------------
+;  _gptrget1.S - read one byte pointed to by a generic pointer
+;
+;      Written By      Raphael Neider, rneider@web.de (2005)
+;
+;  This library is free software; you can redistribute it and/or
+;  modify it under the terms of the GNU Library General Public
+;  License as published by the Free Software Foundation; either
+;  version 2 of the License, or (at your option) any later version.
+;
+;  This library 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
+;  Library General Public License for more details.
+;
+;  You should have received a copy of the GNU Library General Public
+;  License along with this library; if not, write to the 
+;  Free Software Foundation, Inc., 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!
+;
+;  $Id$
+;  ------------------------------------------------------------------------
+
+; calling conventions:
+;   3 byte generic pointer is passed in via (WREG STK00 STK01).
+;   The result is returned in (WREG (STK00 (STK01 (STK02)))).
+;
+;   unsigned char _gptrget  (void *gptr);
+;   unsigned char _gptrget1 (void *gptr);
+;   unsigned int  _gptrget2 (void *gptr);
+;   void *        _gptrget3 (void *gptr);
+;   unsigned long _gptrget4 (void *gptr);
+;
+;   void _gptrput  (void *ptr, unsigned char val);
+;   void _gptrput1 (void *ptr, unsigned char val);
+;   void _gptrput2 (void *ptr, unsigned int  val);
+;   void _gptrput3 (void *ptr, unsigned int  val);
+;   void _gptrput4 (void *ptr, unsigned long val);
+
+include macros.inc
+include p16f_common.inc
+
+       global  __gptrget
+       global  __gptrget1
+       global  __codeptrget1
+       
+       CODE
+
+__gptrget:
+__gptrget1:
+       select_routine __dataptrget1, __codeptrget1
+       ; invalid tag -- return 0x00
+       retlw   0x00
+
+__dataptrget1:
+       setup_fsr
+       movf    INDF, W
+       return
+
+__codeptrget1:
+       ; call the RETLW instruction at the given address
+       movf    STK00, W
+       movwf   PCLATH
+       movf    STK01, W
+       movwf   PCL
+       return  ; should never be executed...
+
+       END
diff --git a/device/lib/pic/libsdcc/_gptrget2.S b/device/lib/pic/libsdcc/_gptrget2.S
new file mode 100644 (file)
index 0000000..4829a62
--- /dev/null
@@ -0,0 +1,81 @@
+; -------------------------------------------------------------------------
+;  _gptrget2.S - read two bytes pointed to by a generic pointer
+;
+;      Written By      Raphael Neider, rneider@web.de (2005)
+;
+;  This library is free software; you can redistribute it and/or
+;  modify it under the terms of the GNU Library General Public
+;  License as published by the Free Software Foundation; either
+;  version 2 of the License, or (at your option) any later version.
+;
+;  This library 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
+;  Library General Public License for more details.
+;
+;  You should have received a copy of the GNU Library General Public
+;  License along with this library; if not, write to the 
+;  Free Software Foundation, Inc., 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!
+;
+;  $Id$
+;  ------------------------------------------------------------------------
+
+; calling conventions:
+;   3 byte generic pointer is passed in via (WREG STK00 STK01).
+;   The result is returned in (WREG (STK00 (STK01 (STK02)))).
+;
+;   unsigned char _gptrget  (void *gptr);
+;   unsigned char _gptrget1 (void *gptr);
+;   unsigned int  _gptrget2 (void *gptr);
+;   void *        _gptrget3 (void *gptr);
+;   unsigned long _gptrget4 (void *gptr);
+;
+;   void _gptrput  (void *ptr, unsigned char val);
+;   void _gptrput1 (void *ptr, unsigned char val);
+;   void _gptrput2 (void *ptr, unsigned int  val);
+;   void _gptrput3 (void *ptr, unsigned int  val);
+;   void _gptrput4 (void *ptr, unsigned long val);
+
+include macros.inc
+include p16f_common.inc
+
+       global  __gptrget2
+       extern  __codeptrget1
+       
+       CODE
+
+__gptrget2:
+       select_routine __dataptrget2, __codeptrget2
+       ; invalid tag -- return 0x0000
+       clrf    STK00
+       retlw   0x00
+
+__dataptrget2:
+       setup_fsr
+       movf    INDF, W
+       movwf   STK00           ; low byte in STK00
+       inc_fsr
+       movf    INDF, W         ; high byte in WREG
+       return
+
+__codeptrget2:
+       pagesel __codeptrget1   ; might reside in different page
+       call    __codeptrget1
+       movwf   STK02           ; temporarily store LSB
+       incfsz  STK01,F         ; increment low address byte
+       decf    STK00,F         ; undo increment of high address byte if low byte did not overflow
+       incf    STK00,F         ; increment high address byte
+       pagesel __codeptrget1   ; might reside in different page
+       call    __codeptrget1
+       movwf   STK03           ; temporarily store MSB
+       movf    STK02, W
+       movwf   STK00           ; LSB in STK00
+       movf    STK03, W        ; MSB in WREG
+       return
+       
+       END
diff --git a/device/lib/pic/libsdcc/_gptrget3.S b/device/lib/pic/libsdcc/_gptrget3.S
new file mode 100644 (file)
index 0000000..6592846
--- /dev/null
@@ -0,0 +1,93 @@
+; -------------------------------------------------------------------------
+;  _gptrget3.S - read three bytes pointed to by a generic pointer
+;
+;      Written By      Raphael Neider, rneider@web.de (2005)
+;
+;  This library is free software; you can redistribute it and/or
+;  modify it under the terms of the GNU Library General Public
+;  License as published by the Free Software Foundation; either
+;  version 2 of the License, or (at your option) any later version.
+;
+;  This library 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
+;  Library General Public License for more details.
+;
+;  You should have received a copy of the GNU Library General Public
+;  License along with this library; if not, write to the 
+;  Free Software Foundation, Inc., 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!
+;
+;  $Id$
+;  ------------------------------------------------------------------------
+
+; calling conventions:
+;   3 byte generic pointer is passed in via (WREG STK00 STK01).
+;   The result is returned in (WREG (STK00 (STK01 (STK02)))).
+; 
+;   unsigned char _gptrget  (void *gptr);
+;   unsigned char _gptrget1 (void *gptr);
+;   unsigned int  _gptrget2 (void *gptr);
+;   void *        _gptrget3 (void *gptr);
+;   unsigned long _gptrget4 (void *gptr);
+; 
+;   void _gptrput  (void *ptr, unsigned char val);
+;   void _gptrput1 (void *ptr, unsigned char val);
+;   void _gptrput2 (void *ptr, unsigned int  val);
+;   void _gptrput3 (void *ptr, unsigned int  val);
+;   void _gptrput4 (void *ptr, unsigned long val);
+
+include macros.inc
+include p16f_common.inc
+
+       global  __gptrget3
+       extern  __codeptrget1
+       
+       CODE
+
+__gptrget3:
+       select_routine __dataptrget3, __codeptrget3
+       ; invalid tag -- return 0x000000
+       clrf    STK01
+       clrf    STK00
+       retlw   0x00
+
+__dataptrget3:
+       setup_fsr
+       movf    INDF, W
+       movwf   STK01           ; LSB in STK01
+       inc_fsr
+       movf    INDF, W
+       movwf   STK00           ; 2nd byte in STK00
+       inc_fsr
+       movf    INDF, W         ; MSB in WREG
+       return
+
+__codeptrget3:
+       pagesel __codeptrget1   ; might reside in different page
+       call    __codeptrget1
+       movwf   STK02           ; temporarily store LSB
+       incfsz  STK01,F         ; increment low address byte
+       decf    STK00,F         ; undo increment of high address byte if low byte did not overflow
+       incf    STK00,F         ; increment high address byte
+       pagesel __codeptrget1   ; might reside in different page
+       call    __codeptrget1
+       movwf   STK03           ; temporarily store 2nd byte
+       incfsz  STK01,F         ; increment low address byte
+       decf    STK00,F         ; undo increment of high address byte if low byte did not overflow
+       incf    STK00,F         ; increment high address byte
+       pagesel __codeptrget1   ; might reside in different page
+       call    __codeptrget1
+       movwf   STK04           ; temporarily store MSB
+       movf    STK02, W
+       movwf   STK01           ; LSB in STK01
+       movf    STK03, W
+       movwf   STK00           ; 2nd byte in STK00
+       movf    STK04, W        ; MSB in WREG
+       return
+
+       END
diff --git a/device/lib/pic/libsdcc/_gptrget4.S b/device/lib/pic/libsdcc/_gptrget4.S
new file mode 100644 (file)
index 0000000..3648832
--- /dev/null
@@ -0,0 +1,105 @@
+; -------------------------------------------------------------------------
+;  _gptrget4.S - read four bytes pointed to by a generic pointer
+;
+;      Written By      Raphael Neider, rneider@web.de (2005)
+;
+;  This library is free software; you can redistribute it and/or
+;  modify it under the terms of the GNU Library General Public
+;  License as published by the Free Software Foundation; either
+;  version 2 of the License, or (at your option) any later version.
+;
+;  This library 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
+;  Library General Public License for more details.
+;
+;  You should have received a copy of the GNU Library General Public
+;  License along with this library; if not, write to the 
+;  Free Software Foundation, Inc., 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!
+;
+;  $Id$
+;  ------------------------------------------------------------------------
+
+; calling conventions:
+;   3 byte generic pointer is passed in via (WREG STK00 STK01).
+;   The result is returned in (WREG (STK00 (STK01 (STK02)))).
+; 
+;   unsigned char _gptrget  (void *gptr);
+;   unsigned char _gptrget1 (void *gptr);
+;   unsigned int  _gptrget2 (void *gptr);
+;   void *        _gptrget3 (void *gptr);
+;   unsigned long _gptrget4 (void *gptr);
+; 
+;   void _gptrput  (void *ptr, unsigned char val);
+;   void _gptrput1 (void *ptr, unsigned char val);
+;   void _gptrput2 (void *ptr, unsigned int  val);
+;   void _gptrput3 (void *ptr, unsigned int  val);
+;   void _gptrput4 (void *ptr, unsigned long val);
+
+include macros.inc
+include p16f_common.inc
+
+       global  __gptrget4
+       extern  __codeptrget1
+       
+       CODE
+
+__gptrget4:
+       select_routine __dataptrget4, __codeptrget4
+       ; invalid tag -- return 0x00000000
+       clrf    STK02
+       clrf    STK01
+       clrf    STK00
+       retlw   0x00
+
+__dataptrget4:
+       setup_fsr
+       movf    INDF, W
+       movwf   STK02           ; LSB in STK02
+       inc_fsr
+       movf    INDF, W
+       movwf   STK01           ; 2nd byte in STK01
+       inc_fsr
+       movf    INDF, W
+       movwf   STK00           ; 3rd byte in STK00
+       inc_fsr
+       movf    INDF, W         ; MSB in WREG
+       return
+
+__codeptrget4:
+       pagesel __codeptrget1   ; might reside in different page
+       call    __codeptrget1
+       movwf   STK02           ; temporarily store LSB
+       incfsz  STK01,F         ; increment low address byte
+       decf    STK00,F         ; undo increment of high address byte if low byte did not overflow
+       incf    STK00,F         ; increment high address byte
+       pagesel __codeptrget1   ; might reside in different page
+       call    __codeptrget1
+       movwf   STK03           ; temporarily store 2nd byte
+       incfsz  STK01,F         ; increment low address byte
+       decf    STK00,F         ; undo increment of high address byte if low byte did not overflow
+       incf    STK00,F         ; increment high address byte
+       pagesel __codeptrget1   ; might reside in different page
+       call    __codeptrget1
+       movwf   STK04           ; temporarily store 3rd byte
+       incfsz  STK01,F         ; increment low address byte
+       decf    STK00,F         ; undo increment of high address byte if low byte did not overflow
+       incf    STK00,F         ; increment high address byte
+       pagesel __codeptrget1   ; might reside in different page
+       call    __codeptrget1
+       movwf   STK05           ; temporarily store MSB
+       movf    STK02, W
+       movwf   STK02           ; LSB in STK02
+       movf    STK03, W
+       movwf   STK01           ; 2nd byte in STK01
+       movf    STK04, W
+       movwf   STK00           ; 3rd byte in STK00
+       movf    STK05, W        ; MSB in WREG
+       return
+
+       END
diff --git a/device/lib/pic/libsdcc/_gptrput1.S b/device/lib/pic/libsdcc/_gptrput1.S
new file mode 100644 (file)
index 0000000..1247be3
--- /dev/null
@@ -0,0 +1,64 @@
+; -------------------------------------------------------------------------
+;  _gptrput1.S : write one byte pointed to by a generic pointer
+;
+;      Written By      Raphael Neider, rneider@web.de (2005)
+;
+;  This library is free software; you can redistribute it and/or
+;  modify it under the terms of the GNU Library General Public
+;  License as published by the Free Software Foundation; either
+;  version 2 of the License, or (at your option) any later version.
+;
+;  This library 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
+;  Library General Public License for more details.
+;
+;  You should have received a copy of the GNU Library General Public
+;  License along with this library; if not, write to the 
+;  Free Software Foundation, Inc., 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!
+;
+;  $Id$
+;  ------------------------------------------------------------------------
+
+; calling conventions:
+;   3 byte generic pointer is passed in via (WREG STK00 STK01).
+;   The result is returned in (WREG (STK00 (STK01 (STK02)))).
+;
+;   unsigned char _gptrget  (void *gptr);
+;   unsigned char _gptrget1 (void *gptr);
+;   unsigned int  _gptrget2 (void *gptr);
+;   void *        _gptrget3 (void *gptr);
+;   unsigned long _gptrget4 (void *gptr);
+;
+;   void _gptrput  (void *ptr, unsigned char val);
+;   void _gptrput1 (void *ptr, unsigned char val);
+;   void _gptrput2 (void *ptr, unsigned int  val);
+;   void _gptrput3 (void *ptr, unsigned int  val);
+;   void _gptrput4 (void *ptr, unsigned long val);
+
+include macros.inc
+include p16f_common.inc
+
+       global  __gptrput
+       global  __gptrput1
+       
+       CODE
+
+__gptrput:
+__gptrput1:
+       check_data      __dataptrput1
+       ; cannot write to __code space
+       return
+
+__dataptrput1:
+       setup_fsr
+       movf    STK02, W        ; get LSB(val)
+       movwf   INDF            ; store LSB
+       return
+
+       END
diff --git a/device/lib/pic/libsdcc/_gptrput2.S b/device/lib/pic/libsdcc/_gptrput2.S
new file mode 100644 (file)
index 0000000..c6d5b48
--- /dev/null
@@ -0,0 +1,65 @@
+; -------------------------------------------------------------------------
+;  _gptrput2.S : write two bytes pointed to by a generic pointer
+;
+;      Written By      Raphael Neider, rneider@web.de (2005)
+;
+;  This library is free software; you can redistribute it and/or
+;  modify it under the terms of the GNU Library General Public
+;  License as published by the Free Software Foundation; either
+;  version 2 of the License, or (at your option) any later version.
+;
+;  This library 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
+;  Library General Public License for more details.
+;
+;  You should have received a copy of the GNU Library General Public
+;  License along with this library; if not, write to the 
+;  Free Software Foundation, Inc., 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!
+;
+;  $Id$
+;  ------------------------------------------------------------------------
+
+; calling conventions:
+;   3 byte generic pointer is passed in via (WREG STK00 STK01).
+;   The result is returned in (WREG (STK00 (STK01 (STK02)))).
+;
+;   unsigned char _gptrget  (void *gptr);
+;   unsigned char _gptrget1 (void *gptr);
+;   unsigned int  _gptrget2 (void *gptr);
+;   void *        _gptrget3 (void *gptr);
+;   unsigned long _gptrget4 (void *gptr);
+;
+;   void _gptrput  (void *ptr, unsigned char val);
+;   void _gptrput1 (void *ptr, unsigned char val);
+;   void _gptrput2 (void *ptr, unsigned int  val);
+;   void _gptrput3 (void *ptr, unsigned int  val);
+;   void _gptrput4 (void *ptr, unsigned long val);
+
+include macros.inc
+include p16f_common.inc
+
+       global  __gptrput2
+       
+       CODE
+
+__gptrput2:
+       check_data      __dataptrput2
+       ; cannot write to __code space
+       return
+
+__dataptrput2:
+       setup_fsr
+       movf    STK03, W        ; get LSB(val)
+       movwf   INDF
+       inc_fsr
+       movf    STK02, W        ; get MSB(val)
+       movwf   INDF
+       return
+
+       END
diff --git a/device/lib/pic/libsdcc/_gptrput3.S b/device/lib/pic/libsdcc/_gptrput3.S
new file mode 100644 (file)
index 0000000..214a93f
--- /dev/null
@@ -0,0 +1,68 @@
+; -------------------------------------------------------------------------
+;  _gptrput3.S : write three bytes pointed to by a generic pointer
+;
+;      Written By      Raphael Neider, rneider@web.de (2005)
+;
+;  This library is free software; you can redistribute it and/or
+;  modify it under the terms of the GNU Library General Public
+;  License as published by the Free Software Foundation; either
+;  version 2 of the License, or (at your option) any later version.
+;
+;  This library 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
+;  Library General Public License for more details.
+;
+;  You should have received a copy of the GNU Library General Public
+;  License along with this library; if not, write to the 
+;  Free Software Foundation, Inc., 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!
+;
+;  $Id$
+;  ------------------------------------------------------------------------
+
+; calling conventions:
+;   3 byte generic pointer is passed in via (WREG STK00 STK01).
+;   The result is returned in (WREG (STK00 (STK01 (STK02)))).
+;
+;   unsigned char _gptrget  (void *gptr);
+;   unsigned char _gptrget1 (void *gptr);
+;   unsigned int  _gptrget2 (void *gptr);
+;   void *        _gptrget3 (void *gptr);
+;   unsigned long _gptrget4 (void *gptr);
+;
+;   void _gptrput  (void *ptr, unsigned char val);
+;   void _gptrput1 (void *ptr, unsigned char val);
+;   void _gptrput2 (void *ptr, unsigned int  val);
+;   void _gptrput3 (void *ptr, unsigned int  val);
+;   void _gptrput4 (void *ptr, unsigned long val);
+
+include macros.inc
+include p16f_common.inc
+
+       global  __gptrput3
+       
+       CODE
+
+__gptrput3:
+       check_data      __dataptrput3
+       ; cannot write to __code space
+       return
+
+__dataptrput3:
+       setup_fsr
+       movf    STK04, W        ; get LSB(val)
+       movwf   INDF
+       inc_fsr
+       movf    STK03, W        ; get 2nd byte of val
+       movwf   INDF
+       inc_fsr
+       movf    STK02, W        ; get MSB(val)
+       movwf   INDF
+       return
+
+       END
diff --git a/device/lib/pic/libsdcc/_gptrput4.S b/device/lib/pic/libsdcc/_gptrput4.S
new file mode 100644 (file)
index 0000000..2e108c2
--- /dev/null
@@ -0,0 +1,71 @@
+; -------------------------------------------------------------------------
+;  _gptrput4.S : write four bytes pointed to by a generic pointer
+;
+;      Written By      Raphael Neider, rneider@web.de (2005)
+;
+;  This library is free software; you can redistribute it and/or
+;  modify it under the terms of the GNU Library General Public
+;  License as published by the Free Software Foundation; either
+;  version 2 of the License, or (at your option) any later version.
+;
+;  This library 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
+;  Library General Public License for more details.
+;
+;  You should have received a copy of the GNU Library General Public
+;  License along with this library; if not, write to the 
+;  Free Software Foundation, Inc., 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!
+;
+;  $Id$
+;  ------------------------------------------------------------------------
+
+; calling conventions:
+;   3 byte generic pointer is passed in via (WREG STK00 STK01).
+;   The result is returned in (WREG (STK00 (STK01 (STK02)))).
+;
+;   unsigned char _gptrget  (void *gptr);
+;   unsigned char _gptrget1 (void *gptr);
+;   unsigned int  _gptrget2 (void *gptr);
+;   void *        _gptrget3 (void *gptr);
+;   unsigned long _gptrget4 (void *gptr);
+;
+;   void _gptrput  (void *ptr, unsigned char val);
+;   void _gptrput1 (void *ptr, unsigned char val);
+;   void _gptrput2 (void *ptr, unsigned int  val);
+;   void _gptrput3 (void *ptr, unsigned int  val);
+;   void _gptrput4 (void *ptr, unsigned long val);
+
+include macros.inc
+include p16f_common.inc
+
+       global  __gptrput4
+       
+       CODE
+
+__gptrput4:
+       check_data      __dataptrput4
+       ; cannot write to __code space
+       return
+
+__dataptrput4:
+       setup_fsr
+       movf    STK05, W        ; get LSB(val)
+       movwf   INDF
+       inc_fsr
+       movf    STK04, W        ; get 2nd byte of val
+       movwf   INDF
+       inc_fsr
+       movf    STK03, W        ; get 3rd byte of val
+       movwf   INDF
+       inc_fsr
+       movf    STK02, W        ; get MSB(val)
+       movwf   INDF
+       return
+
+       END
diff --git a/device/lib/pic/libsdcc/_modschar.c b/device/lib/pic/libsdcc/_modschar.c
new file mode 100644 (file)
index 0000000..1f32f97
--- /dev/null
@@ -0,0 +1,48 @@
+/* ---------------------------------------------------------------------------
+   _modschar.c : 8 bit modulus routines for pic14 devices
+
+       Written By      Raphael Neider, rneider@web.de (2005)
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the 
+   Free Software Foundation, Inc., 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!
+
+   $Id$
+   ------------------------------------------------------------------------ */
+
+extern unsigned char _moduchar (unsigned char a, unsigned char b);
+
+signed char
+_modschar (signed char a, signed char b)
+{
+  if (a < 0) {
+    /* a < 0 */
+    if (b < 0)
+      return _moduchar ((unsigned int)-a, (unsigned int)-b);
+    else
+      return -_moduchar ((unsigned int)-a, (unsigned int)b);
+  } else {
+    /* a >= 0 */
+    if (b < 0)
+      return -_moduchar ((unsigned int)a, (unsigned int)-b);
+    else
+      return _moduchar ((unsigned int)a, (unsigned int)b);
+  }
+  /* we never reach here */
+}
+
diff --git a/device/lib/pic/libsdcc/_moduchar.c b/device/lib/pic/libsdcc/_moduchar.c
new file mode 100644 (file)
index 0000000..402002e
--- /dev/null
@@ -0,0 +1,54 @@
+/* ---------------------------------------------------------------------------
+   _moduchar.c : 8 bit modulus routines for pic14 devices
+
+       Written By      Raphael Neider, rneider@web.de (2005)
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the 
+   Free Software Foundation, Inc., 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!
+
+   $Id$
+   ------------------------------------------------------------------------ */
+
+unsigned char
+_moduchar (unsigned char a, unsigned char b)
+{
+  unsigned char count = 1;
+
+  /* prevent endless loop (division by zero exception?!?) */
+  if (!b) return (unsigned char)-1;
+
+  /* it would suffice to make b >= a, but that test is
+   * more complex and will fail if a has its MSB set */
+  while (!(b & (1UL << (8*sizeof(unsigned char)-1)))) {
+    b <<= 1;
+    ++count;
+  } // while
+
+  /* now subtract all the powers of two (of b) that "fit" into a */
+  while (count) {
+    if (a >= b) {
+      a -= b;
+    } // if
+    b >>= 1;
+    --count;
+  } // while
+
+  return a;
+}
+
diff --git a/device/lib/pic/libsdcc/_mulchar.c b/device/lib/pic/libsdcc/_mulchar.c
new file mode 100644 (file)
index 0000000..656786c
--- /dev/null
@@ -0,0 +1,49 @@
+/* ---------------------------------------------------------------------------
+   _mulchar.c : routine for 8 bit multiplication
+
+       Written By      Raphael Neider, rneider@web.de (2005)
+
+   This library is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This library 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library 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!
+
+   $Id$
+   ------------------------------------------------------------------------ */
+
+#pragma save
+#pragma disable_warning 126 /* unreachable code */
+#pragma disable_warning 116 /* left shifting more than size of object */
+char
+_mulchar (char a, char b)
+{
+  char result = 0;
+  unsigned char i;
+
+  /* check all bits in a byte */
+  for (i = 0; i < 8u; i++) {
+    /* check all bytes in operand (generic code, optimized by the compiler) */
+    if (a & (unsigned char)0x0001u) result += b;
+    if (sizeof (a) > 1 && (a & 0x00000100ul)) result += (b << 8u);
+    if (sizeof (a) > 2 && (a & 0x00010000ul)) result += (b << 16u);
+    if (sizeof (a) > 3 && (a & 0x01000000ul)) result += (b << 24u);
+    a = ((unsigned char)a) >> 1u;
+    b <<= 1u;
+  } // for i
+
+  return result;
+}
+#pragma restore
index c37e6da82a9855a1a8b02cc36099ba6aa18d2a8f..b7b13d6b8e8e2b67ca0d52d4fc4a17e4ea9f5700 100644 (file)
@@ -36,12 +36,12 @@ _mulint (int a, int b)
   /* check all bits in a byte */
   for (i = 0; i < 8u; i++) {
     /* check all bytes in operand (generic code, optimized by the compiler) */
-    if (a & 0x0001) result += b;
-    if (sizeof (int) > 1 && (a & 0x00000100)) result += (b << 8);
-    if (sizeof (int) > 2 && (a & 0x00010000)) result += (b << 16);
-    if (sizeof (int) > 3 && (a & 0x01000000)) result += (b << 24);
-    a = ((unsigned int)(a)) >> 1;
-    b <<= 1;
+    if (a & 0x0001u) result += b;
+    if (sizeof (a) > 1 && (a & 0x00000100ul)) result += (b << 8u);
+    if (sizeof (a) > 2 && (a & 0x00010000ul)) result += (b << 16u);
+    if (sizeof (a) > 3 && (a & 0x01000000ul)) result += (b << 24u);
+    a = ((unsigned int)a) >> 1u;
+    b <<= 1u;
   } // for i
 
   return result;
index 8675adbd6e0232dddc3b2893b68f2064284beabd..21624fed2a881f7d8751bd5544836b8422a7d320 100644 (file)
@@ -36,12 +36,12 @@ _mullong (long a, long b)
   /* check all bits in a byte */
   for (i = 0; i < 8u; i++) {
     /* check all bytes in operand (generic code, optimized by the compiler) */
-    if (a & 0x0001) result += b;
-    if (sizeof (long) > 1 && (a & 0x00000100)) result += (b << 8);
-    if (sizeof (long) > 2 && (a & 0x00010000)) result += (b << 16);
-    if (sizeof (long) > 3 && (a & 0x01000000)) result += (b << 24);
-    a = ((unsigned long)a) >> 1;
-    b <<= 1;
+    if (a & 0x0001u) result += b;
+    if (sizeof (a) > 1 && (a & 0x00000100ul)) result += (b << 8u);
+    if (sizeof (a) > 2 && (a & 0x00010000ul)) result += (b << 16u);
+    if (sizeof (a) > 3 && (a & 0x01000000ul)) result += (b << 24u);
+    a = ((unsigned long)a) >> 1u;
+    b <<= 1u;
   } // for i
 
   return result;
diff --git a/device/lib/pic/libsdcc/macros.inc b/device/lib/pic/libsdcc/macros.inc
new file mode 100644 (file)
index 0000000..5ab3874
--- /dev/null
@@ -0,0 +1,42 @@
+; -----------------------------------------------
+; --- generic pointer access helpers
+; -----------------------------------------------
+
+GPTRTAG_DATA   EQU     0x00
+GPTRTAG_CODE   EQU     0x80
+
+; setup FSR to point to (STK00:STK01)
+setup_fsr      macro
+       movf    STK01, W
+       movwf   FSR
+       ; select indirectly addressed bank
+       bcf     STATUS, IRP
+       btfsc   STK00, 0
+       bsf     STATUS, IRP
+       endm
+
+; increment FSR, update IRP on bank crossings
+; FIXME: update IRP if FSR is reset to 0...
+inc_fsr                macro
+       incf    FSR, F
+       endm
+
+; dispatch according to gptr type
+select_routine macro   dataptr, codeptr
+       ; __data pointer tag: 0x00
+       xorlw   GPTRTAG_DATA
+       btfsc   STATUS, Z
+       goto    dataptr
+       ; __code pointer tag: 0x80
+       xorlw   (GPTRTAG_DATA ^ GPTRTAG_CODE)
+       btfsc   STATUS, Z
+       goto    codeptr
+       endm
+
+check_data     macro   dataptr
+       ; __data pointer tag: 0x00
+       xorlw   GPTRTAG_DATA
+       btfsc   STATUS, Z
+       goto    dataptr
+       endm
+
index afc37d00a1df05e6dc0411e68b8c9ff982cc058a..e5ff75874e2e895d5bb4d5ddce6fcfd220725698 100644 (file)
@@ -82,7 +82,7 @@ SDCC Compiler User Guide
 
 
 \size normal 
-SDCC 2.5.3
+SDCC 2.5.5
 \size footnotesize 
 
 \newline 
@@ -16103,7 +16103,7 @@ $(PRJ).hex: $(OBJS)
 \SpecialChar ~
 \SpecialChar ~
 \SpecialChar ~
-gplink -m -s $(PRJ).lkr -o $(PRJ).hex $(OBJS)
+gplink -m -s $(PRJ).lkr -o $(PRJ).hex $(OBJS) libsdcc.lib
 \layout Standard
 
 Here is a 
@@ -16149,7 +16149,7 @@ $(PRJ).hex: $(OBJS)
 \SpecialChar ~
 \SpecialChar ~
 \SpecialChar ~
-mplink /v $(PRJ).lkr /m $(PRJ).map /o $(PRJ).hex $(OBJS)
+mplink /v $(PRJ).lkr /m $(PRJ).map /o $(PRJ).hex $(OBJS) libsdcc.lib
 \layout Standard
 
 Please note that indentations within a
@@ -16157,6 +16157,131 @@ Please note that indentations within a
  Makefile
 \family default 
  have to be done with a tabulator character.
+\layout Subsection
+
+Command-line options
+\layout Standard
+
+Besides the switches common to all SDCC backends, the PIC14 port accepts
+ the following options (for an updated list see sdcc -
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash 
+/
+\end_inset 
+
+-help):
+\layout List
+\labelwidthstring 00.00.0000
+
+-
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash 
+/
+\end_inset 
+
+-debug-extra emit debug info in assembly output
+\layout List
+\labelwidthstring 00.00.0000
+
+-
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash 
+/
+\end_inset 
+
+-no-pcode-opt disable (slightly faulty) optimization on pCode
+\layout Subsection
+
+The library
+\layout Subsubsection
+
+error: missing definition for symbol 
+\begin_inset Quotes sld
+\end_inset 
+
+__gptrget1
+\begin_inset Quotes srd
+\end_inset 
+
+
+\layout Standard
+
+The PIC14 port uses library routines to provide more complex operations
+ like multiplication, division/modulus and (generic) pointer dereferencing.
+ In order to add these routines to your project, you must link with PIC14's
+\family typewriter 
+libsdcc.lib
+\family default 
+.
+ For single source file projects this is done automatically, more complex
+ projects must add 
+\family typewriter 
+libsdcc.lib
+\family default 
+ to the linker's arguments.
+ Make sure you also add an include path for the library (using the -I switch
+ to the linker)!
+\layout Subsubsection
+
+Processor mismatch in file 
+\begin_inset Quotes sld
+\end_inset 
+
+XXX
+\begin_inset Quotes srd
+\end_inset 
+
+.
+\layout Standard
+
+This warning can usually be ignored due to the very good compatibility amongst
+ 14 bit PIC devices.
+\layout Standard
+
+You might also consider recompiling the library for your specific device
+ by changing the ARCH=p16f877 (default target) entry in 
+\family typewriter 
+device/lib/pic/Makefile.in
+\family default 
+ and 
+\family typewriter 
+device/lib/pic/Makefile
+\family default 
+ to reflect your device.
+ This might even improve performance for smaller devices as unneccesary
+ BANKSELs migth be removed.
+\layout Subsection
+
+Known bugs
+\layout Subsubsection
+
+initialized data
+\layout Standard
+
+Currently, data can only be initialized if it resides in the source file
+ together with 
+\emph on 
+main()
+\emph default 
+.
+ Data in other source files will silently 
+\series bold 
+not
+\series default 
+ be initialized.
 \layout Section
 
 The PIC16
@@ -16632,6 +16757,20 @@ status Collapsed
 /
 \end_inset 
 
+-optimize-df Analyze the dataflow of the generated code and improve it.
+\layout List
+\labelwidthstring 00.00.0000
+
+-
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash 
+/
+\end_inset 
+
 -obanksel=nn Set optimization level for inserting BANKSELs.
 \newline 
 
index a7cf5cbbbaf703fc885387d40265ba4826c7271f..6c24ba6b7a06c0e48011e085cad02452c3347986 100644 (file)
@@ -219,7 +219,7 @@ cnvToFcall (iCode * ic, eBBlock * ebp)
   if (currFunc)
     FUNC_HASFCALL (currFunc->type) = 1;
 
-  if(TARGET_IS_PIC16) {
+  if(TARGET_IS_PIC16 || TARGET_IS_PIC) {
         /* normally these functions aren't marked external, so we can use their
          * _extern field to marked as already added to symbol table */
 
@@ -316,7 +316,7 @@ found:
   if (currFunc)
     FUNC_HASFCALL (currFunc->type) = 1;
 
-  if(TARGET_IS_PIC16) {
+  if(TARGET_IS_PIC16 || TARGET_IS_PIC) {
        /* normally these functions aren't marked external, so we can use their
         * _extern field to marked as already added to symbol table */
 
@@ -408,7 +408,7 @@ found:
   if (currFunc)
     FUNC_HASFCALL (currFunc->type) = 1;
 
-  if(TARGET_IS_PIC16) {
+  if(TARGET_IS_PIC16 || TARGET_IS_PIC) {
         /* normally these functions aren't marked external, so we can use their
          * _extern field to marked as already added to symbol table */
 
@@ -501,7 +501,7 @@ found:
   if (currFunc)
     FUNC_HASFCALL (currFunc->type) = 1;
 
-  if(TARGET_IS_PIC16) {
+  if(TARGET_IS_PIC16 || TARGET_IS_PIC) {
         /* normally these functions aren't marked external, so we can use their
          * _extern field to marked as already added to symbol table */
 
@@ -601,7 +601,7 @@ found:
   if (currFunc)
     FUNC_HASFCALL (currFunc->type) = 1;
 
-  if(TARGET_IS_PIC16) {
+  if(TARGET_IS_PIC16 || TARGET_IS_PIC) {
        /* normally these functions aren't marked external, so we can use their
         * _extern field to marked as already added to symbol table */
 
index 1b9fd8e96690a98038d20fb07a3cce0cd50cb45c..62369f1d41eb3c235dbcae329defd2fe62367409 100644 (file)
@@ -24,6 +24,7 @@
 #include "newalloc.h"
 
 
+#include "main.h"
 #include "pcode.h"
 #include "ralloc.h"
 #include "device.h"
@@ -34,6 +35,9 @@
 #define STRCASECMP strcasecmp
 #endif
 
+extern int Gstack_base_addr;
+extern int Gstack_size;
+
 static PIC_device Pics[] = {
        {
                {"p16f627", "16f627", "pic16f627", "f627"}, /* processor name */
@@ -102,7 +106,8 @@ AssignedMemory *finalMapping=NULL;
 
 static unsigned int config_word = DEFAULT_CONFIG_WORD;
 
-extern void emitSymbolToFile (FILE *of, const char *name, int size);
+extern int is_shared (regs *reg);
+extern void emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize);
 
 void addMemRange(memRange *r, int type)
 {
@@ -195,6 +200,16 @@ int REGallBanks(regs *reg)
 /*-----------------------------------------------------------------*
 *-----------------------------------------------------------------*/
 
+int isSFR(int address)
+{
+       
+       if( (address > pic->maxRAMaddress) || !finalMapping[address].isSFR)
+               return 0;
+       
+       return 1;
+       
+}
+
 /*
 *  dump_map -- debug stuff
 */
@@ -220,11 +235,12 @@ void dump_map(void)
 
 void dump_sfr(FILE *of)
 {
-       
+#if 0
        int start=-1;
-       int addr=0;
        int bank_base;
        static int udata_flag=0;
+#endif
+       int addr=0;
        
        //dump_map();   /* display the register map */
        //fprintf(stdout,";dump_sfr  \n");
@@ -233,8 +249,27 @@ void dump_sfr(FILE *of)
                return;
        }
        
-       do {
+       for (addr = 0; addr <= pic->maxRAMaddress; addr++)
+       {
+               regs *reg = finalMapping[addr].reg;
                
+               if (reg && !reg->isEmitted)
+               {
+                 if (pic14_options.isLibrarySource && is_shared (reg))
+                 {
+                   /* rely on external declarations for the non-fixed stack */
+                   fprintf (of, "\textern\t%s\n", reg->name);
+                 } else {
+                   emitSymbolToFile (of, reg->name, "udata", reg->size, reg->isFixed ? reg->address : -1, 0, is_shared (reg));
+                 }
+                 
+                 reg->isEmitted = 1;
+               }
+       } // for
+
+#if 0
+       do {
+
                if(finalMapping[addr].reg && !finalMapping[addr].reg->isEmitted) {
                        
                        if(start<0)
@@ -291,8 +326,9 @@ void dump_sfr(FILE *of)
                addr++;
                
        } while(addr <= pic->maxRAMaddress);
-       
-       
+
+
+#endif
 }
 
 /*-----------------------------------------------------------------*
@@ -420,16 +456,6 @@ char *processor_base_name(void)
        return pic->name[0];
 }
 
-int isSFR(int address)
-{
-       
-       if( (address > pic->maxRAMaddress) || !finalMapping[address].isSFR)
-               return 0;
-       
-       return 1;
-       
-}
-
 /*-----------------------------------------------------------------*
 *-----------------------------------------------------------------*/
 int validAddress(int address, int reg_size)
@@ -441,7 +467,8 @@ int validAddress(int address, int reg_size)
                return 0;
        }
        //  fprintf(stderr, "validAddress: Checking 0x%04x\n",address);
-       if(address > pic->maxRAMaddress)
+       assert (reg_size > 0);
+       if(address + (reg_size - 1) > pic->maxRAMaddress)
                return 0;
        
        for (i=0; i<reg_size; i++)
@@ -518,8 +545,8 @@ int assignRegister(regs *reg, int start_address)
                        return reg->address;
                }
                
-               //fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
-               //    reg->address, reg->name);
+               fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
+                   reg->address, reg->name);
                
        } else {
                
@@ -637,7 +664,7 @@ void setDefMaxRam(void)
        unsigned i;
        setMaxRAM(pic->defMaxRAMaddrs); /* Max RAM has not been included, so use default setting */
        /* Validate full memory range for use by general purpose RAM */
-       for (i=pic->defMaxRAMaddrs; i--; ) {
+       for (i=0; i <= pic->defMaxRAMaddrs; i++) {
                finalMapping[i].bank = (i>>7);
                finalMapping[i].isValid = 1;
        }
index f8b6b9d2e965be151fe583a6a6587631fb8f6b89..9a221d2572e7dc313a9e59175548df408d33b20b 100644 (file)
@@ -5,6 +5,7 @@
          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)
+    cont'd   -  Raphael Neider rneider@web.de (2005)
   
   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
 #include "pcode.h"
 #include "gen.h"
 
+/* When changing these, you must also update the assembler template
+ * in device/lib/libsdcc/macros.inc */
+#define GPTRTAG_DATA   0x00
+#define GPTRTAG_CODE   0x80
+
 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
 void genMult8X8_8 (operand *, operand *,operand *);
@@ -49,7 +55,7 @@ extern void printpBlock(FILE *of, pBlock *pb);
 
 static int labelOffset=0;
 extern int debug_verbose;
-static int optimized_for_speed = 0;
+//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
@@ -59,6 +65,7 @@ static int max_key=0;
 static int GpsuedoStkPtr=0;
 
 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
+extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
 unsigned int pic14aopLiteral (value *val, int offset);
 const char *AopType(short type);
 
@@ -109,10 +116,12 @@ static void saverbank (int, iCode *,bool);
 static lineNode *lineHead = NULL;
 static lineNode *lineCurr = NULL;
 
+#if 0
 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};
+#endif
 
 static pBlock *pb;
 
@@ -144,15 +153,17 @@ static int my_powof2 (unsigned long num)
 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
 {
        
-       DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
+       DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
                line_no,
                ((result) ? AopType(AOP_TYPE(result)) : "-"),
                ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
+               ((result) ? AOP_SIZE(result) : 0),
                ((left)   ? AopType(AOP_TYPE(left)) : "-"),
                ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
+               ((left)   ? AOP_SIZE(left) : 0),
                ((right)  ? AopType(AOP_TYPE(right)) : "-"),
                ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
-               ((result) ? AOP_SIZE(result) : 0));
+               ((right)  ? AOP_SIZE(right) : 0));
        
 }
 
@@ -237,6 +248,11 @@ void emitpComment (const char *fmt, ...)
     Safe_vsnprintf (buffer, 4096, fmt, va);
     //fprintf (stderr, "%s\n" ,buffer);
     addpCode2pBlock (pb, newpCodeCharP (buffer));
+#if 0
+  } else {
+    Safe_vsnprintf (buffer, 4096, fmt, va);
+    fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
+#endif
   }
   va_end (va);
 }
@@ -312,7 +328,7 @@ pic14_emitDebuggerSymbol (char * debugSym)
        _G.debugLine = 0;
 }
 
-
+#if 0
 /*-----------------------------------------------------------------*/
 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
 /*-----------------------------------------------------------------*/
@@ -395,6 +411,7 @@ endOfWorld :
                "getFreePtr should never reach here");
        exit(0);
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* newAsmop - creates a new asmOp                                                                 */
@@ -463,12 +480,14 @@ static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
 /*-----------------------------------------------------------------*/
 /* pointerCode - returns the code for a pointer type                      */
 /*-----------------------------------------------------------------*/
+#if 0
 static int pointerCode (sym_link *etype)
 {
        
        return PTR_TYPE(SPEC_OCLS(etype));
        
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* aopForSym - for a true symbol                                                                  */
@@ -483,6 +502,7 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
        if (sym->aop)
                return sym->aop;
        
+#if 0
        /* 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         */    
@@ -549,7 +569,8 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
                aop->size = getSize(sym->type); 
                return aop;
        }
-       
+#endif
+
        //DEBUGpic14_emitcode(";","%d",__LINE__);
        /* if in bit space */
        if (IN_BITSPACE(space)) {
@@ -587,6 +608,17 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
                return aop;
        }
        
+       if (IS_ARRAY(sym->type)) {
+               sym->aop = aop = newAsmop(AOP_PCODE);
+               aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
+               PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
+               PCOI(aop->aopu.pcop)->_function = 0;
+               PCOI(aop->aopu.pcop)->index = 0;
+               aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
+               
+               DEBUGpic14_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 */
@@ -601,7 +633,7 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
        
        allocDirReg (IC_LEFT(ic));
        
-       aop->size = FPTRSIZE; 
+       aop->size = FPTRSIZE;
        /*
        DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
        sym->aop = aop = newAsmop(AOP_DPTR);
@@ -630,7 +662,7 @@ static asmop *aopForRemat (operand *op) // x symbol *sym)
        int offset = 0;
        
        ic = sym->rematiCode;
-       
+
        DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
        if(IS_OP_POINTER(op)) {
                DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
@@ -1264,7 +1296,7 @@ pCodeOp *popGetHighLabel(unsigned int key)
 pCodeOp *popGetLit(unsigned int lit)
 {
        
-       return newpCodeOpLit(lit);
+       return newpCodeOpLit((unsigned char)lit);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1276,6 +1308,7 @@ pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
        return newpCodeOpImmd(name, offset,index, 0, is_func);
 }
 
+extern set *externs;
 
 /*-----------------------------------------------------------------*/
 /* popGetWithString - asm operator to pcode operator conversion                           */
@@ -1292,7 +1325,31 @@ pCodeOp *popGetWithString(char *str, int isExtern)
        
        pcop = newpCodeOp(str,PO_STR);
        PCOS(pcop)->isPublic = isExtern ? 1 : 0;
+
+       return pcop;
+}
+
+pCodeOp *popGetExternal (char *str)
+{
+       pCodeOp *pcop = popGetWithString (str, 1);
        
+       if (str) {
+         symbol *sym;
+         bool found = 0;
+
+         for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
+         {
+           if (!strcmp (str, sym->rname))
+             found = 1;
+         }
+         
+         if (!found)
+         {
+           sym = newSymbol(str, 0);
+           strncpy(sym->rname, str, SDCC_NAME_MAX);
+           addSet (&externs, sym);
+         } // if
+       }
        return pcop;
 }
 
@@ -1364,12 +1421,8 @@ pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
        /* offset is greater than
        size then zero */
 
-       if (!(offset >= 0 && ((offset < aop->size) || (aop->size == 0))))
-       {
-         fprintf (stderr, "%s:%u: offset=%d, aop-type:%s, size:%d\n", __FILE__, __LINE__, offset, AopType (aop->type), aop->size);
-       }
-       assert (offset >= 0 && ((offset < aop->size) || (aop->size == 0)));
-       
+       assert (aop);
+
        /* XXX: still needed for BIT operands (AOP_CRY) */
        if (offset > (aop->size - 1) &&
                aop->type != AOP_LIT)
@@ -1413,7 +1466,9 @@ pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
                
        case AOP_REG:
                {
-                       int rIdx = aop->aopu.aop_reg[offset]->rIdx;
+                       int rIdx;
+                       assert (offset < aop->size);
+                       rIdx = aop->aopu.aop_reg[offset]->rIdx;
                        
                        pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
                        PCOR(pcop)->rIdx = rIdx;
@@ -1484,18 +1539,28 @@ pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
 
 /*-----------------------------------------------------------------*/
 /* popGetAddr - access the low/high word of a symbol (immediate)   */
-/*              (for non-PO_IMMEDIATEs this is the same as poGet)  */
+/*              (for non-PO_IMMEDIATEs this is the same as popGet) */
 /*-----------------------------------------------------------------*/
 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
 {
   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
   {
     pCodeOp *pcop = aop->aopu.pcop;
+    assert (offset <= GPTRSIZE);
+
+    /* special case: index >= 2 should return GPOINTER-style values */
+    if (offset == 2)
+    {
+      pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
+      return pcop;
+    }
+    
     pcop = pCodeOpCopy (pcop);
     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
     PCOI(pcop)->offset += offset;
     PCOI(pcop)->index += index;
+    //fprintf (stderr, "is PO_IMMEDIATE: %s+o%d+i%d (new o%d,i%d)\n", pcop->name,PCOI(pcop)->offset,PCOI(pcop)->index, offset, index);
     return pcop;
   } else {
     return popGet (aop, offset + index);
@@ -1541,13 +1606,12 @@ void aopPut (asmop *aop, char *s, int offset)
                                if(offset >= aop->size) {
                                        emitpcode(POC_CLRF,popGet(aop,offset));
                                        break;
-                               } else
-                                       emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
+                               } else {
+                                       emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
+                               }
                        }
-                       
                        emitpcode(POC_MOVWF,popGet(aop,offset));
-                       
-                       
+               
                }
                break;
                
@@ -1733,6 +1797,35 @@ void aopPut (asmop *aop, char *s, int offset)
        
 }
 
+/*-----------------------------------------------------------------*/
+/* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
+/*-----------------------------------------------------------------*/
+static void mov2w_op (operand *op, int offset)
+{
+       assert (op);
+       FENTRY;
+
+       /* for PO_IMMEDIATEs: use address or value? */
+       if (op_isLitLike (op))
+       {
+               /* access address of op */
+               if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
+               if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
+               {
+                       if (offset == GPTRSIZE-1)
+                               emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
+                       else
+                               emitpcode (POC_MOVLW, popGetLit (0));
+               }
+               else
+                       emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
+       } else {
+               /* access value stored in op */
+               mov2w (AOP(op), offset);
+       }
+}
+
+
 /*-----------------------------------------------------------------*/
 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
 /*-----------------------------------------------------------------*/
@@ -1751,6 +1844,48 @@ void mov2w (asmop *aop, int offset)
        
 }
 
+static void movwf (asmop *op, int offset)
+{
+       emitpcode (POC_MOVWF, popGet(op, offset));
+}
+
+static pCodeOp *get_argument_pcop (int idx)
+{
+       assert (idx > 0 && "the 0th (first) argument is passed via WREG");
+       return popRegFromIdx (Gstack_base_addr - (idx - 1));
+}
+
+static pCodeOp *get_return_val_pcop (int offset)
+{
+       assert (offset > 0 && "the most significant byte is returned via WREG");
+       return popRegFromIdx (Gstack_base_addr - (offset - 1));
+}
+
+static void pass_argument (operand *op, int offset, int idx)
+{
+       if (op)
+               mov2w_op (op, offset);
+       if (idx != 0)
+               emitpcode(POC_MOVWF, get_argument_pcop (idx));
+}
+
+static void get_returnvalue (operand *op, int offset, int idx)
+{
+       if (idx != 0)
+               emitpcode(POC_MOVFW, get_return_val_pcop (idx));
+       movwf(AOP(op), offset);
+}
+
+static void call_libraryfunc (char *name)
+{
+  /* library code might reside in different page... */
+  emitpcode (POC_PAGESEL, popGetWithString (name, 1));
+  /* call the library function */
+  emitpcode (POC_CALL, popGetExternal (name));
+  /* might return from different page... */
+  emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
+}
+#if 0
 /*-----------------------------------------------------------------*/
 /* reAdjustPreg - points a register back to where it should        */
 /*-----------------------------------------------------------------*/
@@ -1789,6 +1924,7 @@ static void reAdjustPreg (asmop *aop)
        }
        
 }
+#endif
 
 
 #if 0
@@ -1814,17 +1950,20 @@ static int opIsGptr(operand *op)
 /*-----------------------------------------------------------------*/
 int pic14_getDataSize(operand *op)
 {
-       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+       int size;
        
+       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        
-       return AOP_SIZE(op);
+#if 0
+       size = getSize(OP_SYM_ETYPE(op));
+       return size;
+       //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;
+#else
        size = AOP_SIZE(op);
-       if (size == GPTRSIZE)
+       if (IS_GENPTR(OP_SYM_TYPE(op)))
        {
                sym_link *type = operandType(op);
                if (IS_GENPTR(type))
@@ -1884,17 +2023,33 @@ void pic14_outBitC(operand *result)
 /*-----------------------------------------------------------------*/
 void pic14_toBoolean(operand *oper)
 {
-       int size = AOP_SIZE(oper) - 1;
-       int offset = 1;
+       int size = AOP_SIZE(oper);
+       int offset = 0;
        
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       
-       if ( AOP_TYPE(oper) != AOP_ACC) {
-               emitpcode(POC_MOVFW,popGet(AOP(oper),0));
+
+       assert (size > 0);
+
+       if (size == 1) {
+               /* MOVFW does not load the flags... */
+               if (AOP_TYPE(oper) == AOP_ACC) {
+                       emitpcode(POC_IORLW, popGetLit(0));
+                       offset = 1;
+               } else {
+                       emitpcode(POC_MOVLW, popGetLit(0));
+                       offset = 0;
+               }
+       } else {
+               if ( AOP_TYPE(oper) != AOP_ACC) {
+                       emitpcode(POC_MOVFW,popGet(AOP(oper),0));
+                       offset = 1;
+               }
        }
-       while (size--) {
+       
+       while (offset < size) {
                emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
        }
+       /* Z is set iff (oper == 0) */
 }
 
 
@@ -1927,19 +2082,24 @@ static void genNot (iCode *ic)
                goto release;
        }
        
-       assert (!pic14_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))));
        size = AOP_SIZE(IC_LEFT(ic));
-       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
        mov2w (AOP(IC_LEFT(ic)),0);
        while (--size > 0)
        {
-         if (aop_isLitLike (AOP(IC_LEFT(ic))))
+         if (op_isLitLike (IC_LEFT(ic)))
            emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
          else
            emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
        }
+       emitpcode(POC_MOVLW, popGetLit (0));
        emitSKPNZ;
-       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
+       emitpcode(POC_MOVLW, popGetLit (1));
+       movwf(AOP(IC_RESULT(ic)), 0);
+
+       for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
+       {
+         emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
+       }
        goto release;
        
 release:       
@@ -1975,6 +2135,7 @@ static void genCpl (iCode *ic)
        } 
        
        size = AOP_SIZE(result);
+       if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
        while (size--) {
                
                if(AOP_TYPE(left) == AOP_ACC) 
@@ -1985,6 +2146,7 @@ static void genCpl (iCode *ic)
                emitpcode(POC_MOVWF,popGet(AOP(result),offset));
                offset++;
        }
+       addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
        
        
 release:
@@ -2216,6 +2378,7 @@ static void pushSide(operand * oper, int size)
 static void assignResultValue(operand * oper)
 {
        int size = AOP_SIZE(oper);
+       int offset = 0;
        
        FENTRY;
 
@@ -2223,10 +2386,10 @@ static void assignResultValue(operand * oper)
        
        DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
        
+       /* assign MSB first (passed via WREG) */
        while (size--) {
-               if (GpsuedoStkPtr++)
-                       emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
-               emitpcode(POC_MOVWF, popGet(AOP(oper),size));
+               get_returnvalue (oper, size, offset + GpsuedoStkPtr);
+               GpsuedoStkPtr++;
        }
 }
 
@@ -2301,6 +2464,7 @@ static void genIpop (iCode *ic)
        FENTRY;
 
        DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
+       assert (!"genIpop -- unimplemented");
 #if 0
        int size,offset ;
        
@@ -2492,7 +2656,7 @@ static void genCall (iCode *ic)
                                }
                                firstTimeThruLoop=0;
                                
-                               mov2w (AOP(IC_LEFT(sic)),  offset);
+                               mov2w_op (IC_LEFT(sic),  offset);
                                offset++;
                        }
                        freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
@@ -2529,20 +2693,6 @@ static void genCall (iCode *ic)
                freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
        }
        
-       /* adjust the stack for parameters if 
-       required */
-       if (ic->parmBytes) {
-               int i;
-               if (ic->parmBytes > 3) {
-                       pic14_emitcode("mov","a,%s",spname);
-                       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
-                       pic14_emitcode("mov","%s,a",spname);
-               } else 
-                       for ( i = 0 ; i <  ic->parmBytes ;i++)
-                               pic14_emitcode("dec","%s",spname);
-                       
-       }
-       
        /* if register bank was saved then pop them */
        if (ic->bankSaved)
                unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
@@ -2586,6 +2736,8 @@ static void genPcall (iCode *ic)
        aopOp(left,ic,FALSE);
        DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
        
+       poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
+       
        pushSide(IC_LEFT(ic), FPTRSIZE);
        
        /* if send set is not empty, assign parameters */
@@ -2614,8 +2766,6 @@ static void genPcall (iCode *ic)
        emitpcode(POC_GOTO,pcop);
        emitpLabel(albl->key);
        
-       poc = ( aop_isLitLike (AOP(left)) ? POC_MOVLW : POC_MOVFW );
-       
        emitpcode(poc,popGetAddr(AOP(left),1,0));
        emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
        emitpcode(poc,popGetAddr(AOP(left),0,0));
@@ -2634,6 +2784,8 @@ static void genPcall (iCode *ic)
                _G.accInUse++;
                aopOp(IC_RESULT(ic),ic,FALSE);
                _G.accInUse--;
+
+               GpsuedoStkPtr = 0;
                
                assignResultValue(IC_RESULT(ic));
                
@@ -3045,7 +3197,7 @@ registers :-) */
 /*-----------------------------------------------------------------*/
 static void genRet (iCode *ic)
 {
-       int size,offset = 0 , pushed = 0;
+       int size,offset = 0;
        
        FENTRY;
 
@@ -3059,44 +3211,12 @@ static void genRet (iCode *ic)
        move the return value into place */
        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 = aopGet(AOP(IC_LEFT(ic)),offset++,
-                               FALSE,TRUE);
-                       pic14_emitcode("push","%s",l);
-                       pushed++;
-               } else {
-                       l = aopGet(AOP(IC_LEFT(ic)),offset,
-                               FALSE,FALSE);
-                       if (strcmp(fReturn[offset],l)) {
-                               if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
-                                       AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
-                                       ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
-                                       ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
-                                       emitpcode(POC_MOVLW, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
-                               }else {
-                                       emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
-                               }
-                               if(size) {
-                                       emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
-                               }
-                               offset++;
-                       }
-               }
+
+       for (offset = 0; offset < size; offset++)
+       {
+               pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
        }
        
-       if (pushed) {
-               while(pushed) {
-                       pushed--;
-                       if (strcmp(fReturn[pushed],"a"))
-                               pic14_emitcode("pop",fReturn[pushed]);
-                       else
-                               pic14_emitcode("pop","acc");
-               }
-       }
        freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
        
 jumpret:
@@ -3106,7 +3226,6 @@ jumpret:
                IC_LABEL(ic->next) == returnLabel)) {
                
                emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
-               pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
        }
        
 }
@@ -3167,10 +3286,11 @@ static void genMultOneByte (operand *left,
                                                        operand *right,
                                                        operand *result)
 {
-       sym_link *opetype = operandType(result);
+       char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
        
        // symbol *lbl ;
-       int size,offset;
+       int size,offset,i;
+       
        
        FENTRY;
        
@@ -3185,87 +3305,41 @@ static void genMultOneByte (operand *left,
                right = left;
                left = t;
        }
+
+       assert (AOP_SIZE(left) == AOP_SIZE(right));
        
-       size = AOP_SIZE(result);
-       if(size == 1) {
-               
-               if (AOP_TYPE(right) == AOP_LIT){
-                       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
-                               aopGet(AOP(right),0,FALSE,FALSE), 
-                               aopGet(AOP(left),0,FALSE,FALSE), 
-                               aopGet(AOP(result),0,FALSE,FALSE));
-                       pic14_emitcode("call","genMultLit");
-               } else {
-                       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
-                               aopGet(AOP(right),0,FALSE,FALSE), 
-                               aopGet(AOP(left),0,FALSE,FALSE), 
-                               aopGet(AOP(result),0,FALSE,FALSE));
-                       pic14_emitcode("call","genMult8X8_8");
-                       
-               }
-               genMult8X8_8 (left, right,result);
-               
-               
-               /* signed or unsigned */
-               //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
-               //l = aopGet(AOP(left),0,FALSE,FALSE);
-               //MOVA(l);               
-               //pic14_emitcode("mul","ab");
-               /* if result size = 1, mul signed = mul unsigned */
-               //aopPut(AOP(result),"a",0);
-               
-       } else {        // (size > 1)
-               
-               pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
-                       aopGet(AOP(right),0,FALSE,FALSE), 
-                       aopGet(AOP(left),0,FALSE,FALSE), 
-                       aopGet(AOP(result),0,FALSE,FALSE));
-               
-               if (SPEC_USIGN(opetype)){
-                       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
-                       genUMult8X8_16 (left, right, result, NULL);
-                       
-                       if (size > 2) {
-                               /* for filling the MSBs */
-                               emitpcode(POC_CLRF,  popGet(AOP(result),2));
-                               emitpcode(POC_CLRF,  popGet(AOP(result),3));
-                       }
-               }
-               else{
-                       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
-                       
-                       pic14_emitcode("mov","a,b");
-                       
-                       /* adjust the MSB if left or right neg */
-                       
-                       /* if one literal */
-                       if (AOP_TYPE(right) == AOP_LIT){
-                               pic14_emitcode("multiply ","right is a lit");
-                               /* AND literal negative */
-                               if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
-                                       /* adjust MSB (c==0 after mul) */
-                                       pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
-                               }
-                       }
-                       else{
-                               genSMult8X8_16 (left, right, result, NULL);
-                       }
-                       
-                       if(size > 2){
-                               pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
-                               /* get the sign */
-                               pic14_emitcode("rlc","a");
-                               pic14_emitcode("subb","a,acc");
-                       }
-               }
-               
-               size -= 2;
-               offset = 2;
-               if (size > 0)
-                       while (size--)
-                               pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
-                       //aopPut(AOP(result),"a",offset++);
-       }
+       size = min(AOP_SIZE(result),AOP_SIZE(left));
+       offset = Gstack_base_addr - (2*size - 1);
+
+       /* pass right operand as argument */
+       for (i=0; i < size; i++)
+       {
+               mov2w (AOP(right), i);
+               emitpcode(POC_MOVWF, popRegFromIdx (++offset));
+       } // for
+       
+       /* pass left operand as argument */
+       for (i=0; i < size; i++)
+       {
+               mov2w (AOP(left), i);
+               if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
+       } // for
+       assert (offset == Gstack_base_addr);
+       
+       /* call library routine */
+       assert (size > 0 && size <= 4);
+       call_libraryfunc (func[size]);
+       
+       /* assign result */
+       movwf (AOP(result), size-1);
+       for (i=0; i < size - 1; i++)
+       {
+               emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
+               movwf (AOP(result), size - 2 - i);
+       } // for
+
+       /* now (zero-/sign) extend the result to its size */
+       addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
 }
 
 /*-----------------------------------------------------------------*/
@@ -3302,11 +3376,6 @@ static void genMult (iCode *ic)
                goto release ;
        }
        
-       pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
-
-       assert( AOP_SIZE(left) == AOP_SIZE(right) );
-       assert( AOP_SIZE(result) >= AOP_SIZE(left) );
-
        /* should have been converted to function call */
        assert(0) ;
        
@@ -3347,86 +3416,87 @@ static void genDivOneByte (operand *left,
                                                   operand *right,
                                                   operand *result)
 {
-       sym_link *opetype = operandType(result);
-       char *l ;
-       symbol *lbl ;
-       int size,offset;
+       int size;
        
        FENTRY;
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       size = AOP_SIZE(result) - 1;
-       offset = 1;
-       /* signed or unsigned */
-       if (SPEC_USIGN(opetype)) {
-               /* unsigned is easy */
-               pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
-               l = aopGet(AOP(left),0,FALSE,FALSE);
-               MOVA(l);                
-               pic14_emitcode("div","ab");
-               aopPut(AOP(result),"a",0);
-               while (size--)
-                       aopPut(AOP(result),zero,offset++);
-               return ;
-       }
-       
-       /* signed is a little bit more difficult */
-       
-       /* save the signs of the operands */
-       l = aopGet(AOP(left),0,FALSE,FALSE);      
-       MOVA(l);          
-       pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
-       pic14_emitcode("push","acc"); /* save it on the stack */
-       
-       /* now sign adjust for both left & right */
-       l =  aopGet(AOP(right),0,FALSE,FALSE);  
-       MOVA(l);                 
-       lbl = newiTempLabel(NULL);
-       pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
-       pic14_emitcode("cpl","a");   
-       pic14_emitcode("inc","a");
-       pic14_emitcode("","%05d_DS_:",(lbl->key+100));
-       pic14_emitcode("mov","b,a");
-       
-       /* sign adjust left side */
-       l =  aopGet(AOP(left),0,FALSE,FALSE);    
-       MOVA(l);
-       
-       lbl = newiTempLabel(NULL);
-       pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
-       pic14_emitcode("cpl","a");
-       pic14_emitcode("inc","a");
-       pic14_emitcode("","%05d_DS_:",(lbl->key+100));
-       
-       /* now the division */
-       pic14_emitcode("div","ab");
-       /* we are interested in the lower order
-       only */
-       pic14_emitcode("mov","b,a");
-       lbl = newiTempLabel(NULL);
-       pic14_emitcode("pop","acc");     
-       /* if there was an over flow we don't 
-       adjust the sign of the result */
-       pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
-       pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
-       CLRC;
-       pic14_emitcode("clr","a");
-       pic14_emitcode("subb","a,b");
-       pic14_emitcode("mov","b,a");
-       pic14_emitcode("","%05d_DS_:",(lbl->key+100));
        
-       /* now we are done */
-       aopPut(AOP(result),"b",0);
-       if(size > 0){
-               pic14_emitcode("mov","c,b.7");
-               pic14_emitcode("subb","a,acc");   
+       assert (AOP_SIZE(result) == 1);
+       assert (AOP_SIZE(right) == 1);
+       assert (AOP_SIZE(left) == 1);
+
+       size = min(AOP_SIZE(result),AOP_SIZE(left));
+
+       if (AOP_TYPE(right) == AOP_LIT)
+       {
+               /* XXX: might add specialized code */
        }
-       while (size--)
-               aopPut(AOP(result),"a",offset++);
-       
+
+       if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
+       {
+               /* unsigned division */
+       #if 1
+               mov2w(AOP(right),0);
+               emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
+               mov2w(AOP(left),0);
+               call_libraryfunc("__divuchar");
+               movwf(AOP(result),0);
+       #else
+               pCodeOp *temp;
+               symbol *lbl;
+
+               temp = popGetTempReg();
+               lbl = newiTempLabel(NULL);
+               
+               /* XXX: improve this naive approach:
+                  [result] = [a] / [b]
+                       ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
+
+                  In PIC assembler:
+                  movf  left,W
+                  movwf temp           // temp <-- left
+                  movf  right,W        // W <-- right
+                  clrf  result
+                  label1:
+                  incf  result
+                  subwf temp,F         // temp <-- temp - W
+                  skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
+                  goto  label1
+                  decf result          // we just subtract once too often
+                */
+
+               /* XXX: This loops endlessly on DIVIDE BY ZERO */
+               /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
+               
+               mov2w(AOP(left),0);
+               emitpcode(POC_MOVWF, temp);
+               mov2w(AOP(right),0);
+               emitpcode(POC_CLRF, popGet(AOP(result),0));
+
+               emitpLabel(lbl->key);
+               emitpcode(POC_INCF, popGet(AOP(result),0));
+               emitpcode(POC_SUBWF, temp);
+               emitSKPNC;
+               emitpcode(POC_GOTO, popGetLabel(lbl->key));
+               emitpcode(POC_DECF, popGet(AOP(result),0));
+       #endif
+       }
+       else
+       {
+               /* signed division */
+               mov2w(AOP(right),0);
+               emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
+               mov2w(AOP(left),0);
+               call_libraryfunc("__divschar");
+               movwf(AOP(result),0);
+       }
+
+       /* now performed the signed/unsigned division -- extend result */
+       addSign(result, 1, !SPEC_USIGN(operandType(result)));
 }
 
 /*-----------------------------------------------------------------*/
-/* genDiv - generates code for division                                                   */
+/* genDiv - generates code for division                           */
 /*-----------------------------------------------------------------*/
 static void genDiv (iCode *ic)
 {
@@ -3494,72 +3564,83 @@ static void genModOneByte (operand *left,
                                                   operand *right,
                                                   operand *result)
 {
-       sym_link *opetype = operandType(result);
-       char *l ;
-       symbol *lbl ;
+       int size;
        
        FENTRY;
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       /* signed or unsigned */
-       if (SPEC_USIGN(opetype)) {
-               /* unsigned is easy */
-               pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
-               l = aopGet(AOP(left),0,FALSE,FALSE);
-               MOVA(l);        
-               pic14_emitcode("div","ab");
-               aopPut(AOP(result),"b",0);
-               return ;
-       }
-       
-       /* signed is a little bit more difficult */
-       
-       /* save the signs of the operands */
-       l = aopGet(AOP(left),0,FALSE,FALSE);      
-       MOVA(l);
-       
-       pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
-       pic14_emitcode("push","acc"); /* save it on the stack */
-       
-       /* now sign adjust for both left & right */
-       l =  aopGet(AOP(right),0,FALSE,FALSE);  
-       MOVA(l);
-       
-       lbl = newiTempLabel(NULL);
-       pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
-       pic14_emitcode("cpl","a");   
-       pic14_emitcode("inc","a");
-       pic14_emitcode("","%05d_DS_:",(lbl->key+100));
-       pic14_emitcode("mov","b,a"); 
-       
-       /* sign adjust left side */
-       l =  aopGet(AOP(left),0,FALSE,FALSE);    
-       MOVA(l);
-       
-       lbl = newiTempLabel(NULL);
-       pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
-       pic14_emitcode("cpl","a");   
-       pic14_emitcode("inc","a");
-       pic14_emitcode("","%05d_DS_:",(lbl->key+100));
-       
-       /* now the multiplication */
-       pic14_emitcode("div","ab");
-       /* we are interested in the lower order
-       only */
-       lbl = newiTempLabel(NULL);
-       pic14_emitcode("pop","acc");     
-       /* if there was an over flow we don't 
-       adjust the sign of the result */
-       pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
-       pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
-       CLRC ;
-       pic14_emitcode("clr","a");
-       pic14_emitcode("subb","a,b");
-       pic14_emitcode("mov","b,a");
-       pic14_emitcode("","%05d_DS_:",(lbl->key+100));
-       
-       /* now we are done */
-       aopPut(AOP(result),"b",0);
        
+       assert (AOP_SIZE(result) == 1);
+       assert (AOP_SIZE(right) == 1);
+       assert (AOP_SIZE(left) == 1);
+
+       size = min(AOP_SIZE(result),AOP_SIZE(left));
+
+       if (AOP_TYPE(right) == AOP_LIT)
+       {
+               /* XXX: might add specialized code */
+       }
+
+       if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
+       {
+               /* unsigned division */
+       #if 1
+               mov2w(AOP(right),0);
+               emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
+               mov2w(AOP(left),0);
+               call_libraryfunc("__moduchar");
+               movwf(AOP(result),0);
+       #else
+               pCodeOp *temp;
+               symbol *lbl;
+
+               lbl = newiTempLabel(NULL);
+               
+               assert(!pic14_sameRegs(AOP(right),AOP(result)));
+
+               /* XXX: improve this naive approach:
+                  [result] = [a] % [b]
+                       ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
+
+                  In PIC assembler:
+                  movf  left,W
+                  movwf result         // result <-- left
+                  movf  right,W        // W <-- right
+                  label1:
+                  subwf result,F       // result <-- result - W
+                  skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
+                  goto  label1
+                  addwf result, F      // we just subtract once too often
+                */
+
+               /* XXX: This loops endlessly on DIVIDE BY ZERO */
+               /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
+               
+               if (!pic14_sameRegs(AOP(left), AOP(result)))
+               {
+                       mov2w(AOP(left),0);
+                       emitpcode(POC_MOVWF, popGet(AOP(result),0));
+               }
+               mov2w(AOP(right),0);
+
+               emitpLabel(lbl->key);
+               emitpcode(POC_SUBWF, popGet(AOP(result),0));
+               emitSKPNC;
+               emitpcode(POC_GOTO, popGetLabel(lbl->key));
+               emitpcode(POC_ADDWF, popGet(AOP(result),0));
+       #endif
+       }
+       else
+       {
+               /* signed division */
+               mov2w(AOP(right),0);
+               emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
+               mov2w(AOP(left),0);
+               call_libraryfunc("__modschar");
+               movwf(AOP(result),0);
+       }
+
+       /* now we performed the signed/unsigned modulus -- extend result */
+       addSign(result, 1, !SPEC_USIGN(operandType(result)));
 }
 
 /*-----------------------------------------------------------------*/
@@ -3651,6 +3732,7 @@ static void genIfxJump (iCode *ic, char *jval)
        ic->generated = 1;
 }
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genSkip                                                                                                                */
 /*-----------------------------------------------------------------*/
@@ -3701,6 +3783,7 @@ static void genSkip(iCode *ifx,int status_bit)
        }
        
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* genSkipc                                                                                                       */
@@ -3721,6 +3804,7 @@ static void genSkipc(resolvedIfx *rifx)
        rifx->generated = 1;
 }
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genSkipz2                                                                                                      */
 /*-----------------------------------------------------------------*/
@@ -3738,15 +3822,16 @@ static void genSkipz2(resolvedIfx *rifx, int invert_condition)
        emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
        rifx->generated = 1;
 }
+#endif
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genSkipz                                                        */
 /*-----------------------------------------------------------------*/
 static void genSkipz(iCode *ifx, int condition)
 {
        FENTRY;
-       if(!ifx)
-               return;
+       assert (ifx != NULL);
        
        if(condition)
                emitSKPNZ;
@@ -3764,6 +3849,7 @@ static void genSkipz(iCode *ifx, int condition)
                pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
        
 }
+#endif
 
 #if 0
 /*-----------------------------------------------------------------*/
@@ -4774,6 +4860,7 @@ static void genCmpLt (iCode *ic, iCode *ifx)
        freeAsmop(result,NULL,ic,TRUE); 
 }
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genc16bit2lit - compare a 16 bit value to a literal             */
 /*-----------------------------------------------------------------*/
@@ -4825,7 +4912,9 @@ static void genc16bit2lit(operand *op, int lit, int offset)
        }
        
 }
+#endif
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* gencjneshort - compare and jump if not equal                    */
 /*-----------------------------------------------------------------*/
@@ -5054,6 +5143,7 @@ static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
                ifx->generated = 1;
 #endif
 }
+#endif
 
 #if 0
 /*-----------------------------------------------------------------*/
@@ -5083,294 +5173,116 @@ static void gencjne(operand *left, operand *right, iCode *ifx)
 /*-----------------------------------------------------------------*/
 static void genCmpEq (iCode *ic, iCode *ifx)
 {
-       operand *left, *right, *result;
-       unsigned long lit = 0L;
-       int size,offset=0;
-       
-       FENTRY;
-       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       
-       if(ifx)
-               DEBUGpic14_emitcode ("; ifx is non-null","");
-       else
-               DEBUGpic14_emitcode ("; ifx is null","");
-       
-       aopOp((left=IC_LEFT(ic)),ic,FALSE);
-       aopOp((right=IC_RIGHT(ic)),ic,FALSE);
-       aopOp((result=IC_RESULT(ic)),ic,TRUE);
-       
-       size = max(AOP_SIZE(left),AOP_SIZE(right));
-       
-       DEBUGpic14_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_isLitLike (AOP(IC_LEFT(ic)))
-                       || (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){
-                                       pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-                                       pic14_emitcode("cpl","c");
-                               } else if(lit == 1L) {
-                                       pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-                               } else {
-                                       pic14_emitcode("clr","c");
-                               }
-                               /* AOP_TYPE(right) == AOP_CRY */
-                       } else {
-                               symbol *lbl = newiTempLabel(NULL);
-                               pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-                               pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
-                               pic14_emitcode("cpl","c");
-                               pic14_emitcode("","%05d_DS_:",(lbl->key+100));
-                       }
-                       /* if true label then we jump if condition
-                       supplied is true */
-                       tlbl = newiTempLabel(NULL);
-                       if ( IC_TRUE(ifx) ) {
-                               pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
-                               pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
-                       } else {
-                               pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
-                               pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
-                       }
-                       pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
-                       
-                       {
-                               /* left and right are both bit variables, result is carry */
-                               resolvedIfx rIfx;
-                               
-                               resolveIfx(&rIfx,ifx);
-                               
-                               emitpcode(POC_MOVLW,popGet(AOP(left),0));
-                               emitpcode(POC_ANDFW,popGet(AOP(left),0));
-                               emitpcode(POC_BTFSC,popGet(AOP(right),0));
-                               emitpcode(POC_ANDLW,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) ) {
-                                                       emitpcode(POC_DECFW,popGet(AOP(left),offset));
-                                                       emitSKPNZ;
-                                                       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
-                                               } else {
-                                                       emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
-                                                       emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
-                                               }
-                                               break;
-                                       case 0xff:
-                                               if ( IC_TRUE(ifx) ) {
-                                                       emitpcode(POC_INCFW,popGet(AOP(left),offset));
-                                                       emitSKPNZ;
-                                                       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
-                                               } else {
-                                                       emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
-                                                       emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
-                                               }
-                                               break;
-                                       default:
-                                               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
-                                               if(lit)
-                                                       emitpcode(POC_XORLW,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) {
-                                                       emitpcode(POC_MOVFW,popGet(AOP(left),0));
-                                                       emitpcode(POC_IORFW,popGet(AOP(left),1));
-                                                       emitpcode(POC_IORFW,popGet(AOP(left),2));
-                                                       emitpcode(POC_IORFW,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 {
-                                                               emitpcode(POC_IORFW,popGet(AOP(left),2));
-                                                               emitpcode(POC_IORFW,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 */
-                               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
-                               emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
-                                       popGet(AOP(right),offset));
-                               emitpcode(POC_XORLW,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)
-                                       emitpcode(POC_IORFW,popGet(AOP(left),offset));
-                               
-                               if ( IC_TRUE(ifx) ) {
-                                       emitSKPNZ;
-                                       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
-                                       pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
-                               } else {
-                                       emitSKPZ;
-                                       emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
-                                       pic14_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--) {
-                                       mov2w (AOP(right),offset); /* right might be litLike() */
-                                       emitpcode(POC_XORFW,popGet(AOP(left),offset));
-                                       
-                                       if ( IC_TRUE(ifx) ) {
-                                               if(size) {
-                                                       emitSKPZ;
-                                                       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
-                                                       pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
-                                               } else {
-                                                       emitSKPNZ;
-                                                       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
-                                                       pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
-                                               }
-                                       } else {
-                                               emitSKPZ;
-                                               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
-                                               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
-                                       }
-                                       offset++;
-                               }
-                               if(s>1 && IC_TRUE(ifx)) {
-                                       emitpLabel(tlbl->key);
-                                       pic14_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){
-                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-                         pic14_emitcode("cpl","c");
-                 } else if(lit == 1L) {
-                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-                 } else {
-                         pic14_emitcode("clr","c");
-                 }
-                 /* AOP_TYPE(right) == AOP_CRY */
-         } else {
-                 symbol *lbl = newiTempLabel(NULL);
-                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
-                 pic14_emitcode("cpl","c");
-                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
-         }
-         /* c = 1 if egal */
-         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
-                 pic14_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 */
-         pic14_outBitC(result);
-  } else {
-         
-         DEBUGpic14_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)) {
-         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) 
-         pic14_outAcc(result);
-         */
-         /* leave the result in acc */
+  operand *left, *right, *result;
+  int size;
+  symbol *false_label;
+
+  FENTRY;
+  DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  if(ifx)
+    DEBUGpic14_emitcode ("; ifx is non-null","");
+  else
+    DEBUGpic14_emitcode ("; ifx is null","");
+
+  aopOp((left=IC_LEFT(ic)),ic,FALSE);
+  aopOp((right=IC_RIGHT(ic)),ic,FALSE);
+  aopOp((result=IC_RESULT(ic)),ic,TRUE);
+
+  DEBUGpic14_AopType(__LINE__,left,right,result);
+
+  /* if literal, move literal to right */ 
+  if (op_isLitLike (IC_LEFT(ic))) {
+    operand *tmp = right ;
+    right = left;
+    left = tmp;
   }
-  
-release:
+
+  false_label = NULL;
+  if (ifx && !IC_TRUE(ifx))
+  {
+    assert (IC_FALSE(ifx));
+    false_label = IC_FALSE(ifx);
+  }
+
+  size = min(AOP_SIZE(left),AOP_SIZE(right));
+  assert(!pic14_sameRegs(AOP(result),AOP(left)));
+  assert(!pic14_sameRegs(AOP(result),AOP(right)));
+
+  /* assume left != right */
+  {
+    int i;
+    for (i=0; i < AOP_SIZE(result); i++)
+    {
+      emitpcode(POC_CLRF, popGet(AOP(result),i));
+    }
+  }
+
+  if (AOP_TYPE(right) == AOP_LIT)
+  {
+    unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
+    int i;
+    size = AOP_SIZE(left);
+    assert(!op_isLitLike(left));
+
+    switch (lit)
+    {
+      case 0:
+        mov2w(AOP(left), 0);
+       for (i=1; i < size; i++)
+         emitpcode(POC_IORFW,popGet(AOP(left),i));
+       /* now Z is set iff `left == right' */
+       emitSKPZ;
+       if (!false_label) false_label = newiTempLabel(NULL);
+       emitpcode(POC_GOTO, popGetLabel(false_label->key));
+       break;
+
+      default:
+       for (i=0; i < size; i++)
+       {
+         mov2w(AOP(left),i);
+         emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
+         /* now Z is cleared if `left != right' */
+         emitSKPZ;
+         if (!false_label) false_label = newiTempLabel(NULL);
+         emitpcode(POC_GOTO, popGetLabel(false_label->key));
+       } // for i
+       break;
+    } // switch (lit)
+  }
+  else
+  {
+    /* right is no literal */
+    int i;
+
+    for (i=0; i < size; i++)
+    {
+      mov2w(AOP(right),i);
+      emitpcode(POC_XORFW,popGet(AOP(left),i));
+      /* now Z is cleared if `left != right' */
+      emitSKPZ;
+      if (!false_label) false_label = newiTempLabel(NULL);
+      emitpcode(POC_GOTO, popGetLabel(false_label->key));
+    } // for i
+  }
+
+  /* if we reach here, left == right */
+
+  if (AOP_SIZE(result) > 0)
+  {
+    emitpcode(POC_INCF, popGet(AOP(result),0));
+  }
+
+  if (ifx && IC_TRUE(ifx))
+  {
+    emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
+  }
+
+  if (false_label && (!ifx || IC_TRUE(ifx)))
+    emitpLabel(false_label->key);
+
+  if (ifx) ifx->generated = 1;
+
   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
   freeAsmop(result,NULL,ic,TRUE);
@@ -5476,6 +5388,7 @@ static void genOrOp (iCode *ic)
 {
        operand *left,*right, *result;
        symbol *tlbl;
+       int i;
        
        /* note here that || operations that are in an
        if statement are taken away by backPatchLabels
@@ -5487,29 +5400,21 @@ static void genOrOp (iCode *ic)
        aopOp((result=IC_RESULT(ic)),ic,FALSE);
        
        DEBUGpic14_AopType(__LINE__,left,right,result);
-       
-       /* if both are bit variables */
-       if (AOP_TYPE(left) == AOP_CRY &&
-               AOP_TYPE(right) == AOP_CRY ) {
-               pic14_emitcode("clrc","");
-               pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
-                       AOP(left)->aopu.aop_dir,
-                       AOP(left)->aopu.aop_dir);
-               pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
-                       AOP(right)->aopu.aop_dir,
-                       AOP(right)->aopu.aop_dir);
-               pic14_emitcode("setc","");
-               
-       } else {
-               tlbl = newiTempLabel(NULL);
-               pic14_toBoolean(left);
-               emitSKPZ;
-               pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
-               pic14_toBoolean(right);
-               pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
-               
-               pic14_outBitAcc(result);
-       }
+
+       for (i=0; i < AOP_SIZE(result); i++)
+       {
+               emitpcode(POC_CLRF, popGet(AOP(result), i));
+       } // for i
+
+       tlbl = newiTempLabel(NULL);
+       pic14_toBoolean(left);
+       emitSKPZ;
+       emitpcode(POC_GOTO, popGetLabel(tlbl->key));
+       pic14_toBoolean(right);
+       emitpLabel(tlbl->key);
+       /* here Z is clear IFF `left || right' */
+       emitSKPZ;
+       emitpcode(POC_INCF, popGet(AOP(result), 0));
        
        freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
        freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
@@ -6555,95 +6460,141 @@ static void genGetHbit (iCode *ic)
 }
 
 /*-----------------------------------------------------------------*/
-/* AccRol - rotate left accumulator by known count                 */
+/* AccLsh - shift left accumulator by known count                  */
+/* MARK: pic14 always rotates through CARRY!                       */
 /*-----------------------------------------------------------------*/
-static void AccRol (operand *op,int offset,int shCount)
+static void AccLsh (pCodeOp *pcop,int shCount)
 {
        FENTRY;
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        shCount &= 0x0007;              // shCount : 0..7
        switch(shCount){
        case 0 :
+               return;
                break;
        case 1 :
-               pic14_emitcode("rl","a");
-               emitpcode(POC_RLF,popGet(AOP(op),offset));
+               emitCLRC;
+               emitpcode(POC_RLF,pcop);
+               return;
                break;
        case 2 :
-               pic14_emitcode("rl","a");
-               pic14_emitcode("rl","a");
-               emitpcode(POC_RLF,popGet(AOP(op),offset));
-               emitpcode(POC_RLF,popGet(AOP(op),offset));
+               emitpcode(POC_RLF,pcop);
+               emitpcode(POC_RLF,pcop);
                break;
        case 3 :
-               pic14_emitcode("swap","a");
-               pic14_emitcode("rr","a");
-               emitpcode(POC_SWAPF,popGet(AOP(op),offset));
-               emitpcode(POC_RRF,popGet(AOP(op),offset));
+               emitpcode(POC_RLF,pcop);
+               emitpcode(POC_RLF,pcop);
+               emitpcode(POC_RLF,pcop);
                break;
        case 4 :
-               pic14_emitcode("swap","a");
-               emitpcode(POC_SWAPF,popGet(AOP(op),offset));
+               emitpcode(POC_SWAPF,pcop);
                break;
        case 5 :
-               pic14_emitcode("swap","a");
-               pic14_emitcode("rl","a");
-               emitpcode(POC_SWAPF,popGet(AOP(op),offset));
-               emitpcode(POC_RLF,popGet(AOP(op),offset));
+               emitpcode(POC_SWAPF,pcop);
+               emitpcode(POC_RLF,pcop);
                break;
        case 6 :
-               pic14_emitcode("rr","a");
-               pic14_emitcode("rr","a");
-               emitpcode(POC_RRF,popGet(AOP(op),offset));
-               emitpcode(POC_RRF,popGet(AOP(op),offset));
+               emitpcode(POC_SWAPF,pcop);
+               emitpcode(POC_RLF,pcop);
+               emitpcode(POC_RLF,pcop);
                break;
        case 7 :
-               pic14_emitcode("rr","a");
-               emitpcode(POC_RRF,popGet(AOP(op),offset));
+               emitpcode(POC_RRFW,pcop);
+               emitpcode(POC_RRF,pcop);
                break;
        }
+       /* clear invalid bits */
+       emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
+       emitpcode(POC_ANDWF, pcop);
 }
 
 /*-----------------------------------------------------------------*/
-/* AccLsh - left shift accumulator by known count                  */
+/* AccRsh - shift right accumulator by known count                 */
+/* MARK: pic14 always rotates through CARRY!                       */
+/* maskmode - 0: leave invalid bits undefined (caller should mask) */
+/*            1: mask out invalid bits (zero-extend)               */
+/*            2: sign-extend result (pretty slow)                  */
 /*-----------------------------------------------------------------*/
-static void AccLsh (operand *op,int offset,int shCount)
+static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
 {
        FENTRY;
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       if(shCount != 0) {
-               if (shCount == 1)
+       shCount &= 0x0007;              // shCount : 0..7
+       switch(shCount){
+       case 0 :
+               return;
+               break;
+       case 1 :
+               /* load sign if needed */
+               if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
+               else if (mask_mode == 1) emitCLRC;
+               emitpcode(POC_RRF,pcop);
+               return;
+               break;
+       case 2 :
+               /* load sign if needed */
+               if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
+               emitpcode(POC_RRF,pcop);
+               /* load sign if needed */
+               if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
+               emitpcode(POC_RRF,pcop);
+               if (mask_mode == 2) return;
+               break;
+       case 3 :
+               /* load sign if needed */
+               if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
+               emitpcode(POC_RRF,pcop);
+               /* load sign if needed */
+               if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
+               emitpcode(POC_RRF,pcop);
+               /* load sign if needed */
+               if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
+               emitpcode(POC_RRF,pcop);
+               if (mask_mode == 2) return;
+               break;
+       case 4 :
+               emitpcode(POC_SWAPF,pcop);
+               break;
+       case 5 :
+               emitpcode(POC_SWAPF,pcop);
+               emitpcode(POC_RRF,pcop);
+               break;
+       case 6 :
+               emitpcode(POC_SWAPF,pcop);
+               emitpcode(POC_RRF,pcop);
+               emitpcode(POC_RRF,pcop);
+               break;
+       case 7 :
+               if (mask_mode == 2)
                {
-                       emitCLRC;
-                       emitpcode (POC_RLF, popGet (AOP(op), 0));
+                       /* load sign */
+                       emitpcode(POC_RLFW,pcop);
+                       emitpcode(POC_CLRF,pcop);
+                       emitSKPNC;
+                       emitpcode(POC_COMF,pcop);
+                       return;
                } else {
-                       /* rotate left accumulator */
-                       AccRol(op,offset,shCount);
-                       /* and kill the lower order bits */
-                       emitpcode(POC_MOVLW,popGetLit(SLMask[shCount]));
-                       emitpcode (POC_ANDWF, popGet (AOP(op),0));
+                       emitpcode(POC_RLFW,pcop);
+                       emitpcode(POC_RLF,pcop);
                }
+               break;
        }
-}
 
-/*-----------------------------------------------------------------*/
-/* AccRsh - right shift accumulator by known count                 */
-/*-----------------------------------------------------------------*/
-static void AccRsh (operand *op,int offset,int shCount)
-{
-       FENTRY;
-       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       if(shCount != 0){
-               if(shCount == 1){
-                       emitCLRC;
-                       emitpcode (POC_RRF, popGet (AOP(op), 0));
-               } else {
-                       /* rotate right accumulator */
-                       AccRol(op,offset,8 - shCount);
-                       /* and kill the higher order bits */
-                       emitpcode (POC_MOVLW, popGetLit (SRMask[shCount]));
-                       emitpcode (POC_ANDWF, popGet (AOP(op),0));
-               }
+       if (mask_mode == 0)
+       {
+               /* leave invalid bits undefined */
+               return;
+       }
+       
+       /* clear invalid bits -- zero-extend */
+       emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
+       emitpcode(POC_ANDWF, pcop);
+
+       if (mask_mode == 2) {
+         /* sign-extend */
+         emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
+         emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
+         emitpcode(POC_IORWF, pcop);
        }
 }
 
@@ -7758,6 +7709,8 @@ static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
        }
        
 }
+
+#if 0
 /*-----------------------------------------------------------------*/
 /* genLeftShift - generates code for left shifting                 */
 /*-----------------------------------------------------------------*/
@@ -7933,6 +7886,7 @@ release:
        freeAsmop(left,NULL,ic,TRUE);
        freeAsmop(result,NULL,ic,TRUE);
 }
+#endif
 
 #if 0
 /*-----------------------------------------------------------------*/
@@ -8156,6 +8110,7 @@ static void genRightShiftLiteral (operand *left,
 }
 #endif
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genSignedRightShift - right shift of signed number              */
 /*-----------------------------------------------------------------*/
@@ -8297,17 +8252,31 @@ release:
        freeAsmop(result,NULL,ic,TRUE);
        freeAsmop(right,NULL,ic,TRUE);
 }
+#endif
+
+/*-----------------------------------------------------------------*/
+/* loadSignToC - load the operand's sign bit into CARRY            */
+/*-----------------------------------------------------------------*/
+
+static void loadSignToC (operand *op)
+{
+       FENTRY;
+       assert (op && AOP(op) && AOP_SIZE(op));
+
+       emitCLRC;
+       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
+       emitSETC;
+}
 
 /*-----------------------------------------------------------------*/
 /* genRightShift - generate code for right shifting                */
 /*-----------------------------------------------------------------*/
-static void genRightShift (iCode *ic)
+static void genGenericShift (iCode *ic, int shiftRight)
 {
        operand *right, *left, *result;
        sym_link *retype ;
-       int size, offset;
-       char *l;
-       symbol *tlbl, *tlbl1 ;
+       int size;
+       symbol *tlbl, *tlbl1, *inverselbl;
        
        FENTRY;
        /* if signed then we do it the hard way preserve the
@@ -8315,11 +8284,6 @@ static void genRightShift (iCode *ic)
        retype = getSpec(operandType(IC_RESULT(ic)));
        DEBUGpic14_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
@@ -8338,7 +8302,17 @@ static void genRightShift (iCode *ic)
        /* if the shift count is known then do it 
        as efficiently as possible */
        if (AOP_TYPE(right) == AOP_LIT) {
-               shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 0);
+               int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
+               if (lit < 0)
+               {
+                       lit = -lit;
+                       shiftRight = !shiftRight;
+               }
+               
+               if (shiftRight)
+                       shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
+               else
+                       shiftLeft_Left2ResultLit (left, result, lit);
                //genRightShiftLiteral (left,right,result,ic, 0);
                return ;
        }
@@ -8348,224 +8322,307 @@ static void genRightShift (iCode *ic)
        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 ) */  
-       
-       pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
-       pic14_emitcode("inc","b");
+
+       /* we must not overwrite the shift counter */
+       assert (!pic14_sameRegs(AOP(right),AOP(result)));
        
        /* now move the left to the result if they are not the
        same */
-       if (!pic14_sameRegs(AOP(left),AOP(result)) && 
-               AOP_SIZE(result) > 1) {
-               
-               size = AOP_SIZE(result);
-               offset=0;
+       if (!pic14_sameRegs(AOP(left),AOP(result)))
+       {
+               size = min(AOP_SIZE(result), AOP_SIZE(left));
                while (size--) {
-                       l = aopGet(AOP(left),offset,FALSE,TRUE);
-                       if (*l == '@' && IS_AOP_PREG(result)) {
-                               
-                               pic14_emitcode("mov","a,%s",l);
-                               aopPut(AOP(result),"a",offset);
-                       } else
-                               aopPut(AOP(result),l,offset);
-                       offset++;
+                       mov2w(AOP(left), size);
+                       movwf(AOP(result), size);
                }
+               addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
        }
        
        tlbl = newiTempLabel(NULL);
        tlbl1= newiTempLabel(NULL);
+       inverselbl = NULL;
        size = AOP_SIZE(result);
-       offset = size - 1;
-       
-       /* if it is only one byte then */
-       if (size == 1) {
+
+       mov2w(AOP(right),0);
+       if (!SPEC_USIGN(operandType(right)))
+       {
+               inverselbl = newiTempLabel(NULL);
+               /* signed shift count -- invert shift direction for c<0 */
+               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
+               emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
+       } // if
+       emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
+       /* check for `a = b >> c' with `-c == 0' */
+       emitSKPNZ;
+       emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
+       emitpLabel(tlbl->key);
+       /* propagate the sign bit inwards for SIGNED result */
+       if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
+       genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
+       emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
+       emitSKPC;
+       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
+
+       if (!SPEC_USIGN(operandType(right)))
+       {
+               symbol *inv_loop = newiTempLabel(NULL);
+
+               shiftRight = !shiftRight;       /* invert shift direction */
                
-               tlbl = newiTempLabel(NULL);
-               if (!pic14_sameRegs(AOP(left),AOP(result))) {
-                       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
-                       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
-               }
+               /* we came here from the code above -- we are done */
+               emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
                
-               emitpcode(POC_COMFW,  popGet(AOP(right),0));
-               emitpcode(POC_RLF,    popGet(AOP(result),0));
-               emitpLabel(tlbl->key);
-               emitpcode(POC_RRF,    popGet(AOP(result),0));
-               emitpcode(POC_ADDLW,  popGetLit(1));
+               /* emit code for shifting N<0 steps, count is already in W */
+               emitpLabel(inverselbl->key);
+               if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
+               emitpLabel(inv_loop->key);
+               /* propagate the sign bit inwards for SIGNED result */
+               if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
+               genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
+               emitpcode(POC_ADDLW, popGetLit(1));
                emitSKPC;
-               emitpcode(POC_GOTO,popGetLabel(tlbl->key));
-               
-               goto release ;
-       }
-       
-       reAdjustPreg(AOP(result));
-       pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
-       pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
-       CLRC;
-       while (size--) {
-               l = aopGet(AOP(result),offset,FALSE,FALSE);
-               MOVA(l);
-               pic14_emitcode("rrc","a");         
-               aopPut(AOP(result),"a",offset--);
-       }
-       reAdjustPreg(AOP(result));
+               emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
+       } // if
        
-       pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
-       pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
+       emitpLabel(tlbl1->key);
        
-release:
        freeAsmop(left,NULL,ic,TRUE);
        freeAsmop (right,NULL,ic,TRUE);
        freeAsmop(result,NULL,ic,TRUE);
 }
 
+static void genRightShift (iCode *ic)
+{
+       genGenericShift(ic, 1);
+}
+
+static void genLeftShift (iCode *ic)
+{
+       genGenericShift(ic, 0);
+}
+
 /*-----------------------------------------------------------------*/
-/* genUnpackBits - generates code for unpacking bits               */
+/* SetIrp - Set IRP bit                                            */
 /*-----------------------------------------------------------------*/
-static void genUnpackBits (operand *result, operand *left, char *rname, int ptype, iCode *ifx)
-{    
-       int shCnt;
-       int offset = 0;       /* result byte offset */
-       int rsize;            /* result size */
-       int rlen = 0;         /* remaining bitfield length */
-       sym_link *etype;      /* bitfield type information */
-       int blen;             /* bitfield length */
-       int bstr;             /* bitfield starting bit within byte */
-
+void SetIrp(operand *result) {
        FENTRY;
-       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       etype = getSpec(operandType(result));
-       rsize = getSize (operandType (result));
-       blen = SPEC_BLEN (etype);
-       bstr = SPEC_BSTR (etype);
-       
-       /* single bit field case */
-       if (blen == 1) {
-               if (ifx) { /* that is for an if statement */
-                       pCodeOp *pcop;
-                       resolvedIfx rIfx;
-                       resolveIfx(&rIfx,ifx);
-                       if (ptype == -1) /* direct */
-                               pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
+       if (AOP_TYPE(result) == AOP_LIT) {
+               unsigned lit = (unsigned)operandLitValue(result);
+               if (lit&0x100)
+                       emitSETIRP;
+               else
+                       emitCLRIRP;
+       } else {
+               if (PCOP(AOP(result))->type == PO_LITERAL) {
+                       int addrs = PCOL(AOP(result))->lit;
+                       if (addrs & 0x100)
+                               emitSETIRP;
                        else
-                               pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
-                       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
-                       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
-                       ifx->generated=1;
+                               emitCLRIRP;
                } else {
-                       pCodeOp *pcop;
-                       int i;
-                       assert (!pic14_sameRegs (AOP(result), AOP(left)));
-                       for (i=0; i < AOP_SIZE(result); i++)
-                               emitpcode (POC_CLRF, popGet (AOP(result), i));
-                       if (ptype == -1) /* direct */
-                               pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
-                       else
-                               pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
-                       emitpcode(POC_BTFSC,pcop);
-                       emitpcode(POC_BSF,newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),0,0));
+                       emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
+                       if(AOP_SIZE(result) > 1) {
+                               emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
+                               emitSETIRP;
+                       }
                }
-               return;
        }
+}
 
-       {
-         static int has_warned=0;
-         if (!has_warned)
-         {
-           fprintf (stderr, "%s: bitfields with more than 1 bit are probably broken...", __FUNCTION__);
-           has_warned=1;
-         }
-       }
+static void
+setup_fsr (operand *ptr)
+{
+  mov2w_op(ptr, 0);
+  emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
 
-       /* read the first byte  */
-       switch (ptype) {
-               
-       case POINTER:
-       case IPOINTER:
-//             pic14_emitcode("mov","a,@%s",rname);
-               emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
-               break;
-               
-       case PPOINTER:
-               pic14_emitcode("movx","a,@%s",rname);
-               break;
-               
-       case FPOINTER:
-               pic14_emitcode("movx","a,@dptr");
-               break;
-               
-       case CPOINTER:
-               pic14_emitcode("clr","a");
-               pic14_emitcode("movc","a","@a+dptr");
-               break;
-               
-       case GPOINTER:
-               pic14_emitcode("lcall","__gptrget");
-               break;
-       }
+  /* also setup-up IRP */
+  SetIrp (ptr);
+}
 
-       /* if we have bitdisplacement then it fits   */
-       /* into this byte completely or if length is */
-       /* less than a byte                          */
-       if ((shCnt = SPEC_BSTR(etype)) || blen <= 8)  {
-               
-               /* shift right acc */
-               AccRsh(left,0,shCnt);
-               
-               pic14_emitcode("anl","a,#0x%02x",
-                       ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
-               aopPut(AOP(result),"a",offset);
-               return ;
-       }
-       
-       /* bit field did not fit in a byte  */
-       rlen = SPEC_BLEN(etype) - 8;
-       aopPut(AOP(result),"a",offset++);
-       
-       while (1)  {
-               
-               switch (ptype) {
-               case POINTER:
-               case IPOINTER:
-                       pic14_emitcode("inc","%s",rname);
-                       pic14_emitcode("mov","a,@%s",rname);
-                       break;
-                       
-               case PPOINTER:
-                       pic14_emitcode("inc","%s",rname);
-                       pic14_emitcode("movx","a,@%s",rname);
-                       break;
-                       
-               case FPOINTER:
-                       pic14_emitcode("inc","dptr");
-                       pic14_emitcode("movx","a,@dptr");
-                       break;
-                       
-               case CPOINTER:
-                       pic14_emitcode("clr","a");
-                       pic14_emitcode("inc","dptr");
-                       pic14_emitcode("movc","a","@a+dptr");
-                       break;
-                       
-               case GPOINTER:
-                       pic14_emitcode("inc","dptr");
-                       pic14_emitcode("lcall","__gptrget");
-                       break;
-               }
-               
-               rlen -= 8;            
-               /* if we are done */
-               if ( rlen <= 0 )
-                       break ;
-               
-               aopPut(AOP(result),"a",offset++);
-               
-       }
-       
-       if (rlen) {
-               pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
-               aopPut(AOP(result),"a",offset);        
-       }
-       
-       return ;
+/*-----------------------------------------------------------------*/
+/* emitPtrByteGet - emits code to get a byte into WREG from an     */
+/*                  arbitrary pointer (__code, __data, generic)    */
+/*-----------------------------------------------------------------*/
+static void
+emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
+{
+    FENTRY;
+    switch (p_type)
+    {
+    case POINTER:
+      if (!alreadyAddressed) setup_fsr (src);
+      emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
+      break;
+    
+    case CPOINTER:
+      assert( AOP_SIZE(src) == 2 );
+      mov2w_op(src, 0);
+      emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
+      mov2w_op(src, 1);
+      emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
+      emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));  /* GPOINTER tag for __code space */
+      call_libraryfunc ("__gptrget1");
+      break;
+    
+    case GPOINTER:
+      assert( AOP_SIZE(src) == 3 );
+      mov2w_op(src, 0);
+      emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
+      mov2w_op(src, 1);
+      emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
+      mov2w_op(src, 2);
+      call_libraryfunc ("__gptrget1");
+      break;
+    
+    default:
+      assert( !"unhandled pointer type" );
+      break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* emitPtrByteSet - emits code to set a byte from src through a    */
+/* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
+/*-----------------------------------------------------------------*/
+static void
+emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
+{
+    FENTRY;
+    switch (p_type)
+    {
+    case POINTER:
+      if (!alreadyAddressed) setup_fsr (dst);
+      emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
+      break;
+    
+    case CPOINTER:
+      assert( !"trying to assign to __code pointer" );
+      break;
+    
+    case GPOINTER:
+      emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
+      mov2w_op(dst, 0);
+      emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
+      mov2w_op(dst, 1);
+      emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
+      mov2w_op(dst, 2);
+      call_libraryfunc ("__gptrput1");
+      break;
+
+    default:
+      assert( !"unhandled pointer type" );
+      break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genUnpackBits - generates code for unpacking bits               */
+/*-----------------------------------------------------------------*/
+static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
+{    
+  int rsize;            /* result size */
+  sym_link *etype;      /* bitfield type information */
+  int blen;             /* bitfield length */
+  int bstr;             /* bitfield starting bit within byte */
+
+  FENTRY;
+  DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  etype = getSpec(operandType(result));
+  rsize = getSize (operandType (result));
+  blen = SPEC_BLEN (etype);
+  bstr = SPEC_BSTR (etype);
+
+  /* single bit field case */
+  if (blen == 1) {
+    if (ifx) { /* that is for an if statement */
+      pCodeOp *pcop;
+      resolvedIfx rIfx;
+      resolveIfx(&rIfx,ifx);
+      if (ptype == -1) /* direct */
+       pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
+      else
+       pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
+      emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
+      emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
+      ifx->generated=1;
+    } else {
+      int i;
+      assert (!pic14_sameRegs (AOP(result), AOP(left)));
+      for (i=0; i < AOP_SIZE(result); i++)
+       emitpcode (POC_CLRF, popGet (AOP(result), i));
+
+      switch (ptype)
+      {
+      case -1:
+        emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
+       /* adjust result below */
+        break;
+       
+      case POINTER:
+      case GPOINTER:
+      case CPOINTER:
+        emitPtrByteGet (left, ptype, FALSE);
+       emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
+       emitSKPZ;
+       /* adjust result below */
+        break;
+       
+      default:
+        assert( !"unhandled pointer type" );
+      } // switch
+
+      /* move sign-/zero extended bit to result */
+      if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
+       emitpcode (POC_INCF, popGet (AOP(result), 0));
+      } else {
+       emitpcode (POC_DECF, popGet (AOP(result), 0));
+      }
+      addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
+    }
+    return;
+  }
+  else if (blen <= 8 && ((blen + bstr) <= 8))
+  {
+    /* blen > 1 */
+    int i;
+
+    for (i=0; i < AOP_SIZE(result); i++)
+      emitpcode (POC_CLRF, popGet (AOP(result), i));
+
+    switch (ptype)
+    {
+    case -1:
+      mov2w(AOP(left), 0);
+      break;
+      
+    case POINTER:
+    case GPOINTER:
+    case CPOINTER:
+      emitPtrByteGet (left, ptype, FALSE);
+      break;
+      
+    default:
+      assert( !"unhandled pointer type" );
+    } // switch
+
+    if (blen < 8)
+      emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
+    movwf(AOP(result), 0);
+    AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
+
+    if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
+    {
+      /* signed bitfield */
+      assert (bstr + blen > 0);
+      emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
+      emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
+      emitpcode(POC_IORWF, popGet(AOP(result),0));
+    }
+    addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
+    return;
+  }
+
+  assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
 }
 
 #if 1
@@ -8596,8 +8653,9 @@ static void genDataPointerGet (operand *left,
        //emitpcode(POC_MOVFW, popGet(AOP(left),0));
        
        size = AOP_SIZE(result);
-       if (size > AOP_SIZE(left)) size = AOP_SIZE(left);
+       if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
        
+       offset = 0;
        while (size--) {
                emitpcode(POC_MOVFW, popGet(AOP(left),offset));
                emitpcode(POC_MOVWF, popGet(AOP(result),offset));
@@ -8608,6 +8666,7 @@ static void genDataPointerGet (operand *left,
        freeAsmop(result,NULL,ic,TRUE);
 }
 #endif
+
 /*-----------------------------------------------------------------*/
 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
 /*-----------------------------------------------------------------*/
@@ -8642,27 +8701,26 @@ static void genNearPointerGet (operand *left,
        aopOp (result,ic,FALSE);
        
        /* Check if can access directly instead of via a pointer */
-       if (PCOP(AOP(left))->type == PO_LITERAL && AOP_SIZE(result) == 1) {
+       if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
+               && AOP_SIZE(result) == 1)
+       {
                direct = 1;
        }
 
-       /* If the pointer value is not in a the FSR then need to put it in */
-       if (!AOP_INPREG(AOP(left)) && !direct) {
-               /* otherwise get a free pointer register */
-               DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-               if (PCOP(AOP(result))->type == PO_LITERAL) /* XXX: check me */ 
-                       emitpcode(POC_MOVLW, popGet(AOP(left),0));
-               else
-                       emitpcode(POC_MOVFW, popGet(AOP(left),0));
-               emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
+       if (IS_BITFIELD(getSpec(operandType(result)))) 
+       {
+               genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
+               goto release;
        }
        
+       /* If the pointer value is not in a the FSR then need to put it in */
+       /* Must set/reset IRP bit for use with FSR. */
+       if (!direct)
+         setup_fsr (left);
        
 //     sym_link *etype;
        /* if bitfield then unpack the bits */
-       if (IS_BITFIELD(retype)) 
-               genUnpackBits (result,left,"indf",direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
-       else {
+       {
                /* we have can just get the values */
                int size = AOP_SIZE(result);
                int offset = 0 ;  
@@ -8707,12 +8765,14 @@ static void genNearPointerGet (operand *left,
                }
        }
        
+release:
        /* done */
        freeAsmop(left,NULL,ic,TRUE);
        freeAsmop(result,NULL,ic,TRUE);
 
 }
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
 /*-----------------------------------------------------------------*/
@@ -8845,6 +8905,8 @@ static void genFarPointerGet (operand *left,
        
        freeAsmop(result,NULL,ic,TRUE);
 }
+#endif
+
 #if 0
 /*-----------------------------------------------------------------*/
 /* genCodePointerGet - get value from code space                  */
@@ -8903,9 +8965,6 @@ static void genCodePointerGet (operand *left,
 static void genGenPointerGet (operand *left,
                                                          operand *result, iCode *ic)
 {
-       int size, offset ;
-       sym_link *retype = getSpec(operandType(result));
-       
        FENTRY;
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        aopOp(left,ic,FALSE);
@@ -8913,39 +8972,38 @@ static void genGenPointerGet (operand *left,
        
        
        DEBUGpic14_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) {
-               pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
-               pic14_emitcode("mov","b,#%d",pointerCode(retype));
+
+       if (IS_BITFIELD(getSpec(operandType(result))))
+       {
+         genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
+         return;
        }
-       else { /* we need to get it byte by byte */
-               
-               emitpcode(POC_MOVFW,popGet(AOP(left),0));
-               emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
-               
-               size = AOP_SIZE(result);
-               offset = 0 ;
-               
-               while(size--) {
-                       emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
-                       emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
-                       if(size)
-                               emitpcode(POC_INCF,popCopyReg(&pc_fsr));
-               }
-               goto release;
+
+       {
+         /* emit call to __gptrget */
+         char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
+         int size = AOP_SIZE(result);
+         int idx = 0;
+
+         assert (size > 0 && size <= 4);
+
+         /* pass arguments */
+         assert (AOP_SIZE(left) == 3);
+         mov2w(AOP(left), 0);
+         emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
+         mov2w(AOP(left), 1);
+         emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
+         mov2w(AOP(left), 2);
+         call_libraryfunc (func[size]);
+         
+         /* save result */
+         movwf (AOP(result), --size);
+         while (size--) {
+           emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
+           movwf (AOP(result), size);
+         } // while
        }
-       //}
-       /* so dptr know contains the address */
-       
-       /* if bit then unpack */
-       //if (IS_BITFIELD(retype)) 
-       //  genUnpackBits(result,"dptr",GPOINTER);
        
-release:
        freeAsmop(left,NULL,ic,TRUE);
        freeAsmop(result,NULL,ic,TRUE);
        
@@ -8958,10 +9016,12 @@ static void genConstPointerGet (operand *left,
                                                                operand *result, iCode *ic)
 {
        //sym_link *retype = getSpec(operandType(result));
+       #if 0
        symbol *albl, *blbl;//, *clbl;
+       pCodeOp *pcop;
+       #endif
        PIC_OPCODE poc;
        int i, size, lit;
-       pCodeOp *pcop;
        
        FENTRY;
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
@@ -8974,70 +9034,36 @@ static void genConstPointerGet (operand *left,
        
        DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
 
-       lit = aop_isLitLike (AOP(left));
+       lit = op_isLitLike (left);
        poc = lit ? POC_MOVLW : POC_MOVFW;
 
-       if (lit)
+       if (IS_BITFIELD(getSpec(operandType(result))))
        {
-               for (i = 0; i < size; i++)
-               {
-                       albl = newiTempLabel(NULL);
-                       blbl = newiTempLabel(NULL);
-                       
-                       emitpcode(POC_CALL,popGetLabel(albl->key));
-                       pcop = popGetLabel(blbl->key);
-                       emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
-                       emitpcode(POC_GOTO,pcop);
-                       
-                       emitpLabel(albl->key);
-                       emitpcode(poc,popGetAddr(AOP(left),1,i));
-                       emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
-                       emitpcode(poc,popGetAddr(AOP(left),0,i));
-                       emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
-               
-                       emitpLabel(blbl->key);
-                       emitpcode(POC_MOVWF,popGet(AOP(result),i));
-               } // for
-       } else {
-               albl = newiTempLabel(NULL);
-               blbl = newiTempLabel(NULL);
-               //clbl = newiTempLabel(NULL);
+               genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
+               goto release;
+       }
 
-               emitpcode (POC_GOTO, popGetLabel (blbl->key));
-               
-               emitpLabel(albl->key);
-               emitpcode(poc,popGet(AOP(left),1));
-               emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
-               emitpcode(poc,popGet(AOP(left),0));
-               emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
-               
-               emitpLabel(blbl->key);
-               
-               for (i = 0; i < size; i++)
+       {
+               char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
+               int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
+               assert (size > 0 && size <= 4);
+               
+               mov2w_op(left, 0);
+               emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
+               mov2w_op(left, 1);
+               emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
+               emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
+               call_libraryfunc (func[size]);
+
+               movwf(AOP(result),size-1);
+               for (i = 1; i < size; i++)
                {
-                       emitpcode(POC_CALL,popGetLabel(albl->key));
-                       /* the next two instructions (plus clbl) might be useless... */
-                       //pcop = popGetLabel(clbl->key);
-                       //emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
-                       //emitpcode(POC_GOTO,pcop);
-                       //emitpLabel(clbl->key);
-
-                       if (i+1 < size) {
-                               emitpcode (POC_INCF, popGet (AOP(left), 0));
-                               emitSKPNZ;
-                               emitpcode (POC_INCF, popGet (AOP(left), 1));
-                       }
-                       emitpcode(POC_MOVWF,popGet(AOP(result),i));
+                       emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
+                       movwf(AOP(result),size - 1 - i);
                } // for
-               if (size > 1) {
-                       /* restore left's value */
-                       emitpcode (POC_MOVLW, popGetLit (size-1));
-                       emitpcode (POC_SUBWF, popGet (AOP(left), 0));
-                       emitSKPC;
-                       emitpcode (POC_DECF, popGet (AOP(left), 1));
-               } // if
-       } // if (lit)
+       }
        
+release:
        freeAsmop(left,NULL,ic,TRUE);
        freeAsmop(result,NULL,ic,TRUE);
        
@@ -9100,10 +9126,10 @@ static void genPointerGet (iCode *ic)
        switch (p_type) {
                
        case POINTER: 
-       case IPOINTER:
+       //case IPOINTER:
                genNearPointerGet (left,result,ic);
                break;
-               
+/*
        case PPOINTER:
                genPagedPointerGet(left,result,ic);
                break;
@@ -9111,17 +9137,13 @@ static void genPointerGet (iCode *ic)
        case FPOINTER:
                genFarPointerGet (left,result,ic);
                break;
-               
+*/             
        case CPOINTER:
                genConstPointerGet (left,result,ic);
-               //pic14_emitcodePointerGet (left,result,ic);
                break;
                
        case GPOINTER:
-               if (IS_CODEPTR(type) || IS_PTR_CONST(type) || SPEC_CONST(etype))
-                       genConstPointerGet (left,result,ic);
-               else
-                       genGenPointerGet (left,result,ic);
+               genGenPointerGet (left,result,ic);
                break;
        default:
                assert ( !"unhandled pointer type" );
@@ -9131,282 +9153,216 @@ static void genPointerGet (iCode *ic)
 }
 
 /*-----------------------------------------------------------------*/
-/* emitPtrByteGet - for legacy 8051 emits code to get a byte into  */
-/* A through a pointer register (R0, R1, or DPTR). The original    */
-/* value of A can be preserved in B.                               */
-/* PIC has to use INDF register.                                   */
+/* genPackBits - generates code for packed bit storage             */
 /*-----------------------------------------------------------------*/
-static void
-emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
+static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
 {
-    FENTRY;
-    switch (p_type)
-    {
-    case IPOINTER:
-    case POINTER:
-               if (preserveAinB)
-                       pic14_emitcode ("mov", "b,a");
-//             pic14_emitcode ("mov", "a,@%s", rname);
-               emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
-               break;
-               
-    case PPOINTER:
-               if (preserveAinB)
-                       pic14_emitcode ("mov", "b,a");
-               pic14_emitcode ("movx", "a,@%s", rname);
-               break;
-               
-    case FPOINTER:
-               if (preserveAinB)
-                       pic14_emitcode ("mov", "b,a");
-               pic14_emitcode ("movx", "a,@dptr");
-               break;
-               
-    case CPOINTER:
-               if (preserveAinB)
-                       pic14_emitcode ("mov", "b,a");
-               pic14_emitcode ("clr", "a");
-               pic14_emitcode ("movc", "a,@a+dptr");
-               break;
-               
-    case GPOINTER:
-               if (preserveAinB)
-        {
-                       pic14_emitcode ("push", "b");
-                       pic14_emitcode ("push", "acc");
-        }
-               pic14_emitcode ("lcall", "__gptrget");
-               if (preserveAinB)
-                       pic14_emitcode ("pop", "b");
-               break;
-    }
-}
+  int blen;             /* bitfield length */
+  int bstr;             /* bitfield starting bit within byte */
+  int litval;           /* source literal value (if AOP_LIT) */
+  unsigned char mask;   /* bitmask within current byte */
 
-/*-----------------------------------------------------------------*/
-/* emitPtrByteSet - emits code to set a byte from src through a    */
-/* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
-/*-----------------------------------------------------------------*/
-static void
-emitPtrByteSet (char *rname, int p_type, char *src)
-{
-    FENTRY;
-    switch (p_type)
-    {
-    case IPOINTER:
-    case POINTER:
-               if (*src=='@')
-        {
-                       MOVA (src);
-                       pic14_emitcode ("mov", "@%s,a", rname);
-        }
-               else
-//                     pic14_emitcode ("mov", "@%s,%s", rname, src);
-                       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
-               break;
-               
-    case PPOINTER:
-               MOVA (src);
-               pic14_emitcode ("movx", "@%s,a", rname);
-               break;
-               
-    case FPOINTER:
-               MOVA (src);
-               pic14_emitcode ("movx", "@dptr,a");
-               break;
-               
-    case GPOINTER:
-               MOVA (src);
-               pic14_emitcode ("lcall", "__gptrput");
-               break;
-    }
-}
+  FENTRY;
+  DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
-/*-----------------------------------------------------------------*/
-/* genPackBits - generates code for packed bit storage             */
-/*-----------------------------------------------------------------*/
-static void genPackBits(sym_link *etype,operand *result,operand *right,char *rname,int p_type)
-{
-       int offset = 0;       /* source byte offset */
-       int rlen = 0;         /* remaining bitfield length */
-       int blen;             /* bitfield length */
-       int bstr;             /* bitfield starting bit within byte */
-       int litval;           /* source literal value (if AOP_LIT) */
-       unsigned char mask;   /* bitmask within current byte */
+  blen = SPEC_BLEN (etype);
+  bstr = SPEC_BSTR (etype);
 
-       FENTRY;
-       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  /* If the bitfield length is less than a byte and does not cross byte boundaries */
+  if ((blen <= 8) && ((bstr + blen) <= 8))
+  {
+    mask = ((unsigned char) (0xFF << (blen + bstr)) |
+           (unsigned char) (0xFF >> (8 - bstr)));
+
+    if (AOP_TYPE (right) == AOP_LIT)
+    {
+      /* Case with a bitfield length <8 and literal source */
+      int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+      if (blen == 1) {
+        pCodeOp *pcop;
        
-       blen = SPEC_BLEN (etype);
-       bstr = SPEC_BSTR (etype);
+       switch (p_type)
+       {
+       case -1:
+         if (AOP(result)->type == AOP_PCODE)
+           pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
+         else
+           pcop = popGet(AOP(result),0);
+         emitpcode(lit?POC_BSF:POC_BCF,pcop);
+         break;
        
-       /* If the bitfield length is less than a byte */
-       if (blen < 8)
-    {
-               mask = ((unsigned char) (0xFF << (blen + bstr)) |
-                       (unsigned char) (0xFF >> (8 - bstr)));
-               
-               if (AOP_TYPE (right) == AOP_LIT)
-        {
-                       /* Case with a bitfield length <8 and literal source
-                       */
-                       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
-                       if (blen == 1) {
-                               if (p_type == -1) {
-                                       pCodeOp *pcop;
-                                       if (AOP(result)->type == AOP_PCODE)
-                                               pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
-                                       else
-                                               pcop = popGet(AOP(result),0);
-                                       emitpcode(lit?POC_BSF:POC_BCF,pcop);
-                               } else {
-                                       emitpcode(lit?POC_BSF:POC_BCF,popCopyReg(&pc_indf));
-                               }
-                               return;
-                       } else {
-                               litval = lit << bstr;
-                               litval &= (~mask) & 0xff;
-                               if (p_type == -1)
-                                       emitpcode(POC_MOVFW,popGet(AOP(result),0));
-                               else
-                                       emitPtrByteGet (rname, p_type, FALSE);
-                               if ((mask|litval)!=0xff)
-                                       emitpcode(POC_ANDLW,popGetLit(mask));
-                               if (litval)
-                                       emitpcode(POC_IORLW,popGetLit(litval));
-                       }
-        }
-               else
-        {
-                       if (blen==1) {
-                               if (p_type == -1) {
-                                       /* Note more efficient code, of pre clearing bit then only setting it if required, can only be done if it is known that the result is not a SFR */
-                                       emitpcode(POC_RRFW,popGet(AOP(right),0));
-                                       emitSKPC;
-                                       emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
-                                       emitSKPNC;
-                                       emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
-                                       return;
-                               } else if (p_type!=GPOINTER) {
-                                       /* Case with a bitfield length == 1 and no generic pointer
-                                       */
-                                       if (AOP_TYPE (right) == AOP_CRY)
-                                               pic14_emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
-                                       else
-                                       {
-                                               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
-                                               pic14_emitcode ("rrc","a");
-                                       }
-                                       emitPtrByteGet (rname, p_type, FALSE);
-                                       pic14_emitcode ("mov","acc.%d,c",bstr);
-                               }
-            }
-                       else
-            {
-                               //bool pushedB;
-                               /* Case with a bitfield length < 8 and arbitrary source
-                               */
-                               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
-                               /* shift and mask source value */
-                               AccLsh (right,0,bstr);
-                               pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
-                               emitpcode(POC_ANDLW, popGetLit((~mask) & 0xff));
-                               
-                               //pushedB = pushB ();
-                               if (p_type == -1)
-                                       emitpcode(POC_MOVFW,popGet(AOP(result),0));
-                               else
-                                       emitPtrByteGet (rname, p_type, TRUE);
-                               
-                               pic14_emitcode ("anl", "a,#0x%02x", mask);
-                               pic14_emitcode ("orl", "a,b");
-                               emitpcode(POC_ANDLW,popGetLit(mask));
-                               emitpcode(POC_IORFW,popGet(AOP(right),0));
-                               if (p_type == GPOINTER)
-                                       pic14_emitcode ("pop", "b");
-                               
-                               //popB (pushedB);
-                       }
-        }
-               
-               if (p_type == -1)
-                       emitpcode(POC_MOVWF,popGet(AOP(result),0));
-               else
-                       emitPtrByteSet (rname, p_type, "a");
-               return;
-    }
+       case POINTER:
+         setup_fsr (result);
+         emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
+         break;
+       
+       case CPOINTER:
+         assert( !"trying to assign to bitfield via pointer to __code space" );
+         break;
+       
+       case GPOINTER:
+         emitPtrByteGet(result, p_type, FALSE);
+         if (lit) {
+           emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
+         } else {
+           emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
+         }
+         emitPtrByteSet(result, p_type, TRUE);
+         break;
+       
+       default:
+         assert( !"unhandled pointer type" );
+         break;
+       } // switch (p_type)
+      } else {
+        /* blen > 1 */
+       litval = lit << bstr;
+       litval &= (~mask) & 0x00ff;
+       
+       switch (p_type)
+       {
+       case -1:
+         mov2w (AOP(result), 0);
+         if ((litval|mask) != 0x00ff)
+           emitpcode(POC_ANDLW, popGetLit (mask));
+         if (litval != 0x00)
+           emitpcode(POC_IORLW, popGetLit (litval));
+         movwf (AOP(result), 0);
+         break;
+       
+       case POINTER:
+       case GPOINTER:
+         emitPtrByteGet(result, p_type, FALSE);
+         if ((litval|mask) != 0x00ff)
+           emitpcode(POC_ANDLW, popGetLit (mask));
+         if (litval != 0x00)
+           emitpcode(POC_IORLW, popGetLit (litval));
+         emitPtrByteSet(result, p_type, TRUE);
+         break;
        
-       /* Bit length is greater than 7 bits. In this case, copy  */
-       /* all except the partial byte at the end                 */
-       for (rlen=blen;rlen>=8;rlen-=8)
-    {
-               emitPtrByteSet (rname, p_type,
-                       aopGet (AOP (right), offset++, FALSE, TRUE) );
-               if (rlen>8)
-                       pic14_emitcode ("inc", "%s", rname);
-    }
+       case CPOINTER:
+         assert( !"trying to assign to bitfield via pointer to __code space" );
+         break;
        
-       /* If there was a partial byte at the end */
-       if (rlen)
-    {
-               mask = (((unsigned char) -1 << rlen) & 0xff);
-               
-               if (AOP_TYPE (right) == AOP_LIT)
-        {
-               /* Case with partial byte and literal source
-                       */
-                       litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
-                       litval >>= (blen-rlen);
-                       litval &= (~mask) & 0xff;
-                       emitPtrByteGet (rname, p_type, FALSE);
-                       if ((mask|litval)!=0xff)
-                               pic14_emitcode ("anl","a,#0x%02x", mask);
-                       if (litval)
-                               pic14_emitcode ("orl","a,#0x%02x", litval);
-        }
-               else
-        {
-                       //bool pushedB;
-                       /* Case with partial byte and arbitrary source
-                       */
-                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
-                       pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
-                       
-                       //pushedB = pushB ();
-                       /* transfer A to B and get next byte */
-                       emitPtrByteGet (rname, p_type, TRUE);
-                       
-                       pic14_emitcode ("anl", "a,#0x%02x", mask);
-                       pic14_emitcode ("orl", "a,b");
-                       if (p_type == GPOINTER)
-                               pic14_emitcode ("pop", "b");
-                       
-                       //popB (pushedB);
-        }
-               emitPtrByteSet (rname, p_type, "a");
+       default:
+         assert( !"unhandled pointer type" );
+         break;
+       } // switch
+      } // if (blen > 1)
     }
+    else
+    {
+      /* right is no literal */
+      if (blen==1) {
+        switch (p_type)
+       {
+       case -1:
+         /* Note more efficient code, of pre clearing bit then only setting it if required,
+          * can only be done if it is known that the result is not a SFR */
+         emitpcode(POC_RRFW,popGet(AOP(right),0));
+         emitSKPC;
+         emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
+         emitSKPNC;
+         emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
+         break;
        
-}
+       case POINTER:
+       case GPOINTER:
+         emitPtrByteGet (result, p_type, FALSE);
+         emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
+         emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
+         emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
+         emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
+         emitPtrByteSet (result, p_type, TRUE);
+         break;
+       
+       case CPOINTER:
+         assert( !"trying to assign to bitfield via pointer to __code space" );
+         break;
+       
+       default:
+         assert( !"unhandled pointer type" );
+         break;
+       } // switch
+       return;
+      } else {
+       /* Case with a bitfield 1 < length <= 8 and arbitrary source */
+       pCodeOp *temp = popGetTempReg ();
 
-/*-----------------------------------------------------------------*/
-/* SetIrp - Set IRP bit                                            */
-/*-----------------------------------------------------------------*/
-void SetIrp(operand *result) {
-       FENTRY;
-       if (AOP_TYPE(result) == AOP_LIT) {
-               unsigned lit = (unsigned)operandLitValue(result);
-               emitpcode((lit&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
-       } else {
-               if (PCOP(AOP(result))->type == PO_LITERAL) {
-                       int addrs = PCOL(AOP(result))->lit;
-                       emitpcode((addrs&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
-               } else {
-                       emitpcode(POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT)); /* always ensure this is clear as it may have previouly been set */
-                       if(AOP_SIZE(result) > 1) {
-                               emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
-                               emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
-                       }
-               }
+       mov2w (AOP(right), 0);
+       if (blen < 8) {
+         emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
+       }
+       emitpcode(POC_MOVWF, temp);
+       if (bstr) {
+         AccLsh (temp, bstr);
        }
+       
+       switch (p_type)
+       {
+       case -1:
+         mov2w (AOP(result), 0);
+         emitpcode(POC_ANDLW, popGetLit (mask));
+         emitpcode(POC_IORFW, temp);
+         movwf (AOP(result), 0);
+         break;
+       
+       case POINTER:
+       case GPOINTER:
+         emitPtrByteGet (result, p_type, FALSE);
+         emitpcode(POC_ANDLW, popGetLit (mask));
+         emitpcode(POC_IORFW, temp);
+         emitPtrByteSet (result, p_type, TRUE);
+         break;
+       
+       case CPOINTER:
+         assert( !"trying to assign to bitfield via pointer to __code space" );
+         break;
+       
+       default:
+         assert( !"unhandled pointer type" );
+         break;
+       } // switch
+
+       popReleaseTempReg (temp);
+      } // if (blen > 1)
+    } // if (AOP(right)->type != AOP_LIT)
+    return;
+  } // if (blen <= 8 && ((blen + bstr) <= 8))
+
+  assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
+}
+
+unsigned long
+bitpatternFromVal (value *val)
+{
+  union {
+    float d;
+    unsigned long l;
+  } float_long;
+
+  assert (sizeof (float) == sizeof (long));
+
+  //fprintf (stderr, "%s:%u(%s): val=%lf, type: %d, etype: %d\n", __FILE__, __LINE__, __FUNCTION__, floatFromVal(val), SPEC_NOUN(val->type), SPEC_NOUN(val->etype));
+
+  switch (SPEC_NOUN(val->type))
+  {
+  case V_INT:
+  case V_CHAR:
+    return (unsigned long)floatFromVal (val);
+    
+  case V_FLOAT:
+  case V_DOUBLE:
+    float_long.d = floatFromVal (val);
+    return float_long.l;
+    
+  default:
+    assert( !"unhandled value type" );
+    break;
+  }
+
+  float_long.d = floatFromVal (val);
+  return float_long.l;
 }
 
 /*-----------------------------------------------------------------*/
@@ -9417,13 +9373,23 @@ static void genDataPointerSet(operand *right,
        iCode *ic)
 {
        int size, offset = 0 ;
+       int ressize;
        
        FENTRY;
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        aopOp(right,ic,FALSE);
        aopOp(result,ic,FALSE);
        
+       assert (IS_SYMOP(result));
+       assert (IS_PTR(OP_SYM_TYPE(result)));
+       
        size = AOP_SIZE(right);
+       ressize = getSize(OP_SYM_ETYPE(result));
+       if (size > ressize) size = ressize;
+       //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
+       
+       //assert( !"what's going on here?" );
+
        /*
        if ( AOP_TYPE(result) == AOP_PCODE) {
        fprintf(stderr,"genDataPointerSet   %s, %d\n",
@@ -9434,11 +9400,13 @@ static void genDataPointerSet(operand *right,
        
        // tsd, was l+1 - the underline `_' prefix was being stripped
        while (size--) {
-               emitpComment ("%s:%u: size=%i, offset=%i", __FILE__,__LINE__, size, offset);
+               emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
                
                if (AOP_TYPE(right) == AOP_LIT) {
-                       unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
+                       /* XXX: might be float... */
+                       unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
                        lit = lit >> (8*offset);
+                       //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
                        if(lit&0xff) {
                                emitpcode(POC_MOVLW, popGetLit(lit&0xff));
                                emitpcode(POC_MOVWF, popGet(AOP(result),offset));
@@ -9446,6 +9414,7 @@ static void genDataPointerSet(operand *right,
                                emitpcode(POC_CLRF, popGet(AOP(result),offset));
                        }
                } else {
+                       //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
                        emitpcode(POC_MOVFW, popGet(AOP(right),offset));
                        emitpcode(POC_MOVWF, popGet(AOP(result),offset));
                }
@@ -9475,7 +9444,7 @@ static void genNearPointerSet (operand *right,
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        aopOp(result,ic,FALSE);
        
-       
+#if 1
        /* if the result is rematerializable &
        in data space & not a bit variable */
        //if (AOP_TYPE(result) == AOP_IMMD &&
@@ -9487,6 +9456,7 @@ static void genNearPointerSet (operand *right,
                freeAsmop(result,NULL,ic,TRUE);
                return;
        }
+#endif
 
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        aopOp(right,ic,FALSE);
@@ -9496,26 +9466,20 @@ static void genNearPointerSet (operand *right,
        if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
                direct = 1;
        }
-
-       /* If the pointer value is not in a the FSR then need to put it in */
-       if (!AOP_INPREG(AOP(result)) && !direct) {
-               DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-               if (PCOP(AOP(result))->type == PO_LITERAL) 
-                       emitpcode(POC_MOVLW, popGet(AOP(result),0));
-               else
-                       emitpcode(POC_MOVFW, popGet(AOP(result),0));
-               emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
+       
+       if (IS_BITFIELD (letype))
+       {
+         genPackBits (letype, result, right, direct?-1:POINTER);
+         return;
        }
-
+       
+       /* If the pointer value is not in a the FSR then need to put it in */
        /* Must set/reset IRP bit for use with FSR. */
        /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
        if (!direct)
-               SetIrp(result);
+               setup_fsr (result);
 
-       /* if bitfield then unpack the bits */
-       if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
-               genPackBits ((IS_BITFIELD (retype) ? retype : letype), result, right, "indf", direct?-1:POINTER);
-       } else {
+       {
                /* we have can just get the values */
                int size = AOP_SIZE(right);
                int offset = 0 ;    
@@ -9571,6 +9535,7 @@ static void genNearPointerSet (operand *right,
        freeAsmop(result,NULL,ic,TRUE);
 }
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
 /*-----------------------------------------------------------------*/
@@ -9703,68 +9668,58 @@ static void genFarPointerSet (operand *right,
        
        freeAsmop(right,NULL,ic,TRUE);
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* genGenPointerSet - set value from generic pointer space         */
 /*-----------------------------------------------------------------*/
-static void genGenPointerSet (operand *right,
-                                                         operand *result, iCode *ic)
+static void genGenPointerSet (operand *right, operand *result, iCode *ic)
 {
-       sym_link *ptype = operandType(result);
-       sym_link *retype = getSpec(operandType(right));
-       sym_link *letype = getSpec (ptype);
+       sym_link *retype = getSpec(operandType(result));
        
        FENTRY;
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       
-       aopOp(result,ic,FALSE);
        aopOp(right,ic,FALSE);
+       aopOp(result,ic,FALSE);
+
        
-       DEBUGpic14_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) {
-                       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
-                       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
-               }
-               else {
-                       emitpcode(POC_MOVFW,popGet(AOP(result),0));
-                       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
+       DEBUGpic14_AopType(__LINE__,right,NULL,result);
 
-                       /* Must set/reset IRP bit for use with FSR. */
-                       /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
-                       SetIrp(result);
-               }
+       if (IS_BITFIELD(retype))
+       {
+         genPackBits (retype, result, right, GPOINTER);
+         return;
        }
 
-       /* if bitfield then unpack the bits */
-       if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
-               genPackBits ((IS_BITFIELD (retype) ? retype : letype),result, right, "indf", POINTER);
-       } else {
-               /* we have can just get the values */
-               int size = AOP_SIZE(right);
-               int offset = 0 ;    
-               
-               DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-               while (size--) {
-                       char *l = aopGet(AOP(right),offset,FALSE,TRUE);
-                       if (*l == '@' ) {
-                               emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
-                       } else {
-                               if (AOP_TYPE(right) == AOP_LIT) {
-                                       emitpcode(POC_MOVLW,popGet(AOP(right),offset));
-                               } else {
-                                       emitpcode(POC_MOVFW,popGet(AOP(right),offset));
-                               }
-                               emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
-                       }
-                       if (size)
-                               emitpcode(POC_INCF,popCopyReg(&pc_fsr));
-                       offset++;
-               }
+       {
+         /* emit call to __gptrput */
+         char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
+         int size = AOP_SIZE(right);
+         int idx = 0;
+
+         assert (size == getSize(OP_SYM_ETYPE(result)));
+         assert (size > 0 && size <= 4);
+
+         /* pass arguments */
+         /* - value (MSB in Gstack_base_addr-2, growing downwards) */
+         {
+           int off = size;
+           idx = 2;
+           while (off--)
+           {
+             mov2w_op (right, off);
+             emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
+           }
+           idx = 0;
+         }
+         /* - address */
+         assert (AOP_SIZE(result) == 3);
+         mov2w(AOP(result), 0);
+         emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
+         mov2w(AOP(result), 1);
+         emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
+         mov2w(AOP(result), 2);
+         call_libraryfunc (func[size]);
        }
        
        freeAsmop(right,NULL,ic,TRUE);
@@ -9819,10 +9774,10 @@ static void genPointerSet (iCode *ic)
        switch (p_type) {
                
        case POINTER:
-       case IPOINTER:
+       //case IPOINTER:
                genNearPointerSet (right,result,ic);
                break;
-               
+/*
        case PPOINTER:
                genPagedPointerSet (right,result,ic);
                break;
@@ -9830,7 +9785,7 @@ static void genPointerSet (iCode *ic)
        case FPOINTER:
                genFarPointerSet (right,result,ic);
                break;
-               
+*/
        case GPOINTER:
                genGenPointerSet (right,result,ic);
                break;
@@ -9866,18 +9821,24 @@ static void genIfx (iCode *ic, iCode *popIc)
        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);
-               DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
+       if (isbit)
+       {
+               assert (!"genIfx not implemented for bit variables...");
        }
-       else {
-               if (isbit && !IS_ITEMP(cond))
-                       genIfxJump(ic,OP_SYMBOL(cond)->rname);
-               else
-                       genIfxJump(ic,"a");
+       else
+       {
+               /* now Z if set iff !cond */
+               if (IC_TRUE(ic))
+               {
+                       assert (!IC_FALSE(ic));
+                       emitSKPZ;
+                       emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
+               } else {
+                       emitSKPNZ;
+                       emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
+               }
        }
+       
        ic->generated = 1;
        
 }
@@ -9924,6 +9885,10 @@ static void genAddrOf (iCode *ic)
        }
        
        size = AOP_SIZE(IC_RESULT(ic));
+       if (IS_GENPTR(OP_SYM_TYPE(result))) {
+               /* strip tag */
+               if (size > GPTRSIZE-1) size = GPTRSIZE-1;
+       }
        offset = 0;
        
        while (size--) {
@@ -9937,6 +9902,14 @@ static void genAddrOf (iCode *ic)
 #endif
                offset++;
        }
+
+       if (IS_GENPTR(OP_SYM_TYPE(result)))
+       {
+               /* provide correct tag */
+               int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
+               emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
+               movwf (AOP(result), 2);
+       }
        
        freeAsmop(left,NULL,ic,FALSE);
        freeAsmop(result,NULL,ic,TRUE);
@@ -10107,7 +10080,7 @@ static void genAssign (iCode *ic)
                                emitpcode(POC_INCF, popGet(AOP(result),0));
                        }
                } else {
-                       mov2w (AOP(right), offset);
+                       mov2w_op (right, offset);
                        emitpcode(POC_MOVWF, popGet(AOP(result),offset));
                }
                
@@ -10303,7 +10276,7 @@ release:
 static void genCast (iCode *ic)
 {
        operand *result = IC_RESULT(ic);
-       sym_link *ctype = operandType(IC_LEFT(ic));
+       sym_link *restype = operandType(result);
        sym_link *rtype = operandType(IC_RIGHT(ic));
        operand *right = IC_RIGHT(ic);
        int size, offset ;
@@ -10321,49 +10294,7 @@ static void genCast (iCode *ic)
        
        /* 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 */
-               DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
-               if (AOP_TYPE(right) == AOP_LIT) {
-                       
-                       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
-                               popGet(AOP(result),0));
-                       
-                       if (((int) operandLitValue(right))) 
-                               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
-                               AOP(result)->aopu.aop_dir,
-                               AOP(result)->aopu.aop_dir);
-                       else
-                               pic14_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;
-                       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
-                       
-                       pic14_emitcode("clrc","");
-                       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
-                               AOP(right)->aopu.aop_dir,
-                               AOP(right)->aopu.aop_dir);
-                       aopPut(AOP(result),"c",0);
-                       goto release ;
-               }
-               
-               /* we need to or */
-               if (AOP_TYPE(right) == AOP_REG) {
-                       emitpcode(POC_BCF,    popGet(AOP(result),0));
-                       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
-                       emitpcode(POC_BSF,    popGet(AOP(result),0));
-               }
-               pic14_toBoolean(right);
-               aopPut(AOP(result),"a",0);
-               goto release ;
+               assert(!"assigning to bit variables is not supported");
        }
        
        if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
@@ -10382,6 +10313,82 @@ static void genCast (iCode *ic)
                goto release;
        }
        
+       if (IS_PTR(restype))
+       {
+         operand *result = IC_RESULT(ic);
+         //operand *left = IC_LEFT(ic);
+         operand *right = IC_RIGHT(ic);
+         int tag = 0xff;
+         
+         /* copy common part */
+         int max, size = AOP_SIZE(result);
+         if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
+         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+         /* warn if we discard generic opinter tag */
+         if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
+         {
+           //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
+         } // if
+
+         max = size;
+         while (size--)
+         {
+           mov2w_op (right, size);
+           movwf (AOP(result), size);
+         } // while
+
+         /* upcast into generic pointer type? */
+         if (IS_GENPTR(restype)
+               && (size < AOP_SIZE(result))
+               && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
+         {
+           //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
+           if (IS_PTR(rtype))
+           {
+             switch (DCL_TYPE(rtype))
+             {
+             case POINTER:     /* __data */
+             case FPOINTER:    /* __data */
+               assert (AOP_SIZE(right) == 2);
+               tag = GPTRTAG_DATA;
+               break;
+
+             case CPOINTER:    /* __code */
+               assert (AOP_SIZE(right) == 2);
+               tag = GPTRTAG_CODE;
+               break;
+               
+             case GPOINTER:    /* unknown destination, __data or __code */
+               /* assume __data space (address of immediate) */
+               assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
+               if (AOP(right)->code)
+                 tag = GPTRTAG_CODE;
+               else
+                 tag = GPTRTAG_DATA;
+               break;
+               
+             default:
+               assert (!"unhandled pointer type");
+             } // switch
+           } else {
+             /* convert other values into pointers to __data space */
+             tag = GPTRTAG_DATA;
+           }
+
+           assert (AOP_SIZE(result) == 3);
+           if (tag == 0) {
+             emitpcode(POC_CLRF, popGet(AOP(result), 2));
+           } else {
+             emitpcode(POC_MOVLW, popGetLit(tag));
+             movwf(AOP(result), 2);
+           }
+         } else {
+           addSign(result, max, 0);
+         } // if
+         goto release;
+       }
+       
        /* if they are the same size : or less */
        if (AOP_SIZE(result) <= AOP_SIZE(right)) {
                
@@ -10422,112 +10429,15 @@ static void genCast (iCode *ic)
                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);
-               DEBUGpic14_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 */
-                       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
-                       size = GPTRSIZE - 1; 
-                       offset = 0 ;
-                       while (size--) {
-                               if(offset < AOP_SIZE(right)) {
-                                       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
-                                       if ((AOP_TYPE(right) == AOP_PCODE) && 
-                                               AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
-                                               emitpcode(POC_MOVLW, popGetAddr(AOP(right),offset,0));
-                                               emitpcode(POC_MOVWF, popGet(AOP(result),offset));
-                                       } else { 
-                                               aopPut(AOP(result),
-                                                       aopGet(AOP(right),offset,FALSE,FALSE),
-                                                       offset);
-                                       }
-                               } else 
-                                       emitpcode(POC_CLRF,popGet(AOP(result),offset));
-                               offset++;
-                       }
-                       /* the last byte depending on type */
-                       switch (p_type) {
-                       case IPOINTER:
-                       case POINTER:
-                               emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
-                               break;
-                       case FPOINTER:
-                               pic14_emitcode(";BUG!? ","%d",__LINE__);
-                               l = one;
-                               break;
-                       case CPOINTER:
-                               pic14_emitcode(";BUG!? ","%d",__LINE__);
-                               l = "#0x02";
-                               break;        
-                       case PPOINTER:
-                               pic14_emitcode(";BUG!? ","%d",__LINE__);
-                               l = "#0x03";
-                               break;
-                               
-                       default:
-                               /* this should never happen */
-                               werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-                                       "got unknown pointer type");
-                               exit(1);
-                       }
-                       //aopPut(AOP(result),l, GPTRSIZE - 1);      
-                       goto release ;
-               }
-               
-               /* just copy the pointers */
-               size = AOP_SIZE(result);
-               offset = 0 ;
-               while (size--) {
-                       aopPut(AOP(result),
-                               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))
+       if(0 && genMixedOperation(ic)) {
+               /* XXX: cannot optimize: must copy regs! */
                goto release;
-       
-       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
+       }
        
        /* we move to result for the size of source */
        size = AOP_SIZE(right);
@@ -10537,36 +10447,9 @@ static void genCast (iCode *ic)
                emitpcode(POC_MOVWF,   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--)
-                       emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
-       } else {
-               /* we need to extend the sign :{ */
-               
-               if(size == 1) {
-                       /* Save one instruction of casting char to int */
-                       emitpcode(POC_CLRF,   popGet(AOP(result),offset));
-                       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
-                       emitpcode(POC_DECF,   popGet(AOP(result),offset));
-               } else {
-                       emitpcodeNULLop(POC_CLRW);
-                       
-                       if(offset)
-                               emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
-                       else
-                               emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
-                       
-                       emitpcode(POC_MOVLW,   popGetLit(0xff));
-                       
-                       while (size--)
-                               emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
-               }
-       }
-       
+
+       addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
+
 release:
        freeAsmop(right,NULL,ic,TRUE);
        freeAsmop(result,NULL,ic,TRUE);
@@ -10955,14 +10838,17 @@ void genpic14Code (iCode *lic)
        return;
 }
 
+/* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
+ * (meaning: representing its own address) or not (referencing its contents).
+ * This can only be decided based on the operand's type. */
 int
 aop_isLitLike (asmop *aop)
 {
   assert (aop);
   if (aop->type == AOP_LIT) return 1;
-  if (aop->type == AOP_IMMD) return 1;
+if (aop->type == AOP_IMMD) return 1;
   if ((aop->type == AOP_PCODE) &&
-               ((aop->aopu.pcop->type == PO_LITERAL) || (aop->aopu.pcop->type == PO_IMMEDIATE)))
+               ((aop->aopu.pcop->type == PO_LITERAL)))
   {
     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
@@ -10976,5 +10862,7 @@ op_isLitLike (operand *op)
 {
   assert (op);
   if (aop_isLitLike (AOP(op))) return 1;
+  if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
+  if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
   return 0;
 }
index f12a1bdc7145de5694a7412538342663171bfdc0..d83a479c75dcfb110f18e17b5c2f77e36f329471 100644 (file)
@@ -145,9 +145,11 @@ extern unsigned fReturnSizePic;
 #define emitCLRZ    emitpcode(POC_BCF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_Z_BIT))
 #define emitCLRC    emitpcode(POC_BCF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_C_BIT))
 #define emitCLRDC   emitpcode(POC_BCF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_DC_BIT))
+#define emitCLRIRP  emitpcode(POC_BCF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT))
 #define emitSETZ    emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_Z_BIT))
 #define emitSETC    emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_C_BIT))
 #define emitSETDC   emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_DC_BIT))
+#define emitSETIRP  emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT))
 
 int pic14_getDataSize(operand *op);
 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop);
index 06134915313ded69da8bdc36971b03da75736965..78582d50197e4193f727bbd18dfc89354bcd94ea 100644 (file)
@@ -523,6 +523,8 @@ static void genAddLit (iCode *ic, int lit)
        result = IC_RESULT(ic);
        same = pic14_sameRegs(AOP(left), AOP(result));
        size = pic14_getDataSize(result);
+       if (size > pic14_getDataSize(left))
+               size = pic14_getDataSize(left);
        
        if(same) {
                
@@ -831,6 +833,11 @@ static void genAddLit (iCode *ic, int lit)
                        }
                }
        }
+
+       size = pic14_getDataSize(result);
+       if (size > pic14_getDataSize(left))
+               size = pic14_getDataSize(left);
+       addSign(result, size, 0);
 }
 
 /*-----------------------------------------------------------------*/
index 98811a1906abbbdcf482a40f126e3449fdc064c3..7868be5beb1eae3f0eb8e0b394eac8bf92936cf8 100644 (file)
@@ -28,6 +28,7 @@
 #include "pcode.h"
 #include "newalloc.h"
 #include "gen.h"
+#include "main.h"
 
 
 #ifdef WORDS_BIGENDIAN
@@ -100,6 +101,21 @@ int pic14aopLiteral (value *val, int offset)
        
 }
 
+/* Check whether the given reg is shared amongst all .o files of a project.
+ * This is true for the pseudo stack and WSAVE, SSAVE and PSAVE. */
+int is_shared_address (int addr)
+{
+  return ((addr > Gstack_base_addr - 18)
+       && (addr <= Gstack_base_addr));
+}
+
+int
+is_shared (regs *reg)
+{
+       if (!reg) return 0;
+       return is_shared_address (reg->address);
+}
+
 /* set of already emitted symbols; we store only pointers to the emitted
  * symbol names so these MUST NO BE CHANGED afterwards... */
 static set *symbolsEmitted = NULL;
@@ -109,9 +125,10 @@ static set *symbolsEmitted = NULL;
 /*                    already present                                */
 /*-------------------------------------------------------------------*/
 void
-emitSymbolToFile (FILE *of, const char *name, int size)
+emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
 {
        const char *sym;
+       static unsigned int sec_idx = 0;
        
        /* check whether the symbol is already defined */
        for (sym = (const char *) setFirstItem (symbolsEmitted);
@@ -127,7 +144,34 @@ emitSymbolToFile (FILE *of, const char *name, int size)
        
        /* new symbol -- define it */
        //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
-       fprintf (of, "%s\tres\t%d\n", name, size);
+       if (useEQU)
+         fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
+       else
+       {
+         /* we place each symbol into a section of its own to allow the linker
+          * to distribute the data into all available memory banks */
+         if (!section_type) section_type = "udata";
+         if (addr != -1)
+         {
+           /* workaround gpasm bug with symbols being EQUated and placed in absolute sections */
+           if (is_shared_address (addr))
+           {
+             if (globalize) fprintf (of, "\tglobal\t%s\n", name);
+             fprintf (of, "udata_%s_%u\t%s\t0x%04x\n", moduleName, sec_idx++, section_type, addr);
+             fprintf (of, "%s\tres\t%d\n", name, size);
+           }
+           else
+           {
+             /* EQUs cannot be exported... */
+             fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
+           }
+         } else {
+           if (globalize) fprintf (of, "\tglobal\t%s\n", name);
+           fprintf (of, "udata_%s_%u\t%s\n", moduleName, sec_idx++, section_type);
+           fprintf (of, "%s\tres\t%d\n", name, size);
+         }
+       }
+       
        addSet (&symbolsEmitted, (void *) name);
 }
 
@@ -218,7 +262,7 @@ pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
                        }
                        else
                        {
-                               emitSymbolToFile (map->oFile, sym->rname, getSize (sym->type) & 0xffff);
+                               emitSymbolToFile (map->oFile, sym->rname, NULL, getSize (sym->type) & 0xffff, -1, 0, 0);
                                /*
                                {
                                int i, size;
@@ -965,7 +1009,20 @@ picglue ()
        
        addSetHead(&tmpfileSet,ovrFile);
        pCodeInitRegisters();
-       
+
+       /* check for main() */
+       mainf = newSymbol ("main", 0);
+       mainf->block = 0;
+       mainf = findSymWithLevel (SymbolTab, mainf);
+
+       if (!mainf || !IFFUNC_HASBODY(mainf->type))
+       {
+               /* main missing -- import stack from main module */
+               //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
+               pic14_options.isLibrarySource = 1;
+       }
+
+#if 0
        if (mainf && IFFUNC_HASBODY(mainf->type)) {
                
                pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
@@ -988,7 +1045,7 @@ picglue ()
                        
                }
        }
-       
+#endif 
        
        /* 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 */
@@ -1144,14 +1201,15 @@ picglue ()
                fprintf (asmFile, "%s", iComments2);
                fprintf (asmFile, "; interrupt and initialization code\n");
                fprintf (asmFile, "%s", iComments2);
-               fprintf (asmFile, "code_init\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
+               fprintf (asmFile, "code_interrupt\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
                
                /* interrupt service routine */
-               fprintf (asmFile, "__sdcc_interrupt:\n");
+               fprintf (asmFile, "__sdcc_interrupt\n");
                copypCode(asmFile, 'I');
                
                /* initialize data memory */
-               fprintf (asmFile,"__sdcc_gsinit_startup:\n");
+               fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
+               fprintf (asmFile,"__sdcc_gsinit_startup\n");
                /* FIXME: This is temporary.  The idata section should be used.  If 
                not, we could add a special feature to the linker.  This will 
                work in the mean time.  Put all initalized data in main.c */
index d2244b3c29529e836c9df151946a37cfe5bfb097..976a2e4794e183548d0b3592a050b3dd7f535b68 100644 (file)
@@ -9,6 +9,8 @@
 #include "ralloc.h"
 #include "device.h"
 #include "SDCCutil.h"
+#include "SDCCmacro.h"
+#include "MySystem.h"
 #include "glue.h"
 //#include "gen.h"
 
@@ -47,6 +49,15 @@ static char *_pic14_keywords[] =
        NULL
 };
 
+pic14_options_t pic14_options;
+
+extern int debug_verbose;      /* from pcode.c */
+static OPTION _pic14_poptions[] = {
+       { 0 , "--debug-xtra", &debug_verbose, "show more debug info in assembly output" },
+       { 0 , "--no-pcode-opt", &pic14_options.disable_df, "disable (slightly faulty) optimization on pCode" },
+       { 0 , NULL, NULL, NULL }
+};
+
 void  pCodeInitRegisters(void);
 
 void pic14_assignRegisters (ebbIndex *);
@@ -62,6 +73,7 @@ _pic14_init (void)
 {
        asm_addTree (&asm_asxxxx_mapping);
        pCodeInitRegisters();
+       memset (&pic14_options, 0, sizeof (pic14_options));
 }
 
 static void
@@ -171,7 +183,7 @@ _pic14_parseOptions (int *pargc, char **argv, int *i)
                }
                return 1;
        }
-       
+
        return FALSE;
 }
 
@@ -307,7 +319,7 @@ sym_link *test = NULL;
 value *val;
        */
        
-       fprintf(stderr,"checking for native mult\n");
+       //fprintf(stderr,"checking for native mult\n");
        
        if ( ic->op != '*')
        {
@@ -394,6 +406,68 @@ static const char *_asmCmd[] =
                
 };
 
+extern set *libFilesSet;
+extern set *libDirsSet;
+extern set *libPathsSet;
+extern set *includeDirsSet;
+extern set *userIncDirsSet;
+extern set *dataDirsSetSet;
+extern set *relFilesSet;
+extern set *linkOptionsSet;
+
+static void _pic14_do_link ()
+{
+  hTab *linkValues=NULL;
+  char lfrm[256];
+  char *lcmd;
+  char temp[128];
+  set *tSet=NULL;
+  int ret;
+  
+  /*
+   * link command format:
+   * {linker} {incdirs} {lflags} -o {outfile} {spec_ofiles} {ofiles} {libs}
+   *
+   */
+
+  sprintf(lfrm, "{linker} {incdirs} {sysincdirs} {lflags} -o {outfile} {user_ofile} {spec_ofiles} {ofiles} {libs}");
+
+  shash_add(&linkValues, "linker", "gplink");
+
+  /* LIBRARY SEARCH DIRS */
+  mergeSets(&tSet, libPathsSet);
+  mergeSets(&tSet, libDirsSet);
+  shash_add(&linkValues, "incdirs", joinStrSet(appendStrSet(tSet, "-I\"", "\"")));
+
+  SNPRINTF (&temp[0], 128, "%cpic\"", DIR_SEPARATOR_CHAR);
+  joinStrSet(appendStrSet(libDirsSet, "-I\"", &temp[0]));
+  shash_add(&linkValues, "sysincdirs", joinStrSet(appendStrSet(libDirsSet, "-I\"", &temp[0])));
+  
+  shash_add(&linkValues, "lflags", joinStrSet(linkOptionsSet));
+
+  shash_add(&linkValues, "outfile", dstFileName);
+
+  if(fullSrcFileName) {
+    sprintf(temp, "%s.o", dstFileName);
+    shash_add(&linkValues, "user_ofile", temp);
+  }
+
+  shash_add(&linkValues, "ofiles", joinStrSet(relFilesSet));
+
+  /* LIBRARIES */
+  addSet(&libFilesSet, "libsdcc.lib");
+  shash_add(&linkValues, "libs", joinStrSet(libFilesSet));
+
+  lcmd = msprintf(linkValues, lfrm);
+
+  ret = my_system( lcmd );
+
+  Safe_free( lcmd );
+
+  if(ret)
+    exit(1);
+}
+
 /* Globals */
 PORT pic_port =
 {
@@ -421,7 +495,7 @@ PORT pic_port =
        {
                _linkCmd,
                NULL,
-               NULL,
+               _pic14_do_link,         /* own do link function */
                ".o",
                0
        },
@@ -430,7 +504,7 @@ PORT pic_port =
        },
        {
                /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
-               1, 2, 2, 4, 2, 2, 2, 1, 4, 4
+               1, 2, 2, 4, 2, 2, 3, 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)
@@ -481,7 +555,7 @@ PORT pic_port =
        "_",
        _pic14_init,
        _pic14_parseOptions,
-       NULL,
+       _pic14_poptions,
        NULL,
        _pic14_finaliseOptions,
        _pic14_setDefaultOptions,
index 65552254cc7bc707cfc07401e6f6bbb02e4e58d9..b70c7cb2f39b636d6b6c193f55be5003ec62235d 100644 (file)
@@ -1,6 +1,13 @@
 #ifndef MAIN_INCLUDE
 #define MAIN_INCLUDE
 
+typedef struct {
+  unsigned int isLibrarySource:1;
+  unsigned int disable_df;
+} pic14_options_t;
+
+extern pic14_options_t pic14_options;
+
 bool x_parseOptions (char **argv, int *pargc);
 void x_setDefaultOptions (void);
 void x_finaliseOptions (void);
index 40d2e50ee7cb5dfd994c233344670613302dbc71..e2a8452f3051280124499635dc14cff3c4ee9149 100644 (file)
@@ -71,11 +71,10 @@ static hTab *pic14MnemonicsHash = NULL;
 static hTab *pic14pCodePeepCommandsHash = NULL;
 
 
-static pFile *the_pFile = NULL;
+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 debug_verbose = 0;                /* Set true to inundate .asm file */
 
@@ -150,7 +149,7 @@ pCodeInstruction pciADDWF = {
                0,    // literal operand
                POC_NOP,
                (PCC_W | PCC_REGISTER),   // inCond
-               (PCC_REGISTER | PCC_Z) // outCond
+               (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
 };
 
 pCodeInstruction pciADDFW = {
@@ -172,7 +171,7 @@ pCodeInstruction pciADDFW = {
                0,    // literal operand
                POC_NOP,
                (PCC_W | PCC_REGISTER),   // inCond
-               (PCC_W | PCC_Z) // outCond
+               (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
 };
 
 pCodeInstruction pciADDLW = {
@@ -281,8 +280,8 @@ pCodeInstruction pciBCF = {
                0,0,  // branch, skip
                0,    // literal operand
                POC_BSF,
-               (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
-               PCC_REGISTER // outCond
+               (PCC_REGISTER | PCC_EXAMINE_PCOP),      // inCond
+               (PCC_REGISTER | PCC_EXAMINE_PCOP)       // outCond
 };
 
 pCodeInstruction pciBSF = {
@@ -303,8 +302,8 @@ pCodeInstruction pciBSF = {
                0,0,  // branch, skip
                0,    // literal operand
                POC_BCF,
-               (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
-               (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
+               (PCC_REGISTER | PCC_EXAMINE_PCOP),      // inCond
+               (PCC_REGISTER | PCC_EXAMINE_PCOP)       // outCond
 };
 
 pCodeInstruction pciBTFSC = {
@@ -325,8 +324,8 @@ pCodeInstruction pciBTFSC = {
                1,1,  // branch, skip
                0,    // literal operand
                POC_BTFSS,
-               (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
-               PCC_EXAMINE_PCOP // outCond
+               (PCC_REGISTER | PCC_EXAMINE_PCOP),      // inCond
+               PCC_NONE // outCond
 };
 
 pCodeInstruction pciBTFSS = {
@@ -348,7 +347,7 @@ pCodeInstruction pciBTFSS = {
                0,    // literal operand
                POC_BTFSC,
                (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
-               PCC_EXAMINE_PCOP // outCond
+               PCC_NONE // outCond
 };
 
 pCodeInstruction pciCALL = {
@@ -369,8 +368,8 @@ pCodeInstruction pciCALL = {
                1,0,  // branch, skip
                0,    // literal operand
                POC_NOP,
-               PCC_NONE, // inCond
-               PCC_NONE  // outCond
+               (PCC_NONE | PCC_W), // inCond, reads argument from WREG
+               (PCC_NONE | PCC_W | PCC_C | PCC_DC | PCC_Z)  // outCond, flags are destroyed by called function
 };
 
 pCodeInstruction pciCOMF = {
@@ -392,7 +391,7 @@ pCodeInstruction pciCOMF = {
                0,    // literal operand
                POC_NOP,
                PCC_REGISTER,  // inCond
-               PCC_REGISTER   // outCond
+               PCC_REGISTER | PCC_Z  // outCond
 };
 
 pCodeInstruction pciCOMFW = {
@@ -414,7 +413,7 @@ pCodeInstruction pciCOMFW = {
                0,    // literal operand
                POC_NOP,
                PCC_REGISTER,  // inCond
-               PCC_W   // outCond
+               PCC_W | PCC_Z  // outCond
 };
 
 pCodeInstruction pciCLRF = {
@@ -436,7 +435,7 @@ pCodeInstruction pciCLRF = {
                0,    // literal operand
                POC_NOP,
                PCC_NONE, // inCond
-               PCC_REGISTER  // outCond
+               PCC_REGISTER | PCC_Z // outCond
 };
 
 pCodeInstruction pciCLRW = {
@@ -458,7 +457,7 @@ pCodeInstruction pciCLRW = {
                0,    // literal operand
                POC_NOP,
                PCC_NONE, // inCond
-               PCC_W  // outCond
+               PCC_W | PCC_Z  // outCond
 };
 
 pCodeInstruction pciCLRWDT = {
@@ -502,7 +501,7 @@ pCodeInstruction pciDECF = {
                0,    // literal operand
                POC_NOP,
                PCC_REGISTER,   // inCond
-               PCC_REGISTER    // outCond
+               PCC_REGISTER | PCC_Z   // outCond
 };
 
 pCodeInstruction pciDECFW = {
@@ -524,7 +523,7 @@ pCodeInstruction pciDECFW = {
                0,    // literal operand
                POC_NOP,
                PCC_REGISTER,   // inCond
-               PCC_W    // outCond
+               PCC_W | PCC_Z   // outCond
 };
 
 pCodeInstruction pciDECFSZ = {
@@ -612,7 +611,7 @@ pCodeInstruction pciINCF = {
                0,    // literal operand
                POC_NOP,
                PCC_REGISTER,   // inCond
-               PCC_REGISTER    // outCond
+               PCC_REGISTER | PCC_Z   // outCond
 };
 
 pCodeInstruction pciINCFW = {
@@ -634,7 +633,7 @@ pCodeInstruction pciINCFW = {
                0,    // literal operand
                POC_NOP,
                PCC_REGISTER,   // inCond
-               PCC_W    // outCond
+               PCC_W | PCC_Z   // outCond
 };
 
 pCodeInstruction pciINCFSZ = {
@@ -874,7 +873,7 @@ pCodeInstruction pciRETFIE = {
                0,    // literal operand
                POC_NOP,
                PCC_NONE,   // inCond
-               PCC_NONE // outCond (not true... affects the GIE bit too)
+               (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond (not true... affects the GIE bit too), STATUS bit are retored
 };
 
 pCodeInstruction pciRETLW = {
@@ -896,7 +895,7 @@ pCodeInstruction pciRETLW = {
                1,    // literal operand
                POC_NOP,
                PCC_LITERAL,   // inCond
-               PCC_W // outCond
+               (PCC_W| PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETLW
 };
 
 pCodeInstruction pciRETURN = {
@@ -917,8 +916,8 @@ pCodeInstruction pciRETURN = {
                1,0,  // branch, skip
                0,    // literal operand
                POC_NOP,
-               PCC_NONE,   // inCond
-               PCC_NONE // outCond
+               PCC_NONE | PCC_W,   // inCond, return value is possibly present in W
+               (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETURN
 };
 
 pCodeInstruction pciRLF = {
@@ -940,7 +939,7 @@ pCodeInstruction pciRLF = {
                0,    // literal operand
                POC_NOP,
                (PCC_C | PCC_REGISTER),   // inCond
-               (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
+               (PCC_REGISTER | PCC_) // outCond
 };
 
 pCodeInstruction pciRLFW = {
@@ -962,7 +961,7 @@ pCodeInstruction pciRLFW = {
                0,    // literal operand
                POC_NOP,
                (PCC_C | PCC_REGISTER),   // inCond
-               (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
+               (PCC_W | PCC_C) // outCond
 };
 
 pCodeInstruction pciRRF = {
@@ -984,7 +983,7 @@ pCodeInstruction pciRRF = {
                0,    // literal operand
                POC_NOP,
                (PCC_C | PCC_REGISTER),   // inCond
-               (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
+               (PCC_REGISTER | PCC_C) // outCond
 };
 
 pCodeInstruction pciRRFW = {
@@ -1006,7 +1005,7 @@ pCodeInstruction pciRRFW = {
                0,    // literal operand
                POC_NOP,
                (PCC_C | PCC_REGISTER),   // inCond
-               (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
+               (PCC_W | PCC_C) // outCond
 };
 
 pCodeInstruction pciSUBWF = {
@@ -1028,7 +1027,7 @@ pCodeInstruction pciSUBWF = {
                0,    // literal operand
                POC_NOP,
                (PCC_W | PCC_REGISTER),   // inCond
-               (PCC_REGISTER | PCC_Z) // outCond
+               (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
 };
 
 pCodeInstruction pciSUBFW = {
@@ -1050,7 +1049,7 @@ pCodeInstruction pciSUBFW = {
                0,    // literal operand
                POC_NOP,
                (PCC_W | PCC_REGISTER),   // inCond
-               (PCC_W | PCC_Z) // outCond
+               (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
 };
 
 pCodeInstruction pciSUBLW = {
@@ -1137,8 +1136,8 @@ pCodeInstruction pciTRIS = {
                0,0,  // branch, skip
                0,    // literal operand
                POC_NOP,
-               PCC_NONE,   // inCond
-               PCC_REGISTER // outCond
+               PCC_NONE,   // inCond /* FIXME: what's TRIS doing? */
+               PCC_REGISTER // outCond /* FIXME: what's TIS doing */
 };
 
 pCodeInstruction pciXORWF = {
@@ -1204,7 +1203,7 @@ pCodeInstruction pciXORLW = {
                1,    // literal operand
                POC_NOP,
                (PCC_W | PCC_LITERAL),   // inCond
-               (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
+               (PCC_W | PCC_Z) // outCond
 };
 
 
@@ -1227,7 +1226,7 @@ pCodeInstruction pciBANKSEL = {
                0,    // literal operand
                POC_NOP,
                PCC_NONE, // inCond
-               PCC_REGISTER  // outCond
+               PCC_NONE  // outCond
 };
 
 pCodeInstruction pciPAGESEL = {
@@ -1249,7 +1248,7 @@ pCodeInstruction pciPAGESEL = {
                0,    // literal operand
                POC_NOP,
                PCC_NONE, // inCond
-               PCC_REGISTER  // outCond
+               PCC_NONE  // outCond
 };
 
 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
@@ -1724,16 +1723,17 @@ static int RegCond(pCodeOp *pcop)
                char *name = pcop->name;
                if (!name) 
                        name = PCOR(pcop)->r->name;
-               //      if (strcmp(name, pc_status.pcop.name) != 0) { <<< This breaks the peep 2 optimisation
-               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;
+               if (strcmp(name, pc_status.pcop.name) == 0)
+               {
+                       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;
@@ -2227,12 +2227,12 @@ pCodeOp *newpCodeOpLit(int lit)
        
        pcop->name = NULL;
        if(lit>=0) {
-               sprintf(s,"0x%02x",lit);
+               sprintf(s,"0x%02x", (unsigned char)lit);
                if(s)
                        pcop->name = Safe_strdup(s);
        }
        
-       ((pCodeOpLit *)pcop)->lit = lit;
+       ((pCodeOpLit *)pcop)->lit = (unsigned char)lit;
        
        return pcop;
 }
@@ -3012,7 +3012,7 @@ char *get_op(pCodeOp *pcop,char *buffer, size_t size)
                                } else
                                        SAFE_snprintf(&s,&size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
                        } else {
-                               if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4) {
+                               if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4) 
                                        SAFE_snprintf(&s,&size,"(%s + %d)",
                                                pcop->name,
                                                PCOI(pcop)->index);
@@ -3056,7 +3056,7 @@ char *get_op(pCodeOp *pcop,char *buffer, size_t size)
                                        SAFE_snprintf(&s,&size,"%s",pcop->name);
                        }
                        return buffer;
-                       
+
                case PO_GPR_BIT:
                        if(PCOR(pcop)->r) {
                                if(use_buffer) {
@@ -3078,9 +3078,8 @@ char *get_op(pCodeOp *pcop,char *buffer, size_t size)
                }
        }
 
-       printf("PIC port internal warning: (%s:%d) %s not found\n",
-         __FUNCTION__,
-         __LINE__,
+       printf("PIC port internal warning: (%s:%d(%s)) %s not found\n",
+         __FILE__, __LINE__, __FUNCTION__,
          pCodeOpType(pcop));
 
        return "NO operand";
@@ -3233,7 +3232,7 @@ static void genericPrint(FILE *of, pCode *pc)
       /* Debug */
       if(debug_verbose) {
         pCodeOpReg *pcor = PCOR(pci->pcop);
-        fprintf(of, "\t;id=%u,key=%03x",pc->id,pc->seq);
+        fprintf(of, "\t;id=%u,key=%03x,inCond:%x,outCond:%x",pc->id,pc->seq, pci->inCond, pci->outCond);
         if(pci->pcflow)
           fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
         if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
@@ -3285,6 +3284,23 @@ static void genericPrint(FILE *of, pCode *pc)
       if(PCFL(pc)->ancestor)
         fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
       fprintf(of,"\n");
+      fprintf(of,";  from: ");
+      {
+        pCodeFlowLink *link;
+        for (link = setFirstItem(PCFL(pc)->from); link; link = setNextItem (PCFL(pc)->from))
+       {
+         fprintf(of,"%03x ",link->pcflow->pc.seq);
+       }
+      }
+      fprintf(of,"; to: ");
+      {
+        pCodeFlowLink *link;
+        for (link = setFirstItem(PCFL(pc)->to); link; link = setNextItem (PCFL(pc)->to))
+       {
+         fprintf(of,"%03x ",link->pcflow->pc.seq);
+       }
+      }
+      fprintf(of,"\n");
     }
     break;
 
@@ -3801,34 +3817,33 @@ regs * getRegFromInstruction(pCode *pc)
                return NULL;
        
        switch(PCI(pc)->pcop->type) {
-       case PO_INDF:
+       case PO_STATUS:
        case PO_FSR:
-               return PCOR(PCI(pc)->pcop)->r;
-
+       case PO_INDF:
+       case PO_INTCON:
        case PO_BIT:
        case PO_GPR_TEMP:
+       case PO_SFR_REGISTER:
+       case PO_PCL:
+       case PO_PCLATH:
                return PCOR(PCI(pc)->pcop)->r;
-               
-       case PO_IMMEDIATE:
-               r = PCOI(PCI(pc)->pcop)->r;
-               if (r)
-                       return r;
-               return dirregWithName(PCI(pc)->pcop->name);
-               
+       
+       case PO_GPR_REGISTER:
        case PO_GPR_BIT:
+       case PO_DIR:
                r = PCOR(PCI(pc)->pcop)->r;
                if (r)
                        return r;
                return dirregWithName(PCI(pc)->pcop->name);
                
-       case PO_GPR_REGISTER:
-       case PO_DIR:
-               r = PCOR(PCI(pc)->pcop)->r;
+       case PO_LITERAL:
+               break;
+               
+       case PO_IMMEDIATE:
+               r = PCOI(PCI(pc)->pcop)->r;
                if (r)
                        return r;
                return dirregWithName(PCI(pc)->pcop->name);
-       case PO_LITERAL:
-               break;
                
        default:
                break;
@@ -3956,12 +3971,35 @@ void BuildFlow(pBlock *pb)
                //fprintf(stderr," build: ");
                //pflow->print(stderr,pflow);
                
-               if( PCI(pc)->isSkip) {
+               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.) */
+
+                       last_pci = findPrevInstruction (pc->prev);
+                       
+                       if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
+                               InsertpFlow(last_pci, &pflow);
+                       
+                       PCI(pc)->pcflow = PCFL(pflow);
+                       
+               }
+
+               if(isPCI_SKIP(pc)) {
                        
                /* The two instructions immediately following this one 
                        * mark the beginning of a new flow segment */
                        
-                       while(pc && PCI(pc)->isSkip) {
+                       while(pc && isPCI_SKIP(pc)) {
                                
                                PCI(pc)->pcflow = PCFL(pflow);
                                pc->seq = seq-1;
@@ -3980,31 +4018,13 @@ void BuildFlow(pBlock *pb)
                        pc->seq = 0;
                        InsertpFlow(pc, &pflow);
                        
-               } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next)))  {
+               } else if ( isPCI_BRANCH(pc) && !checkLabel(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(findPrevInstruction(pc->prev), &pflow);
-                       
-                       PCI(pc)->pcflow = PCFL(pflow);
-                       
                }
+               
                last_pci = pc;
                pc = pc->next;
        }
@@ -4264,7 +4284,8 @@ void LinkFlow(pBlock *pb)
                
                //FillFlow(PCFL(pcflow));
                
-               pc = PCFL(pcflow)->end;
+               /* find last instruction in flow */
+               pc = findPrevInstruction (PCFL(pcflow)->end);
                
                //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
                if(isPCI_SKIP(pc)) {
@@ -4282,7 +4303,7 @@ void LinkFlow(pBlock *pb)
                        
                        //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);
@@ -4298,7 +4319,8 @@ void LinkFlow(pBlock *pb)
                                __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
                        //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
                        
-                       continue;
+                       /* link CALLs to next instruction */
+                       if (PCI(pc)->op != POC_CALL) continue;
                }
                
                if(isPCI(pc)) {
@@ -4311,12 +4333,12 @@ void LinkFlow(pBlock *pb)
                }
                
                if(pc) {
-                       //fprintf(stderr, "ends with unknown\n");
-                       //pc->print(stderr,pc);
+                       fprintf(stderr, "ends with unknown\n");
+                       pc->print(stderr,pc);
                        continue;
                }
                
-               //fprintf(stderr, "ends with nothing: ERROR\n");
+               fprintf(stderr, "ends with nothing: ERROR\n");
                
        }
 }
@@ -4428,11 +4450,32 @@ static void BanksUsedFlow(pBlock *pb)
 }
 */
 
+void pCodeReplace (pCode *old, pCode *new)
+{
+       pCodeInsertAfter (old, new);
+
+       /* special handling for pCodeInstructions */
+       if (isPCI(new) && isPCI(old))
+       {
+               assert (!PCI(new)->from && !PCI(new)->to && !PCI(new)->label && /*!PCI(new)->pcflow && */!PCI(new)->cline);
+               PCI(new)->from = PCI(old)->from;
+               PCI(new)->to = PCI(old)->to;
+               PCI(new)->label = PCI(old)->label;
+               PCI(new)->pcflow = PCI(old)->pcflow;
+               PCI(new)->cline = PCI(old)->cline;
+       } // if
+
+       old->destruct (old);
+}
+
 /*-----------------------------------------------------------------*/
 /* Inserts a new pCodeInstruction before an existing one           */
 /*-----------------------------------------------------------------*/
 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
 {
+       pCode *pcprev;
+
+       pcprev = findPrevInstruction(pci->pc.prev);
        
        pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
        
@@ -4452,7 +4495,21 @@ static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_
        
        /* The new instruction has the same pcflow block */
        new_pci->pcflow = pci->pcflow;
-       
+
+       /* Arrrrg: is pci's previous instruction is a skip, we need to
+        * change that into a jump (over pci and the new instruction) ... */
+       if (pcprev && isPCI_SKIP(pcprev))
+       {
+               symbol *lbl = newiTempLabel (NULL);
+               pCode *label = newpCodeLabel (NULL, lbl->key);
+               pCode *jump = newpCode(POC_GOTO, newpCodeOpLabel(NULL, lbl->key));
+
+               pCodeInsertAfter (pcprev, jump);
+
+               pCodeReplace (pcprev, pCodeInstructionCopy (PCI(pcprev), 1));
+               pcprev = NULL;
+               pCodeInsertAfter((pCode*)pci, label);
+       }
 }
 
 /*-----------------------------------------------------------------*/
@@ -4491,7 +4548,7 @@ static void insertBankSel(pCodeInstruction  *pci, const char *name)
 /* Therefore banksel is only called for external registers or the  */
 /* first time a local register is encountered.                     */
 /*-----------------------------------------------------------------*/
-static int LastRegIdx; /* If the previous register is the same one again then no need to change bank. */
+static int LastRegIdx = -1; /* If the previous register is the same one again then no need to change bank. */
 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
 {
        int bank;
@@ -4669,11 +4726,12 @@ static int DoBankSelect(pCode *pc, int cur_bank) {
                        * not a skip type instruction */
                        pcprev = findPrevpCode(pc->prev, PC_OPCODE);
                        
-                       if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
+                       /* This approach does not honor the presence of labels at this instruction... */
+                       //if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
                                cur_bank = BankSelect(PCI(pc),cur_bank,reg);
-                       } else {
-                               cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
-                       }
+                       //} else {
+                       //      cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
+                       //}
                        if (!PCI(pc)->pcflow)
                                fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
                        else
@@ -4975,7 +5033,7 @@ int OptimizepBlock(pBlock *pb)
        pCode *pc, *pcprev;
        int matches =0;
        
-       if(!pb || !peepOptimizing)
+       if(!pb || options.nopeep)
                return 0;
        
        DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
@@ -5488,8 +5546,7 @@ void AnalyzeFlow(int level)
        
        OptimizepCode('*');
        
-       
-       /*
+       /*      
        for(pb = the_pFile->pbHead; pb; pb = pb->next)
        DumpFlow(pb);
        */
@@ -5527,11 +5584,13 @@ void AnalyzeFlow(int level)
 void AnalyzeBanking(void)
 {
        pBlock  *pb;
-       
+
        if(!picIsInitialized()) {
                setDefMaxRam(); // Max RAM has not been included, so use default setting
        }
        
+       if (!the_pFile) return;
+       
        /* Phase x - Flow Analysis - Used Banks
        *
        * In this phase, the individual flow blocks are examined
@@ -5652,6 +5711,7 @@ void ReuseReg(void)
 {
        pBlock  *pb;
        InitReuseReg();
+       if (!the_pFile) return;
        for(pb = the_pFile->pbHead; pb; pb = pb->next) {
                /* Non static functions can be called from other modules so their registers must reassign */
                if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
index 6c6c47205bbd4629a713997338cb6da3dfcf2482..bfa0c757ac57c828790bde7a96bfbbfd968c2590 100644 (file)
@@ -2100,9 +2100,10 @@ int pCodePeepMatchRule(pCode *pc)
                        /* 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 ) {
+                       while(pc && pc_cline ) {
                                
                                pc =  findNextInstruction(pc->next);
+                               if (!pc) break;
                                PCI(pc)->cline = pc_cline;
                                pc_cline = PCCS(pc_cline->pc.next);
                                
@@ -2111,13 +2112,14 @@ int pCodePeepMatchRule(pCode *pc)
                        /* Copy C code comments to new code. */
                        pc = pcprev->next;
                        if (pc) {
-                               for (; pcout!=pcin; pcout=pcout->next) {
+                               for (; pc && pcout!=pcin; pcout=pcout->next) {
                                        if (pcout->type==PC_OPCODE && PCI(pcout)->cline) {
                                                while (pc->type!=PC_OPCODE || PCI(pc)->cline) {
                                                        pc = pc->next;
                                                        if (!pc)
                                                                break;
                                                }
+                                               if (!pc) break;
                                                PCI(pc)->cline = PCI(pcout)->cline;
                                        }
                                }
index 2f489e3e63cb6a5a2fea1b6faae7abfe153de672..536a9405c096be3a61f112f8e4343a9929f810d3 100644 (file)
@@ -35,6 +35,7 @@ pcoderegs.c
 #include "pcode.h"
 #include "pcoderegs.h"
 #include "pcodeflow.h"
+#include "main.h"
 
 extern void dbg_dumpregusage(void);
 extern pCode * findPrevInstruction(pCode *pci);
@@ -43,6 +44,8 @@ void unlinkpCode(pCode *pc);
 extern int pCodeSearchCondition(pCode *pc, unsigned int cond, int contIfSkip);
 char *pCode2str(char *str, int size, pCode *pc);
 void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...);
+//static int sameRegs (const regs *reg1, const regs *reg2);
+
 int total_registers_saved=0;
 int register_optimization=1;
 
@@ -149,7 +152,6 @@ void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
 {
        
        pCode *pc=NULL;
-       pCode *pcprev=NULL;
        
        regs *reg;
        
@@ -173,7 +175,7 @@ void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
                        
                        addSetIfnotP(& (PCFL(pcfl)->registers), reg);
                        
-                       if((PCC_REGISTER | PCC_LITERAL) & PCI(pc)->inCond)
+                       if(PCC_REGISTER & PCI(pc)->inCond)
                                addSetIfnotP(& (reg->reglives.usedpFlows), pcfl);
                        
                        if(PCC_REGISTER & PCI(pc)->outCond)
@@ -183,7 +185,6 @@ void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
                }
                
                
-               pcprev = pc;
                pc = findNextInstruction(pc->next);
                
        }
@@ -235,7 +236,7 @@ void pCodeRegMapLiveRanges(pBlock *pb)
 *-----------------------------------------------------------------*/
 static void Remove1pcode(pCode *pc, regs *reg, int debug_code)
 {
-       
+
        pCode *pcn=NULL;
        
        if(!reg || !pc)
@@ -444,6 +445,23 @@ int regIsSpecial (regs *reg, int mayBeGlobal)
   return 0;
 }
 
+#if 0
+static int regIsLocal (regs *reg)
+{
+       if (!reg) return 1;
+       /* temporaries are local */
+       if (reg->type == REG_TMP) return 1;
+       /* registers named r0x... are local */
+       if (reg->name && !strncmp(reg->name,"r0x", 3))
+       {
+               //fprintf (stderr, "reg %s is not marked REG_TMP...\n", reg->name);
+               return 1;
+       }
+
+       return 0;
+}
+#endif
+
 /*-----------------------------------------------------------------*
 * void pCodeOptime2pCodes(pCode *pc1, pCode *pc2) 
 *
@@ -461,17 +479,23 @@ int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int
        regs  *reg1, *reg2;
        
        int t = total_registers_saved;
+
+       if (!isPCI(pc1) || !isPCI(pc2)) return 0;
+       if (PCI(pc1)->pcflow != PCI(pc2)->pcflow) return 0;
        
        if(pc2->seq < pc1->seq) {
                pct1 = pc2;
                pc2 = pc1;
                pc1 = pct1;
        }
+
+       /* disable this optimization for now -- it's buggy */
+       if(pic14_options.disable_df) return 0;
        
        //fprintf(stderr,"pCodeOptime2pCodes\n");
        //pc1->print(stderr,pc1);
        //pc2->print(stderr,pc2);
-       
+
        if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){
                pCode *newpc;
                int regUsed = 0;
@@ -493,10 +517,10 @@ int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int
                if(pct2 && PCI(pct2)->op == POC_MOVWF) {
                        wSaved = wUsed = 1; /* Maybe able to replace with clrf pc2->next->reg. */
                } else {
-                       wUsed = pCodeSearchCondition(pct2,PCC_W,1) > 0;
+                       wUsed = pCodeSearchCondition(pct2,PCC_W,1) != -1;
                }
                regUsed = regUsedinRange(pct2,0,reg);
-               if ((regUsed&&wUsed) || (pCodeSearchCondition(pct2,PCC_Z,0) 1)) {
+               if ((regUsed&&wUsed) || (pCodeSearchCondition(pct2,PCC_Z,0) != -1)) {
                        /* Do not optimise as exisiting code is required. */
                } else {
                        /* Can optimise. */
@@ -522,7 +546,8 @@ int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int
                
                pct2 = findNextInstruction(pc2->next);
                
-               if(pCodeSearchCondition(pct2, PCC_Z,0) > 0) {
+               /* We must ensure that is destroyed before being read---IORLW must be performed unless this is proven. */
+               if(pCodeSearchCondition(pct2, PCC_Z,0) != -1) {
                        pct2 = newpCode(POC_IORLW, newpCodeOpLit(0));
                        pct2->seq = pc2->seq;
                        PCI(pct2)->pcflow = PCFL(pcfl_used);
@@ -560,7 +585,9 @@ int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int
                                if (reg2 && !regIsSpecial (reg2, 1) && !regUsedinRange(pc1,pc2,reg2)) {
                                        pCode *pct3 = findNextInstruction(pct2->next);
                                        /* Check following instructions are not relying on the use of W or the Z flag condiction */
-                                       if ((pCodeSearchCondition(pct3,PCC_Z,0) < 1) || (pCodeSearchCondition(pct3,PCC_W,0) < 1)) {
+                                       /* XXX: We must ensure that this value is destroyed before use---otherwise it might be used in
+                                        *      subsequent flows (checking for < 1 is insufficient). */
+                                       if ((pCodeSearchCondition(pct3,PCC_Z,0) == -1) && (pCodeSearchCondition(pct3,PCC_W,0) == -1)) {
                                                DFPRINTF((stderr, "   optimising MOVF reg ... MOVF reg,W MOVWF reg2 to MOVWF reg2 ...\n"));
                                                pct2->seq = pc1->seq;
                                                unlinkpCode(pct2);
@@ -788,6 +815,811 @@ void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level)
        }
 }
 
+#if 0
+
+/* The following routines implement pCode optimizations based on
+ * dataflow analysis. The effects should be similar to those
+ * of pCodeOptime2pCodes() but more powerful.
+ *
+ * Unfortunately, the current approach (comparing operands by
+ * their associated registers) is seriously flawed:
+ * Some pCodeOps do not provide access to their repsective regs
+ * (PO_DIRs are created from arbitrary strings, immediates need
+ * to take offset and index into account, ...)
+ *
+ * This has to be rewritten based on pCodeOps instead of regs...
+ */
+
+/* ------------------------------------------------------------------
+   Returns TRUE iff reg1 and reg2 are the same registers.
+   ------------------------------------------------------------------ */
+
+static int sameRegs (const regs *reg1, const regs *reg2)
+{
+       if (reg1 == reg2) return 1;
+       if (!reg1 || !reg2) return 0;
+       assert (reg1->name && reg2->name);
+
+       /* Compare names, as rIdx is not unique... */
+       if (!strcmp(reg1->name, reg2->name)) return 1;
+
+       /* Name mismatch -- not the same register. */
+       return 0;
+}
+
+/* ------------------------------------------------------------------
+   Returns 1 if the register is live at pc (read in this flow),
+   returns -1 if the register is NOT live at pc (assigned a new value
+   prior to readingi the old value in this flow) or
+   return 0 if the register is not mentioned.
+   ------------------------------------------------------------------ */
+
+static int checkRegInFlow (regs **reg, int *cond, pCode *pc)
+{
+       const int verbose = 0;
+       /* find next PCI at or after pc */
+       while (pc && isPCFL(pc)) pc = pc->next;
+
+       assert (reg && cond);
+
+       /* remove pseudo flags from cond */
+       *cond &= ~(PCC_REGISTER | PCC_EXAMINE_PCOP);
+
+       if (verbose && pc)
+       {
+               fprintf (stderr, "Checking for reg %s, cond %x on pc ", *reg ? (*reg)->name : "<none>", *cond); pc->print (stderr, pc);
+       }
+       
+       while (pc && !isPCFL(pc))
+       {
+               if (verbose)
+               {
+                       fprintf (stderr, "        now checking for reg %s, cond %x on pc ", *reg ? (*reg)->name : "<none>", *cond);
+                       pc->print (stderr, pc);
+               }
+               if (isPCI(pc))
+               {
+                       pCode *pcprev;
+                       regs *op = NULL;
+                       int prevIsSkip = 0;
+                       
+                       pcprev = findPrevInstruction (pc);
+                       if (pcprev && isPCI_SKIP(pcprev))
+                               prevIsSkip = 1;
+
+                       if ((PCI(pc)->inCond | PCI(pc)->outCond) & PCC_REGISTER)
+                       {
+                               op = getRegFromInstruction (pc);
+
+                               /* pCodeOpRegBits do not provide register information... */
+                               //if (!op) { __asm__("int3"); pc->print (stderr, pc); }
+                               //assert (op);
+                               if (!op) 
+                               {
+                                       if (reg)
+                                               return 1; /* assume `reg' is alive */
+                               }
+
+                               /* SPECIAL CASE: jump to unknown destination -- assume everything alive */
+                               if (op->type == PO_PCL)
+                               {
+                                       return 1;
+                               }
+                       } // if
+
+                       if (PCI(pc)->inCond & PCC_REGISTER)
+                       {
+                               /* `op' is live (possibly read) */
+                               if (*reg && sameRegs (op, *reg))
+                               {
+                                       if (verbose)
+                                       {
+                                               fprintf (stderr, "reg is read in pc ");
+                                               pc->print (stderr, pc);
+                                       }
+                                       return 1;
+                               }
+                       }
+
+                       /* handle additional implicit operands */
+                       switch (PCI(pc)->op)
+                       {
+                       case POC_CALL: /* read arguments from WREG, clobbers WREG */
+                               if (*cond & PCC_W)
+                               {
+                                       if (verbose)
+                                       {
+                                               fprintf (stderr, "conditions are read at pc ");
+                                               pc->print (stderr, pc);
+                                       }
+                                       return 1;
+                               }
+                               *cond &= ~PCC_W;
+                               break;
+                       case POC_RETURN: /* returns WREG to caller */
+                               //fprintf (stderr, "reached RETURN, reg %s, cond %x\n", *reg ? (*reg)->name : "<none>", *cond);
+                               if (*cond & PCC_W)
+                               {
+                                       if (verbose)
+                                       {
+                                               fprintf (stderr, "conditions are read at pc ");
+                                               pc->print (stderr, pc);
+                                       }
+                                       return 1;
+                               }
+                               /* afterwards, no condition is alive */
+                               *cond = 0;
+                               /* afterwards, all local registers are dead */
+                               if (*reg && regIsLocal (*reg)) *reg = NULL;
+                               break;
+                       case POC_RETLW:
+                       case POC_RETFIE: /* this does not erturn WREG to the "caller", thus its rather a RETLW */
+                               /* this discards WREG */
+                               *cond &= ~PCC_W;
+                               /* afterwards, no condition is alive */
+                               *cond = 0;
+                               /* afterwards, all local registers are dead */
+                               if (*reg && regIsLocal (*reg)) *reg = NULL;
+                               break;
+                       default:
+                               /* no implicit arguments */
+                               break;
+                       }
+
+                       if (PCI(pc)->inCond & (*cond))
+                       {
+                               /* a condition is read */
+                               if (verbose)
+                               {
+                                       fprintf (stderr, "conditions are read at pc ");
+                                       pc->print (stderr, pc);
+                               }
+                               return 1;
+                       }
+
+                       /* remove outConds from `cond' */
+                       (*cond) &= ~(PCI(pc)->outCond);
+
+                       if (PCI(pc)->outCond & PCC_REGISTER)
+                       {
+                               /* `op' is (possibly) discarded */
+                               if (*reg && !prevIsSkip && sameRegs (op, *reg))
+                               {
+                                       if (verbose)
+                                       {
+                                               fprintf (stderr, "reg is assigned (cont'd) at pc ");
+                                               pc->print (stderr, pc);
+                                       }
+                                       *reg = NULL;
+                               }
+                       }
+
+                       /* have all interesting conditions/registers been discarded? */
+                       if (!(*reg) && !(*cond))
+                       {
+                               if (verbose)
+                               {
+                                       fprintf (stderr, "reg and conditions are discarded after ");
+                                       pc->print (stderr, pc);
+                               }
+                               return -1;
+                       }
+               } // if
+
+               pc = pc->next;
+       } // while
+
+       /* no use of (or only conditional writes to) `reg' found in flow */
+       if (verbose)
+       {
+               fprintf (stderr, "analysis inconclusive: reg %s, cond %x remains\n", *reg ? "remains" : "is void", *cond);
+       }
+       return 0;
+}
+
+/* ------------------------------------------------------------------
+   This will return 1 only if
+   - reg is NULL or of type REG_TMP
+   - reg is NULL or its value is discarded after pc
+   - cond is 0 or all conditions are overwritten before being used
+   ------------------------------------------------------------------ */
+
+typedef struct {
+  pCode *pc;
+  regs *reg;
+  int cond;
+} df_state_t;
+
+df_state_t *df_free_states = NULL;
+
+static df_state_t *
+df_newState (regs *reg, int cond, pCode *pc)
+{
+       df_state_t *state;
+
+       if (df_free_states) {
+         state = df_free_states;
+         df_free_states = (df_state_t *)df_free_states->pc;
+       } else {
+         state = Safe_calloc(1, sizeof(df_state_t));
+       }
+       state->pc = pc;
+       state->reg = reg;
+       state->cond = cond;
+       return state;
+}
+
+static int
+df_containsState (set *set, df_state_t *state)
+{
+       /* scan set for presence of `state' */
+       df_state_t *curr;
+       for (curr = setFirstItem (set); curr; curr = setNextItem (set))
+       {
+               if ((curr->pc == state->pc)
+                       && (curr->reg == state->reg)
+                       && (curr->cond == state->cond))
+               {
+                       /* `state' found */
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static void
+df_releaseState (df_state_t *state)
+{
+       state->pc = (pCode *)df_free_states;
+       df_free_states = (df_state_t *)state;
+       state->reg = NULL;
+       state->cond = 0;
+}
+
+static void
+df_removeStates ()
+{
+       df_state_t *next;
+       while (df_free_states)
+       {
+               next = (df_state_t *)df_free_states->pc;
+               Safe_free(df_free_states);
+               df_free_states = next;
+       } // while
+}
+
+int regIsDead (regs *reg, int cond, pCode *pc)
+{
+       set *seenStates = NULL;
+       set *todo = NULL;
+       pCode *curr;
+       df_state_t *state;
+       int result = 1;
+       
+       /* sanity checks */
+       if (reg && !regIsLocal (reg)) return 0;
+
+       pc = findNextInstruction (pc->next);
+
+       addSet (&todo, df_newState(reg, cond, pc));
+
+       while ((result == 1) && (state = getSet (&todo)))
+       {
+               int res;
+               
+               if (df_containsState (seenStates, state)) continue;
+               addSet (&seenStates, state);
+
+               curr = state->pc;
+               reg = state->reg;
+               cond = state->cond;
+               
+               //fprintf (stderr, "Checking for reg %s/cond %x at pc ", reg ? reg->name : "<none>", cond);
+               //curr->print (stderr, curr);
+
+               res = checkRegInFlow (&reg, &cond, curr);
+               switch (res)
+               {
+               case 1: /* `reg' or `cond' is read---not dead */
+                       result = 0;
+                       break;
+               case -1: /* `reg' and `cond' are discarded in this flow---need to check other open flows */
+                       break;
+               default: /* `reg' is not read and (possibly) not assigned---check successor flows */
+                       if (curr)
+                       {
+                               pCodeFlow *pcfl = PCI(curr)->pcflow;
+                               pCodeFlowLink *link;
+                               pCode *first;
+                               assert (pcfl);
+
+                               for (link = setFirstItem(pcfl->to); link; link = setNextItem (pcfl->to))
+                               {
+                                       /* add the first pCodeInstruction in the new flow to `todo' */
+                                       first = findNextInstruction (&link->pcflow->pc);
+                                       if (first) addSet (&todo, df_newState (reg, cond, first));
+                               } // for
+                       }
+                       break;
+               } // switch
+       } // while
+
+       /* clean up */
+       while (NULL != (state = getSet (&todo))) { df_releaseState (state); }
+       while (NULL != (state = getSet (&seenStates))) { df_releaseState (state); }
+
+       /* if result remained 1, `reg' is not even possibly read and thus dead */
+       return result;
+}
+
+
+
+/* ------------------------------------------------------------------
+   Safely remove a pCode.
+   This needs to check that the previous instruction was no SKIP
+   (otherwise the SKIP instruction would have to be removed as well,
+   which may not be done for SFRs (side-effects on read possible)).
+   ------------------------------------------------------------------ */
+
+extern void unBuildFlow (pBlock *pb);
+extern void RegsUnMapLiveRanges ();
+extern void BuildFlow (pBlock *pb);
+extern void LinkFlow (pBlock *pb);
+extern void BuildFlowTree (pBlock *pb);
+extern void pCodeRegMapLiveRanges (pBlock *pb);
+extern pFile *the_pFile;
+
+static int pCodeRemove (pCode *pc, const char *comment)
+{
+       pCode *pcprev, *pcnext;
+       unsigned int result = 0;
+       
+       /* Sanity checks. */
+       if (!pc) return 0;
+       if (!isPCI(pc)) return 0;
+
+       pcprev = findPrevInstruction (pc->prev);
+       if (pcprev && isPCI_SKIP(pcprev))
+       {
+               /* bail out until we know how to fix the Flow... */
+               //return 0;
+
+               /* we also need to remove the preceeding SKIP instruction(s) */
+               result = pCodeRemove (pcprev, "=DF= removing preceeding SKIP as well");
+               if (!result)
+               {
+                       /* previous instruction could not be removed -- this cannot be removed as well */
+                       return result;
+               }
+               /* FIXME: We now have to update the flow! */
+       } // if
+
+       /* do not remove pCodes with SFRs as operands (even reading them might cause side effects) */
+       {
+               regs *reg;
+               reg = getRegFromInstruction (pc);
+               /* accesses to the STATUS register aer always safe, but others... */
+               if (reg && reg->type == REG_SFR && reg->pc_type != PO_STATUS) return result;
+       }
+
+       /* MUST SUCEED FROM NOW ON (or ervert the changes done since NOW ;-)) */
+       
+       /* fix flow */
+       if (PCI(pc)->pcflow && PCI(pc)->pcflow->end == pc)
+       {
+               pCode *pcprev;
+               pcprev = findPrevInstruction (pc->prev);
+               if (PCI(pcprev)->pcflow == PCI(pc)->pcflow)
+               {
+                       PCI(pc)->pcflow->end = pcprev;
+               } else {
+                       pBlock *pb = pc->pb;
+                       RegsUnMapLiveRanges();
+                       unBuildFlow(pb);
+                       BuildFlow(pb);
+                       LinkFlow(pb);
+                       BuildFlowTree(pb);
+                       for (pb = the_pFile->pbHead; pb; pb = pb->next)
+                       {
+                               pCodeRegMapLiveRanges(pb);
+                       }
+               }
+       }
+       
+       /* attach labels to next instruction */
+       pcnext = findNextInstruction (pc->next);
+       if (pcnext)
+       {
+               PCI(pcnext)->label = pBranchAppend (PCI(pcnext)->label, PCI(pc)->label);
+               if (!PCI(pcnext)->cline) PCI(pcnext)->cline = PCI(pc)->cline;
+       }
+       else
+       {
+               fprintf (stderr, "Cannot move a label...\n");
+               exit(-1);
+       }
+       
+       if (comment)
+       {
+               char buffer[512];
+               int size = 512;
+               char *pbuff = &buffer[0];
+               
+               SAFE_snprintf (&pbuff, &size, "; %s:%u(%s): %s", __FILE__, __LINE__, __FUNCTION__, comment);
+               pCodeInsertAfter(pc->prev, newpCodeCharP (&buffer[0]));
+       } // if
+
+       if (1)
+       {
+               /* replace removed pCode with out-commented version of itself */
+               char buffer[512];
+               int size = 512;
+               char *pbuff = &buffer[0];
+               
+               SAFE_snprintf (&pbuff, &size, "; %s:%u(%s): ", __FILE__, __LINE__, __FUNCTION__);
+               pCode2str (pbuff, size, pc);
+               pCodeInsertAfter(pc->prev, newpCodeCharP (&buffer[0]));
+       }
+
+       pc->destruct (pc);
+       return result+1;
+}
+
+/* ------------------------------------------------------------------
+   Find and remove dead pCodes.
+   ------------------------------------------------------------------ */
+
+static int removeIfDeadPCI (pCode *pc)
+{
+       pCode *pcnext = NULL;
+       pCode *curr;
+       unsigned int outCond;
+       unsigned int result = 0;
+       regs *dst;
+       
+       if (!pc) return 0;
+       dst = NULL;
+       
+       /* skip non-PCIs */
+       pcnext = findNextInstruction (pc->next);
+       if (!isPCI(pc)) return 0;
+
+       switch (PCI(pc)->op)
+       {
+       case POC_ADDLW:
+       case POC_ADDWF:
+       case POC_ADDFW:
+       case POC_ANDLW:
+       case POC_ANDWF:
+       case POC_ANDFW:
+       case POC_BCF:
+       case POC_BSF:
+       //case POC_BTFSC:
+       //case POC_BTFSS:
+       //case POC_CALL:
+       case POC_COMF:
+       case POC_COMFW:
+       case POC_CLRF:
+       case POC_CLRW:
+       //case POC_CLRWDT:
+       case POC_DECF:
+       case POC_DECFW:
+       //case POC_DECFSZ:
+       //case POC_DECFSZW:
+       //case POC_GOTO:
+       case POC_INCF:
+       case POC_INCFW:
+       //case POC_INCFSZ:
+       //case POC_INCFSZW:
+       case POC_IORLW:
+       case POC_IORWF:
+       case POC_IORFW:
+       case POC_MOVF:
+       case POC_MOVFW:
+       case POC_MOVLW:
+       case POC_MOVWF:
+       case POC_NOP:
+       //case POC_RETLW:
+       //case POC_RETURN:
+       //case POC_RETFIE:
+       case POC_RLF:
+       case POC_RLFW:
+       case POC_RRF:
+       case POC_RRFW:
+       case POC_SUBLW:
+       case POC_SUBWF:
+       case POC_SUBFW:
+       case POC_SWAPF:
+       case POC_SWAPFW:
+       //case POC_TRIS:
+       case POC_XORLW:
+       case POC_XORWF:
+       case POC_XORFW:
+       //case POC_BANKSEL:
+       //case POC_PAGESEL:
+               break;
+       
+       default:
+               /* do not remove unknown PCIs */
+               return 0;
+       } // switch
+
+       /* redundant checks---those instructions may never be removed */
+       if (isPCI_BRANCH(pc)) return 0;
+       if (isPCI_SKIP(pc)) return 0;
+       
+       outCond = PCI(pc)->outCond;
+       curr = pcnext;
+
+       /* unknown operands assigned to, then ignore */
+       if ((outCond & (PCC_REGISTER | PCC_C | PCC_Z | PCC_DC | PCC_W)) != outCond)
+               return 0;
+       
+       if (outCond & PCC_REGISTER)
+       {
+               dst = getRegFromInstruction (pc);
+               if (!dst) return 0;
+
+               /* special reg? */
+               if (!regIsLocal (dst)) return 0;
+               if (regIsSpecial (dst,0)) return 0;
+       }
+       
+       //fprintf (stderr, "--> checking for liveness pc "); pc->print (stderr, pc);
+       if (regIsDead (dst, outCond, pc))
+       {
+               /* no result from pc has been used -- pc is `dead' */
+               //fprintf (stderr, "--> reg %s and cond %x assumed unused\n", dst ? dst->name : "<none>", outCond);
+               //fprintf (stderr, "--> removing dead pc "); pc->print (stderr, pc);
+               result = pCodeRemove (pc, "=DF= removed dead pCode");
+       }
+       
+       return result;
+}
+
+/* ------------------------------------------------------------------
+   This routine is intended to safely replace one pCodeInstruction
+   with a different pCodeInstruction.
+   If desired, the replaced pCode will be left in (commented out) for
+   debugging.
+   Further, an optional comment can be inserted to indicate the
+   reason for the possible removal of the pCode.
+   ------------------------------------------------------------------ */
+
+static void replace_PCI (pCodeInstruction *pc, pCodeInstruction *newpc, char *comment)
+{
+  newpc->from =  pBranchAppend (newpc->from, pc->from);
+  newpc->to = pBranchAppend (newpc->to, pc->to);
+  newpc->label = pBranchAppend (newpc->label, pc->label);
+  //newpc->pcflow = pc->pcflow; // updated in pCodeInsertAfter, ->pb is as well
+  newpc->cline = pc->cline;
+
+  newpc->pc.seq = pc->pc.seq;
+
+  pCodeInsertAfter (&pc->pc, &newpc->pc);
+
+  /* FIXME: replacing pc will break the liverange maps (usedpCodes, ...) */
+  
+  if (comment)
+  {
+    pCodeInsertAfter (&pc->pc, newpCodeCharP (comment));
+  } // if
+
+  if (1)
+  {
+    /* replace pc with commented out version of itself */
+    char buffer[1024], buffer2[1024];
+    char *pbuff = &buffer[0];
+    int size=1024;
+    pCode2str (&buffer2[0],1024,&pc->pc);
+    SAFE_snprintf (&pbuff,&size,"%s:%u(%s): removed pCode was %s\t", __FILE__, __LINE__, __FUNCTION__, &buffer2[0]);
+    pCodeInsertAfter (&pc->pc, newpCodeCharP (&buffer[0]));
+  } // if
+
+  pc->pc.destruct (&pc->pc);
+}
+
+/* ------------------------------------------------------------------
+   Find the first (unique) assignment to `reg' (prior to pc).
+   ------------------------------------------------------------------ */
+
+pCode *findAssignmentToReg (regs *reg, pCode *pc)
+{
+       pCode *curr;
+       
+       assert (pc && isPCI(pc) && reg);
+
+       curr = findPrevInstruction (pc->prev);
+       
+       while (curr && PCI(curr)->pcflow == PCI(pc)->pcflow)
+       {
+               if (PCI(curr)->outCond & PCC_REGISTER)
+               {
+                       regs *op = getRegFromInstruction (curr);
+                       if (op && (sameRegs(op,reg)))
+                               return curr;
+               } // if
+               curr = findPrevInstruction (curr->prev);
+       } // while
+       
+       /* no assignment to reg found */
+       return NULL;
+}
+
+/* ------------------------------------------------------------------
+   Find a register that holds the same value as `reg' (an alias).
+   ------------------------------------------------------------------ */
+
+regs *findRegisterAlias (regs *reg, pCode *pc)
+{
+       pCode *curr;
+
+       if(!reg) return NULL;
+
+       if (regIsSpecial (reg, 0)) return NULL;
+
+       curr = findAssignmentToReg (reg, pc);
+
+       /* no assignment found --> no alias found */
+       if (!curr) return NULL;
+
+       switch (PCI(curr)->op)
+       {
+       case POC_MOVWF:
+               /* find previous assignment to WREG */
+               while (curr && !(PCI(curr)->outCond & PCC_W))
+                       curr = findPrevInstruction (curr->prev);
+               if (curr && PCI(curr)->op == POC_MOVFW)
+               {
+                       regs *op = getRegFromInstruction (curr);
+                       /* alias must not be changed since assignment... */
+                       if (PCI(curr)->pcop)
+                       {
+                               switch (PCI(curr)->pcop->type)
+                               {
+                               case PO_GPR_REGISTER:
+                               case PO_GPR_TEMP:
+                                       /* these operands are ok */
+                                       break;
+                               default:
+                                       /* not a plain register operand */
+                                       return NULL;
+                                       break;
+                               }
+                       }
+                       if (!op || regIsSpecial (op, 0) || !regIsUnchangedSince (op, pc, curr)) return NULL;
+                       //fprintf (stderr, "found register alias for %s: %s\n", reg->name, op && op->name ? op->name : "<no name>");
+                       return op;
+               } else {
+                       /* unknown source to WREG -- unknown register alias */
+                       return NULL;
+               }
+               break;
+       
+       default:
+               /* unhandled instruction -- assume unknown source, no alias */
+               return NULL;
+       }
+
+       /* no alias found */
+       return NULL;
+}
+
+/* ------------------------------------------------------------------
+   Analyze a single pCodeInstruction's dataflow relations and replace
+   it with a better variant if possible.
+   ------------------------------------------------------------------ */
+
+void analyzeAndReplacePCI (pCodeInstruction *pci)
+{
+       regs *op_reg, *alias_reg;
+       
+       assert (pci);
+
+       if (!isPCI(pci)) return;
+       
+       switch (pci->op)
+       {
+       case POC_MOVFW:
+       case POC_ADDFW:
+       case POC_ANDFW:
+       case POC_IORFW:
+       case POC_XORFW:
+               /* try to find a different source register */
+               op_reg = getRegFromInstruction (&pci->pc);
+               if (pci->op == POC_MOVFW) /* touches Z */
+               {
+                       pCode *assignment = findAssignmentToReg (op_reg, &pci->pc);
+                       if (assignment && isPCI(assignment) && (PCI(assignment)->op == POC_CLRF))
+                       {
+                               replace_PCI (pci, PCI(newpCode(POC_MOVLW, newpCodeOpLit(0))), "replaced with CLRF");
+                               return;
+                       }                       
+               }
+               
+               alias_reg = findRegisterAlias (op_reg, &pci->pc);
+               if (alias_reg)
+               {
+                       replace_PCI (pci, PCI(newpCode(pci->op, newpCodeOpRegFromStr (alias_reg->name))), "=DF= replaced with move from register alias");
+               }
+               break;
+
+       default:
+               /* do not optimize */
+               break;
+       } // switch
+}
+
+extern pFile *the_pFile;
+
+/* ------------------------------------------------------------------
+   Find and remove dead pCodes.
+   ------------------------------------------------------------------ */
+
+static int removeDeadPCIs (void)
+{
+       pBlock *pb;
+       unsigned int removed = 0;
+       
+       if (!the_pFile) return removed;
+       
+       do {
+               removed = 0;
+               
+               /* iterate over all pBlocks */
+               for (pb = the_pFile->pbHead; pb; pb = pb->next)
+               {
+                       pCode *pc, *pcnext = NULL;
+                       
+                       /* iterate over all pCodes */
+                       for (pc = findNextInstruction (pb->pcHead); pc; pc = pcnext)
+                       {
+                               pcnext = findNextInstruction (pc->next);
+                               removed += removeIfDeadPCI (pc);
+                       } // while
+               } // for pb
+
+               fprintf (stderr, "[removed %u dead pCodes]\n", removed);
+       } while (removed);
+       
+       return 0;
+}
+
+/* ------------------------------------------------------------------
+   This routine tries to optimize the dataflow by...
+   (1) 
+   
+   This routine leaves in dead pCodes (assignments whose results are
+   not used) -- these should be removed in a following sweep phase.
+   ------------------------------------------------------------------ */
+
+void optimizeDataflow (void)
+{
+       pBlock *pb;
+       
+       if (!the_pFile) return;
+
+       //fprintf (stderr, "%s:%u(%s): Starting optimization...\n", __FILE__, __LINE__, __FUNCTION__);
+       
+       /* iterate over all pBlocks */
+       for (pb = the_pFile->pbHead; pb; pb = pb->next)
+       {
+               pCode *pc, *pcnext = NULL;
+               
+               /* iterate over all pCodes */
+               for (pc = findNextInstruction (pb->pcHead); pc; pc = pcnext)
+               {
+                       pcnext = findNextInstruction (pc->next);
+                       analyzeAndReplacePCI (PCI(pc));
+               } // while
+       } // for pb
+
+       while (removeDeadPCIs ()) { /* remove dead codes in multiple passes */};
+       df_removeStates ();
+}
+
+#endif
+
 /*-----------------------------------------------------------------*
 * void pCodeRegOptimeRegUsage(pBlock *pb) 
 *-----------------------------------------------------------------*/
@@ -797,7 +1629,14 @@ void pCodeRegOptimizeRegUsage(int level)
        int passes;
        int saved = 0;
        int t = total_registers_saved;
-       
+
+#if 0
+       /* This is currently broken (need rewrite to correctly
+        * hamdle arbitrary pCodeOps instead of registers only). */
+       if (!pic14_options.disable_df)
+               optimizeDataflow ();
+#endif
+
        if(!register_optimization)
                return;
 #define OPT_PASSES 4
index 50c224ade294eda07c26cbcd0d5d68db3a509109..f7015d2cacdeeda9dcca855fbc5c05be595df8c4 100644 (file)
@@ -88,7 +88,8 @@ static int rDirectIdx=0;
 int pic14_nRegs = 128;   // = sizeof (regspic14) / sizeof (regs);
 
 int Gstack_base_addr=0; /* The starting address of registers that
-* are used to pass and return parameters */
+                        * are used to pass and return parameters */
+int Gstack_size = 0;
 
 
 
@@ -478,13 +479,17 @@ void initStack(int base_address, int size)
        int i;
        
        Gstack_base_addr = base_address;
-       //fprintf(stderr,"initStack");
+       Gstack_size = size;
+       //fprintf(stderr,"initStack [base:0x%02x, size:%d]\n", base_address, size);
        
        for(i = 0; i<size; i++) {
-               regs *r = newReg(REG_STK, PO_GPR_TEMP,base_address,NULL,1,0);
+               char buffer[16];
+               SNPRINTF(&buffer[0], 16, "STK%02d", i);
+               regs *r = newReg(REG_STK, PO_GPR_TEMP,base_address,buffer,1,0);
                r->address = base_address; // Pseudo stack needs a fixed location that can be known by all modules
                r->isFixed = 1;
-               r->name[0] = 's';
+               r->isPublic = 1;
+               //r->name[0] = 's';
                r->alias = 0x180; // Using shared memory for pseudo stack
                addSet(&dynStackRegs,r);
                base_address--;