pic patches by Slade
authorbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Tue, 19 Aug 2003 15:47:57 +0000 (15:47 +0000)
committerbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Tue, 19 Aug 2003 15:47:57 +0000 (15:47 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2838 4a8a32a2-be11-0410-ad9d-d568d2c75423

ChangeLog
src/pic/device.c
src/pic/gen.c
src/pic/genarith.c
src/pic/glue.c
src/pic/pcode.c
src/pic/pcode.h
src/pic/ralloc.c
src/pic/ralloc.h

index 949a959ae8cbd8c95e9d07e6d9cc0fb3efa6e3ad..9ebd65e3864dd5586c3fe0f4ec6d1d0e0ad6d3ed 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2003-08-19  Bernhard Held <bernhard@bernhardheld.de>
+
+       pic patch provided by Slade Rich <slade_rich@yahoo.com>
+       1. Interrupt would not compile properly. Ensure PCLATH register is saved
+          during interrupts. Ensure WSAVE is located at a shared bank address.
+       2. Fixed page selection in some places
+       3. Fixed BTFSS/C to where necessary use registers directly and not simply
+          the registers name strings.
+       4. Fixed "signed / unsigned compare" compiler warnings.
+       5. The PIC port manages its own allocation of the general purpose
+          registers, but makes no attempt to reuse them. As a result when
+          compiling it soon runs out of general purpose registers. Some
+          additional code was added to the files pcode.c and device.c to walk
+          through the function call tree and rename the registers so that they
+          get reused.
+
+       * src/pic/device.c
+       * src/pic/gen.c
+       * src/pic/glue.c
+       * src/pic/pcode.c
+       * src/pic/pcode.h
+       * src/pic/ralloc.c
+       * src/pic/ralloc.h
+       * src/pic/genarith.c: Fixed problems with PIC 14 port in functions
+       genPlus() & genMinus() when the result is the same as left or right
+
 2003-08-18  Erik Petrich <epetrich@ivorytower.norman.ok.us>
 
        * src/z80/gen.c (isUnsplitable, fetchPairLog): fixed bug #770454
index 2a2cd646cf244135042eafb5bfba82eb14ac443a..ab3e15a14f96544df39cd2359b1747be319df994 100644 (file)
@@ -167,7 +167,7 @@ int isREGinBank(regs *reg, int bank)
   if(!reg || !pic)
     return 0;
 
-  if(((reg->address | reg->alias) & pic->bankMask & bank) == bank)
+  if((int)((reg->address | reg->alias) & pic->bankMask & bank) == bank)
     return 1;
 
   return 0;
@@ -257,10 +257,18 @@ void dump_sfr(FILE *of)
              (!finalMapping[start].instance) && 
             (!finalMapping[start].isSFR)) {
 
-           fprintf(of,"%s\tres\t%i\n",
+           if (finalMapping[start].reg->isFixed) {
+             unsigned i;
+             for (i=0; i<finalMapping[start].reg->size; i++) {
+               fprintf(of,"%s\tEQU\t0x%04x\n",
+                    finalMapping[start].reg->name, 
+                    finalMapping[start].reg->address+i);
+             }
+           } else {
+             fprintf(of,"%s\tres\t%i\n",
                     finalMapping[start].reg->name, 
                     finalMapping[start].reg->size);
-
+           }
            finalMapping[start].reg->isEmitted = 1;
          }
        }
@@ -440,7 +448,7 @@ int validAddress(int address, int reg_size)
 void mapRegister(regs *reg)
 {
 
-  int i;
+  unsigned i;
   int alias;
 
   if(!reg || !reg->size) {
@@ -553,9 +561,30 @@ void assignRelocatableRegisters(set *regset, int used)
 
     //fprintf(stdout,"assigning %s isFixed=%d, wasUsed=%d\n",reg->name,reg->isFixed,reg->wasUsed);
 
-    if((!reg->isFixed) && ( used || reg->wasUsed))
-      address = assignRegister(reg,address);
-
+    if((!reg->isFixed) && ( used || reg->wasUsed)) {
+      /* If register have been reused then shall not print it a second time. */
+// Undefine REUSE_GPR in files pcode.c & device.c to prevent local function registers being reused.
+#define REUSE_GPR
+#ifdef REUSE_GPR
+      set *s;
+      int done = 0;
+      for (s = regset; s; s = s->next) {
+        regs *r;
+        r = s->item;
+        if (r == reg)
+          break;
+        if((!r->isFixed) && ( used || r->wasUsed)) {
+          if (r->rIdx == reg->rIdx) {
+            reg->address = r->address;
+            done = 1;
+            break;
+          }
+        }
+      }
+      if (!done)
+#endif // REUSE_GPR
+        address = assignRegister(reg,address);
+    }
   }
 
 }
index 9979c39a4d4816033592a68a4ebd6f099b85a99a..eadf223a0d9deb2d72bb42b7a95dbd4a445be59b 100644 (file)
@@ -216,7 +216,6 @@ void emitpLabel(int key)
 
 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
 {
-
   if(pcop)
     addpCode2pBlock(pb,newpCode(poc,pcop));
   else
@@ -230,6 +229,16 @@ void emitpcodeNULLop(PIC_OPCODE poc)
 
 }
 
+void emitpcodePagesel(const char *label)
+{
+
+  char code[81];
+  strcpy(code,"\tpagesel ");
+  strcat(code,label);
+  addpCode2pBlock(pb,newpCodeInlineP(code));
+
+}
+
 /*-----------------------------------------------------------------*/
 /* pic14_emitcode - writes the code into a file : for now it is simple    */
 /*-----------------------------------------------------------------*/
@@ -1182,12 +1191,28 @@ pCodeOp *popGetLabel(unsigned int key)
 
   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
 
-  if(key>max_key)
+  if(key>(unsigned int)max_key)
     max_key = key;
 
   return newpCodeOpLabel(NULL,key+100+labelOffset);
 }
 
+/*-------------------------------------------------------------------*/
+/* popGetLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
+/*-------------------------------------------------------------------*/
+pCodeOp *popGetHighLabel(unsigned int key)
+{
+  pCodeOp *pcop;
+  DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
+
+  if(key>(unsigned int)max_key)
+    max_key = key;
+
+  pcop = newpCodeOpLabel(NULL,key+100+labelOffset);
+  PCOLAB(pcop)->offset = 1;
+  return pcop;
+}
+
 /*-----------------------------------------------------------------*/
 /* popCopyReg - copy a pcode operator                              */
 /*-----------------------------------------------------------------*/
@@ -2554,6 +2579,7 @@ static void genPcall (iCode *ic)
     }
 */
     emitpcode(POC_CALL,popGetLabel(albl->key));
+    emitpcodePagesel(popGetLabel(blbl->key)->name); /* Must restore PCLATH before goto, without destroying W */
     emitpcode(POC_GOTO,popGetLabel(blbl->key));
     emitpLabel(albl->key);
 
@@ -2691,17 +2717,21 @@ static void genFunction (iCode *ic)
     }
 #endif
 
-    /* if this is an interrupt service routine then
-    save acc, b, dpl, dph  */
+    /* if this is an interrupt service routine */
     if (IFFUNC_ISISR(sym->type)) {
+/*  already done in pic14createInterruptVect() - delete me
       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
       emitpcodeNULLop(POC_NOP);
       emitpcodeNULLop(POC_NOP);
       emitpcodeNULLop(POC_NOP);
+*/
       emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
       emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
       emitpcode(POC_CLRF,   popCopyReg(&pc_status));
       emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
+      emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
+      emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
+      emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* durring an interrupt PCLATH must be cleared before a goto or call statement */
 
       pBlockConvert2ISR(pb);
 #if 0  
@@ -2936,18 +2966,17 @@ static void genEndFunction (iCode *ic)
                pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
            _G.debugLine = 0;
        }
-       
-        pic14_emitcode ("reti","");
-
-       emitpcode(POC_CLRF,   popCopyReg(&pc_status));
-       emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
-       emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
-       emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
-       emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
-       addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
-
-       emitpcodeNULLop(POC_RETFIE);
 
+        pic14_emitcode ("reti","");
+        emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
+        emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
+        emitpcode(POC_CLRF,   popCopyReg(&pc_status));
+        emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
+        emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
+        emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
+        emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
+        addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
+        emitpcodeNULLop(POC_RETFIE);
     }
     else {
         if (IFFUNC_ISCRITICAL(sym->type))
@@ -5424,7 +5453,7 @@ static void genAnd (iCode *ic, iCode *ifx)
            } else {
              pic14_emitcode("movlw","0x%x", (lit & 0xff));
              pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
-             if(know_W != (lit&0xff))
+             if(know_W != (int)(lit&0xff))
                emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
              know_W = lit &0xff;
              emitpcode(POC_ANDWF,popGet(AOP(left),offset));
@@ -5731,7 +5760,7 @@ static void genOr (iCode *ic, iCode *ifx)
              emitpcode(POC_BSF,
                        newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
            } else {
-             if(know_W != (lit & 0xff))
+             if(know_W != (int)(lit & 0xff))
                emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
              know_W = lit & 0xff;
              emitpcode(POC_IORWF, popGet(AOP(left),offset));
@@ -8370,6 +8399,7 @@ static void genConstPointerGet (operand *left,
   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
 
   emitpcode(POC_CALL,popGetLabel(albl->key));
+  emitpcodePagesel(popGetLabel(blbl->key)->name); /* Must restore PCLATH before goto, without destroying W */
   emitpcode(POC_GOTO,popGetLabel(blbl->key));
   emitpLabel(albl->key);
 
@@ -9328,7 +9358,7 @@ static void genAssign (iCode *ic)
   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
     if(AOP_TYPE(right) == AOP_LIT) {
       if(lit&0xff) {
-       if(know_W != (lit&0xff))
+       if(know_W != (int)(lit&0xff))
          emitpcode(POC_MOVLW,popGetLit(lit&0xff));
        know_W = lit&0xff;
        emitpcode(POC_MOVWF, popGet(AOP(result),offset));
@@ -9380,6 +9410,8 @@ static void genJumpTab (iCode *ic)
     pic14_emitcode("jmp","@a+dptr");
     pic14_emitcode("","%05d_DS_:",jtab->key+100);
 
+    emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
+    emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
     emitSKPNC;
index b96dcdaca94eb4a74de1a8e824eedc00142a1ab3..3809c711201f92bf0e9baaa9633f6dbdf6fa006a 100644 (file)
@@ -977,30 +977,47 @@ void genPlus (iCode *ic)
     offset = 1;
 
 
-    while(size--){
-      if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
-       emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
-       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
-
-       pic14_emitcode("movf","%s,w",  aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
-       pic14_emitcode("movwf","%s",  aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
+    if(size){
+      if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
+        if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && (
+          (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) || 
+          (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE))) {
+          while(size--){
+            emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset));
+            emitSKPNC;
+            emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset));
+            emitpcode(POC_ADDLW,   popGet(AOP(IC_LEFT(ic)),offset));
+            emitpcode(POC_MOVWF,   popGet(AOP(IC_RESULT(ic)),offset));
+            offset++;
+          }
+        } else {
+          while(size--){
+            emitpcode(POC_MOVFW,   popGet(AOP(IC_LEFT(ic)),offset));
+            emitSKPNC;
+            emitpcode(POC_INCFSZW, popGet(AOP(IC_LEFT(ic)),offset));
+            emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset));
+            offset++;
+          }
+        }
+      } else {
+        PIC_OPCODE poc = POC_MOVFW;
+        if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && (
+          (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) || 
+          (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE)))
+          poc = POC_MOVLW;
+        while(size--){
+          if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+            emitpcode(poc, popGet(AOP(IC_LEFT(ic)),offset));
+            emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
+          }
+          emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset));
+          emitSKPNC;
+          emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset));
+          emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset));
+          offset++;
+        }
       }
-
-      emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset));
-      emitSKPNC;
-      emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset));
-      emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset));
-
-      /*
-       pic14_emitcode("movf","%s,w",  aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
-       emitSKPNC;
-       pic14_emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
-       pic14_emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
-      */
-
-      offset++;
     }
-
   }
 
   if (AOP_SIZE(IC_RESULT(ic)) > AOP_SIZE(IC_RIGHT(ic))) {
@@ -1012,8 +1029,28 @@ void genPlus (iCode *ic)
     size = AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_RIGHT(ic)) - 1;
 
     /* First grab the carry from the lower bytes */
-    emitpcode(POC_CLRF, popGet(AOP(IC_RESULT(ic)),offset));
-    emitpcode(POC_RLF,  popGet(AOP(IC_RESULT(ic)),offset));
+    if (AOP_SIZE(IC_LEFT(ic)) > AOP_SIZE(IC_RIGHT(ic))) { 
+      int leftsize = AOP_SIZE(IC_LEFT(ic)) - AOP_SIZE(IC_RIGHT(ic));
+      PIC_OPCODE poc = POC_MOVFW;
+      if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && (
+       (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) || 
+       (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE)))
+        poc = POC_MOVLW;
+      while(leftsize-- > 0) {
+        emitpcode(poc, popGet(AOP(IC_LEFT(ic)),offset));
+        emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
+        emitSKPNC;
+        emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset));
+        offset++;
+        if (size)
+          size--;
+        else
+          break;
+      }
+    } else {
+      emitpcode(POC_CLRF, popGet(AOP(IC_RESULT(ic)),offset));
+      emitpcode(POC_RLF,  popGet(AOP(IC_RESULT(ic)),offset));
+    }
 
 
     if(sign) {
@@ -1507,35 +1544,53 @@ void genMinus (iCode *ic)
       }
     }
 
-    /*
-      emitpcode(POC_MOVFW,  popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
-
-      if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
-      emitpcode(POC_SUBFW,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-      } else {
-      emitpcode(POC_SUBFW,  popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
-      emitpcode(POC_MOVWF,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-      }
-    */
+    size = min( AOP_SIZE(IC_RESULT(ic)), AOP_SIZE(IC_RIGHT(ic))) - 1;
     offset = 1;
-    size--;
 
-    while(size--){
-      if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
-       emitpcode(POC_MOVFW,  popGet(AOP(IC_LEFT(ic)),offset));
-       emitpcode(POC_MOVWF,  popGet(AOP(IC_RESULT(ic)),offset));
+    if(size){
+      if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
+        if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && (
+          (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) || 
+          (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE))) {
+          while(size--){
+            emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset));
+            emitSKPC;
+            emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset));
+            emitpcode(POC_SUBLW,   popGet(AOP(IC_LEFT(ic)),offset));
+            emitpcode(POC_MOVWF,   popGet(AOP(IC_RESULT(ic)),offset));
+            offset++;
+          }
+        } else {
+          while(size--){
+            emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset));
+            emitSKPC;
+            emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset));
+            emitpcode(POC_SUBFW,   popGet(AOP(IC_LEFT(ic)),offset));
+            emitpcode(POC_MOVWF,   popGet(AOP(IC_RESULT(ic)),offset));
+            offset++;
+          }
+        }
+      } else {
+        PIC_OPCODE poc = POC_MOVFW;
+        if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && (
+          (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) || 
+          (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE)))
+          poc = POC_MOVLW;
+      while(size--){
+          if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+            emitpcode(POC_MOVFW,  popGet(AOP(IC_LEFT(ic)),offset));
+            emitpcode(POC_MOVWF,  popGet(AOP(IC_RESULT(ic)),offset));
+          }
+          emitpcode(POC_MOVFW,  popGet(AOP(IC_RIGHT(ic)),offset));
+          emitSKPC;
+          emitpcode(POC_INCFSZW,popGet(AOP(IC_RIGHT(ic)),offset));
+          emitpcode(POC_SUBWF,  popGet(AOP(IC_RESULT(ic)),offset));
+          offset++;
+        }
       }
-      emitpcode(POC_MOVFW,  popGet(AOP(IC_RIGHT(ic)),offset));
-      emitSKPC;
-      emitpcode(POC_INCFSZW,popGet(AOP(IC_RIGHT(ic)),offset));
-      emitpcode(POC_SUBWF,  popGet(AOP(IC_RESULT(ic)),offset));
-
-      offset++;
     }
-
   }
 
-
   //    adjustArithmeticResult(ic);
         
  release:
index 7699fbad560934da49877a8aa2246bcf190fea65..8a393a8c38c5f42d9d5ae2520ea955eb3fcd0716 100644 (file)
@@ -106,10 +106,10 @@ pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
   symbol *sym;
   int bitvars = 0;;
 
+  /* print the area name */
   if (addPublics)
     fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
 
-  /* print the area name */
   for (sym = setFirstItem (map->syms); sym;
        sym = setNextItem (map->syms)) {
 
@@ -307,7 +307,7 @@ printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
   else {
     //printChar (oFile, s, strlen (s) + 1);
 
-    for(remain=0; remain<strlen(s); remain++) {
+    for(remain=0; remain<(int)strlen(s); remain++) {
       addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
       //fprintf(stderr,"0x%02x ",s[remain]);
     }
@@ -572,14 +572,15 @@ pic14createInterruptVect (FILE * vFile)
   fprintf (vFile, "\t__config 0x%x\n", getConfigWord(0x2007));
 
   fprintf (vFile, "%s", iComments2);
-  fprintf (vFile, "; reset and interrupt vectors \n");
+  fprintf (vFile, "; reset vector \n");
   fprintf (vFile, "%s", iComments2);
   fprintf (vFile, "STARTUP\t%s\n", CODE_NAME);
+  fprintf (vFile, "\tnop\n"); /* first location used by incircuit debugger */
   fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
-  fprintf (vFile, "\tnop\n");
+/* during an interrupt PCLATH must be cleared before a goto  - delete me
   fprintf (vFile, "\tnop\n");
   fprintf (vFile, "\tgoto\t__sdcc_interrupt\n");
-
+*/
 }
 
 
@@ -919,11 +920,15 @@ picglue ()
     copyFile (asmFile, vFile);
     
     fprintf (asmFile, "%s", iComments2);
-    fprintf (asmFile, "; initialization and interrupt code \n");
+    fprintf (asmFile, "; interrupt and initialization code\n");
     fprintf (asmFile, "%s", iComments2);
+    fprintf (asmFile, "code_init\t%s\t0x4\n", CODE_NAME);
+
+    /* interrupt service routine */
+    fprintf (asmFile, "__sdcc_interrupt:\n");
+    copypCode(asmFile, 'I');
 
     /* initialize data memory */
-    fprintf (asmFile, "code_init\t%s\t0x10\n", CODE_NAME);
     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 
@@ -931,11 +936,6 @@ picglue ()
     copypCode(asmFile, statsg->dbName);
     fprintf (asmFile,"\tpagesel _main\n");
     fprintf (asmFile,"\tgoto _main\n");
-
-    /* interrupt service routine */
-    fprintf (asmFile, "__sdcc_interrupt:\n");
-    copypCode(asmFile, 'I');
-    fprintf (asmFile,"\tgoto $\n");
   }
 
 #if 0    
index 3b2b7d91b14917ef41dd58cb28fe7291a35297f3..295ff3367d90f92de6481e86b8219d398235b0b4 100644 (file)
@@ -60,6 +60,7 @@ pCodeOpReg pc_pclath    = {{PO_PCLATH,  "PCLATH"}, -1, NULL,0,NULL};
 pCodeOpReg pc_kzero     = {{PO_GPR_REGISTER,  "KZ"}, -1, NULL,0,NULL};
 pCodeOpReg pc_wsave     = {{PO_GPR_REGISTER,  "WSAVE"}, -1, NULL,0,NULL};
 pCodeOpReg pc_ssave     = {{PO_GPR_REGISTER,  "SSAVE"}, -1, NULL,0,NULL};
+pCodeOpReg pc_psave     = {{PO_GPR_REGISTER,  "PSAVE"}, -1, NULL,0,NULL};
 
 static int mnemonics_initialized = 0;
 
@@ -1226,7 +1227,7 @@ void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
   va_end (val);
 
   len = strlen(*str);
-  if(len > *size) {
+  if((size_t)len > *size) {
     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
     fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
   }
@@ -1277,6 +1278,7 @@ extern void init_pic(char *);
 void  pCodeInitRegisters(void)
 {
   static int initialized=0;
+  int shareBankAddress;
 
   if(initialized)
     return;
@@ -1299,13 +1301,19 @@ void  pCodeInitRegisters(void)
   pc_pcl.rIdx = IDX_PCL;
   pc_pclath.rIdx = IDX_PCLATH;
 
-  pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
-  pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
-  pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
+  pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0); /* Known Zero - actually just a general purpose reg. */
+  pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0x80); /* Interupt storage for working register - must be same address in all banks ie section SHAREBANK. */
+  pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0); /* Interupt storage for status register. */
+  pc_psave.r = allocInternalRegister(IDX_PSAVE,"PSAVE", PO_GPR_REGISTER, 0); /* Interupt storage for pclath register. */
+
+  pc_kzero.rIdx = pc_kzero.r->rIdx;
+  pc_wsave.rIdx = pc_wsave.r->rIdx;
+  pc_ssave.rIdx = pc_ssave.r->rIdx;
+  pc_psave.rIdx = pc_psave.r->rIdx;
 
-  pc_kzero.rIdx = IDX_KZ;
-  pc_wsave.rIdx = IDX_WSAVE;
-  pc_ssave.rIdx = IDX_SSAVE;
+  shareBankAddress = 0x7f; /* FIXME - this is different for some PICs ICs if the sharebank does not exist then this address needs to be reserved across all banks. */
+  pc_wsave.r->isFixed = 1;
+  pc_wsave.r->address = shareBankAddress;
 
   /* probably should put this in a separate initialization routine */
   pb_dead_pcodes = newpBlock();
@@ -1621,16 +1629,20 @@ static int RegCond(pCodeOp *pcop)
   if(!pcop)
     return 0;
 
-  if(pcop->type == PO_GPR_BIT  && !strcmp(pcop->name, pc_status.pcop.name)) {
-    switch(PCORB(pcop)->bit) {
-    case PIC_C_BIT:
-      return PCC_C;
-    case PIC_DC_BIT:
-       return PCC_DC;
-    case PIC_Z_BIT:
-      return PCC_Z;
-    }
-
+  if (pcop->type == PO_GPR_BIT) {
+    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;
+         }
+//    }
   }
 
   return 0;
@@ -2049,6 +2061,7 @@ pCodeOp *newpCodeOpLabel(char *name, int key)
   else 
     s = name, key = label_key--;
 
+  PCOLAB(pcop)->offset = 0;
   if(s)
     pcop->name = Safe_strdup(s);
 
@@ -2148,20 +2161,31 @@ pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
 {
   pCodeOp *pcop;
+  struct regs *r = 0;
 
   pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
   pcop->type = PO_GPR_BIT;
-  if(s)
-    pcop->name = Safe_strdup(s);   
-  else
-    pcop->name = NULL;
 
   PCORB(pcop)->bit = bit;
   PCORB(pcop)->inBitSpace = inBitSpace;
 
   /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
-  PCOR(pcop)->r = NULL;
-  PCOR(pcop)->rIdx = 0;
+  if (s && !inBitSpace) {
+    r = dirregWithName(s);
+    if (!r) {
+      unsigned char idx = ((s[3] - (((s[3]>='0')&&(s[3]<='9'))?'0':'A'-10))<<4)|(s[4] - (((s[4]>='0')&&(s[4]<='9'))?'0':'A'-10));
+      r = pic14_regWithIdx(idx);
+    }
+  }
+  if (r) {
+    pcop->name = NULL;
+    PCOR(pcop)->r = r;
+    PCOR(pcop)->rIdx = r->rIdx;
+  } else {
+    pcop->name = Safe_strdup(s);   
+    PCOR(pcop)->r = NULL;
+    PCOR(pcop)->rIdx = 0;
+  }
   return pcop;
 }
 
@@ -2587,6 +2611,16 @@ char *get_op(pCodeOp *pcop,char *buffer, size_t size)
        SAFE_snprintf(&s,&size,"%s",pcop->name);
       return buffer;
 
+    case PO_LABEL:
+      s = buffer;
+      if  (pcop->name) {
+        if(PCOLAB(pcop)->offset == 1)
+          SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
+           else
+          SAFE_snprintf(&s,&size,"%s",pcop->name);
+      }
+      return buffer;
+
     default:
       if  (pcop->name) {
        if(use_buffer) {
@@ -2642,13 +2676,14 @@ char *pCode2str(char *str, size_t size, pCode *pc)
 
       if(PCI(pc)->isBitInst) {
        if(PCI(pc)->pcop->type == PO_GPR_BIT) {
-         if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
-           SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
-                         PCI(pc)->pcop->name ,
-                         PCI(pc)->pcop->name );
-         else
-           SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)), 
-                         (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
+      char *name = PCI(pc)->pcop->name;
+      if (!name) 
+        name = PCOR(PCI(pc)->pcop)->r->name;
+      if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
+           SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
+      else
+           SAFE_snprintf(&s,&size,"%s,%d", name, 
+                         (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
        } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
          SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
        }else
@@ -3330,7 +3365,8 @@ void AnalyzepBlock(pBlock *pb)
     /* Is this an instruction with operands? */
     if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
 
-      if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
+      if((PCI(pc)->pcop->type == PO_GPR_TEMP) 
+        || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
 
        /* Loop through all of the registers declared so far in
           this block and see if we find this one there */
@@ -4968,23 +5004,122 @@ void AnalyzeBanking(void)
 
 }
 
+// Undefine REUSE_GPR in files pcode.c & device.c to prevent local function registers being reused.
+#define REUSE_GPR
+#ifdef REUSE_GPR
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (resetrIdx)
+{
+  if (!((regs *)item)->isFixed)
+    ((regs *)item)->rIdx = 0;
+
+  return 0;
+}
+
+pCode *findFunction(char *fname);
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+unsigned register_reassign(pBlock *pb, unsigned idx)
+{
+  pCode *pc;
+
+  /* check recursion */
+  pc = setFirstItem(pb->function_entries);
+  if(!pc)
+    return idx;
+
+  DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
+
+  if (pb->tregisters) {
+    regs *r;
+    for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
+      if (r->type == REG_GPR) {
+        if (!r->isFixed) {
+          if (r->rIdx < (int)idx) {
+            char s[20];
+            r->rIdx = idx++;
+            sprintf(s,"r0x%02X", r->rIdx);
+            DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
+            free(r->name);
+            r->name = Safe_strdup(s);
+          }
+        }
+      }
+    }
+  }
+  for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
+
+    if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
+      char *dest = get_op_from_instruction(PCI(pc));
+
+      pCode *pcn = findFunction(dest);
+      if(pcn) {
+         register_reassign(pcn->pb,idx);
+      }
+    }
+
+  }
+
+  return idx;
+}
+
+/*-----------------------------------------------------------------*/
+/* Re-allocate the GPR for optimum reuse for a given pblock        */
+/* eg  if a function m() calls function f1() and f2(), where f1    */
+/* allocates a local variable vf1 and f2 allocates a local         */
+/* variable vf2. Then providing f1 and f2 do not call each other   */
+/* they may share the same general purpose registers for vf1 and   */
+/* vf2.                                                            */
+/* This is done by first setting the the regs rIdx to start after  */
+/* all the global variables, then walking through the call tree    */
+/* renaming the registers to match their new idx and incrementng   */
+/* it as it goes. If a function has already been called it will    */ 
+/* only rename the registers if it has already used up those       */
+/* registers ie rIdx of the function's registers is lower than the */
+/* current rIdx. That way the register will not be reused while    */
+/* still being used by an eariler function call.                   */
+/*-----------------------------------------------------------------*/
+void register_reusage(pBlock *mainPb)
+{
+  static int exercised = 0;
+  if (!exercised) { /* Only do this once */
+       /* Find end of statically allocated variables for start idx */
+    unsigned idx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
+    regs *r;
+    for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
+      if (r->type != REG_SFR) {
+        idx += r->size; /* Increment for all statically allocated variables */
+      }
+    }
+
+    applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
+
+    if (mainPb)
+      idx = register_reassign(mainPb,idx); /* Do main and all the functions that are called from it. */
+    idx = register_reassign(the_pFile->pbHead,idx); /* Do the other functions such as interrupts. */
+  }
+  exercised++;
+}
+#endif // REUSE_GPR
+
 /*-----------------------------------------------------------------*/
 /* buildCallTree - look at the flow and extract all of the calls   */
 /*                                                                 */
 /*-----------------------------------------------------------------*/
 set *register_usage(pBlock *pb);
 
+
 void buildCallTree(void    )
 {
   pBranch *pbr;
-  pBlock  *pb;
+  pBlock  *pb, *mainPb = 0;
   pCode   *pc;
 
   if(!the_pFile)
     return;
 
-
-
   /* Now build the call tree.
      First we examine all of the pCodes for functions.
      Keep in mind that the function boundaries coincide
@@ -5015,37 +5150,43 @@ void buildCallTree(void    )
     pCode *pc_fstart=NULL;
     for(pc = pb->pcHead; pc; pc = pc->next) {
       if(isPCF(pc)) {
-       if (PCF(pc)->fname) {
+        pCodeFunction *pcf = PCF(pc);
+        if (pcf->fname) {
 
-         if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
-           //fprintf(stderr," found main \n");
-           pb->cmemmap = NULL;  /* FIXME do we need to free ? */
-           pb->dbName = 'M';
-         }
+          if(STRCASECMP(pcf->fname, "_main") == 0) {
+            //fprintf(stderr," found main \n");
+            pb->cmemmap = NULL;  /* FIXME do we need to free ? */
+            pb->dbName = 'M';
+                       mainPb = pb;
+          }
 
-         pbr = Safe_calloc(1,sizeof(pBranch));
-         pbr->pc = pc_fstart = pc;
-         pbr->next = NULL;
+          pbr = Safe_calloc(1,sizeof(pBranch));
+          pbr->pc = pc_fstart = pc;
+          pbr->next = NULL;
 
-         the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
+          the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
 
-         // Here's a better way of doing the same:
-         addSet(&pb->function_entries, pc);
+          // Here's a better way of doing the same:
+          addSet(&pb->function_entries, pc);
 
-       } else {
-         // Found an exit point in a function, e.g. return
-         // (Note, there may be more than one return per function)
-         if(pc_fstart)
-           pBranchLink(PCF(pc_fstart), PCF(pc));
+        } else {
+          // Found an exit point in a function, e.g. return
+          // (Note, there may be more than one return per function)
+          if(pc_fstart)
+            pBranchLink(PCF(pc_fstart), pcf);
 
-         addSet(&pb->function_exits, pc);
-       }
+          addSet(&pb->function_exits, pc);
+        }
       } else if(isCALL(pc)) {
-       addSet(&pb->function_calls,pc);
+        addSet(&pb->function_calls,pc);
       }
     }
   }
 
+#ifdef REUSE_GPR
+  register_reusage(mainPb); /* Comment out this line to prevent local function registers being reused. Note from this point onwards finding a GPR by its rIdx value will no longer work.*/
+#endif // REUSE_GPR
+
   /* Re-allocate the registers so that there are no collisions
    * between local variables when one function call another */
 
index e8b441598bf62080087a91d96e201f577953b6a8..1c3a024f7ee18b67f7a068c4dfe60b585ed9d5b9 100644 (file)
@@ -326,6 +326,7 @@ typedef struct pCodeOpLabel
 {
   pCodeOp pcop;
   int key;
+  int offset;           /* low or high byte of label */
 } pCodeOpLabel;
 
 typedef struct pCodeOpReg
@@ -832,8 +833,9 @@ extern pCodeOpReg pc_fsr;
 extern pCodeOpReg pc_pcl;
 extern pCodeOpReg pc_pclath;
 extern pCodeOpReg pc_kzero;
-extern pCodeOpReg pc_wsave;     /* wsave and ssave are used to save W and the Status */
+extern pCodeOpReg pc_wsave;     /* wsave, ssave and psave are used to save W, the Status and PCLATH*/
 extern pCodeOpReg pc_ssave;     /* registers during an interrupt */
+extern pCodeOpReg pc_psave;     /* registers during an interrupt */
 
 
 #endif // __PCODE_H__
index b1a37641f89f4681a6fe38faa11ba014fca61c4b..5c8e6dd159ac62295837f7a14cd59bfce8c23051 100644 (file)
@@ -487,7 +487,7 @@ regWithIdx (set *dRegs, int idx, int fixed)
   for (dReg = setFirstItem(dRegs) ; dReg ; 
        dReg = setNextItem(dRegs)) {
 
-    if(idx == dReg->rIdx && (fixed == dReg->isFixed)) {
+    if(idx == dReg->rIdx && (fixed == (int)dReg->isFixed)) {
       return dReg;
     }
   }
@@ -838,6 +838,8 @@ pic14_allocWithIdx (int idx)
     debugLog ("Found a Processor Register!\n");
   } else if( (dReg = regWithIdx ( dynInternalRegs, idx,0)) != NULL ) {
     debugLog ("Found an Internal Register!\n");
+  } else if( (dReg = regWithIdx ( dynInternalRegs, idx,1)) != NULL ) {
+    debugLog ("Found an Internal Register!\n");
   } else {
     
     debugLog ("Dynamic Register not found\n");
@@ -1075,6 +1077,7 @@ void writeUsedRegs(FILE *of)
 {
   packBits(dynDirectBitRegs);
 
+  assignFixedRegisters(dynInternalRegs);
   assignFixedRegisters(dynAllocRegs);
   assignFixedRegisters(dynStackRegs);
   assignFixedRegisters(dynDirectRegs);
@@ -2134,7 +2137,6 @@ serialRegAssign (eBBlock ** ebbs, int count)
              debugLog ("  %d - \n", __LINE__);
              if(debugF) 
                bitVectDebugOn(_G.regAssigned, debugF);
-
              for (j = 0; j < sym->nRegs; j++)
                {
                  if (sym->regType == REG_PTR)
@@ -2142,7 +2144,7 @@ serialRegAssign (eBBlock ** ebbs, int count)
                  else
                    sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
 
-                 /* if the allocation falied which means
+                 /* if the allocation failed which means
                     this was spilt then break */
                  if (!sym->regs[j])
                    break;
index a330ece3593f856b0cac826e5c20d26b0ac83f91..5c6d77b839c74e288fb47712beafcc0901360971 100644 (file)
@@ -122,5 +122,6 @@ regs *allocRegByName (char *name, int size );
 #define IDX_KZ      0x7fff   /* Known zero - actually just a general purpose reg. */
 #define IDX_WSAVE   0x7ffe
 #define IDX_SSAVE   0x7ffd
+#define IDX_PSAVE   0x7ffc
 
 #endif