multi-byte complements were failing
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for pic
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18   
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22   
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26   
27   Notes:
28   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
29       Made everything static
30 -------------------------------------------------------------------------*/
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #include "common.h"
40 #include "SDCCpeeph.h"
41 #include "ralloc.h"
42 #include "pcode.h"
43 #include "gen.h"
44
45
46 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
47 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
48 void genMult8X8_8 (operand *, operand *,operand *);
49 pCode *AssembleLine(char *line);
50 extern void printpBlock(FILE *of, pBlock *pb);
51
52 static int labelOffset=0;
53 extern int debug_verbose;
54 static int optimized_for_speed = 0;
55
56 /* max_key keeps track of the largest label number used in 
57 a function. This is then used to adjust the label offset
58 for the next function.
59 */
60 static int max_key=0;
61 static int GpsuedoStkPtr=0;
62
63 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
64 unsigned int pic14aopLiteral (value *val, int offset);
65 const char *AopType(short type);
66 static iCode *ifxForOp ( operand *op, iCode *ic );
67
68 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
69
70 /* this is the down and dirty file with all kinds of 
71 kludgy & hacky stuff. This is what it is all about
72 CODE GENERATION for a specific MCU . some of the
73 routines may be reusable, will have to see */
74
75 static char *zero = "#0x00";
76 static char *one  = "#0x01";
77 static char *spname = "sp";
78
79 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
80 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
81 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
82 static char **fReturn = fReturnpic14;
83
84 static char *accUse[] = {"a","b"};
85
86 //static short rbank = -1;
87
88 static struct {
89   short r0Pushed;
90   short r1Pushed;
91   short accInUse;
92   short inLine;
93   short debugLine;
94   short nRegsSaved;
95   set *sendSet;
96 } _G;
97
98 /* Resolved ifx structure. This structure stores information
99 about an iCode ifx that makes it easier to generate code.
100 */
101 typedef struct resolvedIfx {
102   symbol *lbl;     /* pointer to a label */
103   int condition;   /* true or false ifx */
104   int generated;   /* set true when the code associated with the ifx
105                     * is generated */
106 } resolvedIfx;
107
108 extern int pic14_ptrRegReq ;
109 extern int pic14_nRegs;
110 extern FILE *codeOutFile;
111 static void saverbank (int, iCode *,bool);
112
113 static lineNode *lineHead = NULL;
114 static lineNode *lineCurr = NULL;
115
116 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
117 0xE0, 0xC0, 0x80, 0x00};
118 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
119 0x07, 0x03, 0x01, 0x00};
120
121 static  pBlock *pb;
122
123 /*-----------------------------------------------------------------*/
124 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
125 /*                 exponent of 2 is returned, otherwise -1 is      */
126 /*                 returned.                                       */
127 /* note that this is similar to the function `powof2' in SDCCsymt  */
128 /* if(n == 2^y)                                                    */
129 /*   return y;                                                     */
130 /* return -1;                                                      */
131 /*-----------------------------------------------------------------*/
132 static int my_powof2 (unsigned long num)
133 {
134   if(num) {
135     if( (num & (num-1)) == 0) {
136       int nshifts = -1;
137       while(num) {
138         num>>=1;
139         nshifts++;
140       }
141       return nshifts;
142     }
143   }
144   
145   return -1;
146 }
147
148 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
149 {
150   
151   DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
152     line_no,
153     ((result) ? AopType(AOP_TYPE(result)) : "-"),
154     ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
155     ((left)   ? AopType(AOP_TYPE(left)) : "-"),
156     ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
157     ((right)  ? AopType(AOP_TYPE(right)) : "-"),
158     ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
159     ((result) ? AOP_SIZE(result) : 0));
160   
161 }
162
163 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
164 {
165   
166   DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
167     line_no,
168     ((result) ? AopType(AOP_TYPE(result)) : "-"),
169     ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
170     ((left)   ? AopType(AOP_TYPE(left)) : "-"),
171     ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
172     ((right)  ? AopType(AOP_TYPE(right)) : "-"),
173     ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
174   
175 }
176
177 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
178 {
179   va_list ap;
180   char lb[INITIAL_INLINEASM];  
181   char *lbp = lb;
182   
183   if(!debug_verbose)
184     return;
185   
186   va_start(ap,fmt);   
187   
188   if (inst && *inst) {
189     if (fmt && *fmt)
190       sprintf(lb,"%s\t",inst);
191     else
192       sprintf(lb,"%s",inst);
193     vsprintf(lb+(strlen(lb)),fmt,ap);
194   }  else
195     vsprintf(lb,fmt,ap);
196   
197   while (isspace(*lbp)) lbp++;
198   
199   if (lbp && *lbp) 
200     lineCurr = (lineCurr ?
201     connectLine(lineCurr,newLineNode(lb)) :
202   (lineHead = newLineNode(lb)));
203   lineCurr->isInline = _G.inLine;
204   lineCurr->isDebug  = _G.debugLine;
205   
206   addpCode2pBlock(pb,newpCodeCharP(lb));
207   
208   va_end(ap);
209 }
210
211
212 void emitpLabel(int key)
213 {
214   addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
215 }
216
217 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
218 {
219   if(pcop)
220     addpCode2pBlock(pb,newpCode(poc,pcop));
221   else
222     DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
223 }
224
225 void emitpcodeNULLop(PIC_OPCODE poc)
226 {
227   
228   addpCode2pBlock(pb,newpCode(poc,NULL));
229   
230 }
231
232
233 /*-----------------------------------------------------------------*/
234 /* pic14_emitcode - writes the code into a file : for now it is simple    */
235 /*-----------------------------------------------------------------*/
236 void pic14_emitcode (char *inst,char *fmt, ...)
237 {
238   va_list ap;
239   char lb[INITIAL_INLINEASM];  
240   char *lbp = lb;
241   
242   va_start(ap,fmt);   
243   
244   if (inst && *inst) {
245     if (fmt && *fmt)
246       sprintf(lb,"%s\t",inst);
247     else
248       sprintf(lb,"%s",inst);
249     vsprintf(lb+(strlen(lb)),fmt,ap);
250   }  else
251     vsprintf(lb,fmt,ap);
252   
253   while (isspace(*lbp)) lbp++;
254   
255   if (lbp && *lbp) 
256     lineCurr = (lineCurr ?
257     connectLine(lineCurr,newLineNode(lb)) :
258   (lineHead = newLineNode(lb)));
259   lineCurr->isInline = _G.inLine;
260   lineCurr->isDebug  = _G.debugLine;
261   
262   if(debug_verbose)
263     addpCode2pBlock(pb,newpCodeCharP(lb));
264   
265   va_end(ap);
266 }
267
268
269 /*-----------------------------------------------------------------*/
270 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
271 /*-----------------------------------------------------------------*/
272 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
273 {
274   bool r0iu = FALSE , r1iu = FALSE;
275   bool r0ou = FALSE , r1ou = FALSE;
276   
277   /* the logic: if r0 & r1 used in the instruction
278   then we are in trouble otherwise */
279   
280   /* first check if r0 & r1 are used by this
281   instruction, in which case we are in trouble */
282   if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
283     (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
284   {
285     goto endOfWorld;      
286   }
287   
288   r0ou = bitVectBitValue(ic->rMask,R0_IDX);
289   r1ou = bitVectBitValue(ic->rMask,R1_IDX);
290   
291   /* if no usage of r0 then return it */
292   if (!r0iu && !r0ou) {
293     ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
294     (*aopp)->type = AOP_R0;
295     
296     return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
297   }
298   
299   /* if no usage of r1 then return it */
300   if (!r1iu && !r1ou) {
301     ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
302     (*aopp)->type = AOP_R1;
303     
304     return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
305   }    
306   
307   /* now we know they both have usage */
308   /* if r0 not used in this instruction */
309   if (!r0iu) {
310     /* push it if not already pushed */
311     if (!_G.r0Pushed) {
312       //pic14_emitcode ("push","%s",
313       //          pic14_regWithIdx(R0_IDX)->dname);
314       _G.r0Pushed++ ;
315     }
316     
317     ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
318     (*aopp)->type = AOP_R0;
319     
320     return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
321   }
322   
323   /* if r1 not used then */
324   
325   if (!r1iu) {
326     /* push it if not already pushed */
327     if (!_G.r1Pushed) {
328       //pic14_emitcode ("push","%s",
329       //          pic14_regWithIdx(R1_IDX)->dname);
330       _G.r1Pushed++ ;
331     }
332     
333     ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
334     (*aopp)->type = AOP_R1;
335     return pic14_regWithIdx(R1_IDX);
336   }
337   
338 endOfWorld :
339   /* I said end of world but not quite end of world yet */
340   /* if this is a result then we can push it on the stack*/
341   if (result) {
342     (*aopp)->type = AOP_STK;    
343     return NULL;
344   }
345   
346   /* other wise this is true end of the world */
347   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
348     "getFreePtr should never reach here");
349   exit(0);
350 }
351
352 /*-----------------------------------------------------------------*/
353 /* newAsmop - creates a new asmOp                                  */
354 /*-----------------------------------------------------------------*/
355 asmop *newAsmop (short type)
356 {
357   asmop *aop;
358   
359   aop = Safe_calloc(1,sizeof(asmop));
360   aop->type = type;
361   return aop;
362 }
363
364 static void genSetDPTR(int n)
365 {
366   if (!n)
367   {
368     pic14_emitcode(";", "Select standard DPTR");
369     pic14_emitcode("mov", "dps, #0x00");
370   }
371   else
372   {
373     pic14_emitcode(";", "Select alternate DPTR");
374     pic14_emitcode("mov", "dps, #0x01");
375   }
376 }
377
378 /*-----------------------------------------------------------------*/
379 /* resolveIfx - converts an iCode ifx into a form more useful for  */
380 /*              generating code                                    */
381 /*-----------------------------------------------------------------*/
382 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
383 {
384   if(!resIfx) 
385     return;
386   
387   //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
388   
389   resIfx->condition = 1;    /* assume that the ifx is true */
390   resIfx->generated = 0;    /* indicate that the ifx has not been used */
391   
392   if(!ifx) {
393     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
394                       /*
395                       DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
396                       __FUNCTION__,__LINE__,resIfx->lbl->key);
397     */
398   } else {
399     if(IC_TRUE(ifx)) {
400       resIfx->lbl = IC_TRUE(ifx);
401     } else {
402       resIfx->lbl = IC_FALSE(ifx);
403       resIfx->condition = 0;
404     }
405     /*
406     if(IC_TRUE(ifx)) 
407     DEBUGpic14_emitcode("; ***","ifx true is non-null");
408     if(IC_FALSE(ifx)) 
409     DEBUGpic14_emitcode("; ***","ifx false is non-null");
410     */
411   }
412   
413   //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
414   
415 }
416 /*-----------------------------------------------------------------*/
417 /* pointerCode - returns the code for a pointer type               */
418 /*-----------------------------------------------------------------*/
419 static int pointerCode (sym_link *etype)
420 {
421   
422   return PTR_TYPE(SPEC_OCLS(etype));
423   
424 }
425
426 /*-----------------------------------------------------------------*/
427 /* aopForSym - for a true symbol                                   */
428 /*-----------------------------------------------------------------*/
429 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
430 {
431   asmop *aop;
432   memmap *space= SPEC_OCLS(sym->etype);
433   
434   DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
435   /* if already has one */
436   if (sym->aop)
437     return sym->aop;
438   
439   /* assign depending on the storage class */
440   /* if it is on the stack or indirectly addressable */
441   /* space we need to assign either r0 or r1 to it   */    
442   if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
443     sym->aop = aop = newAsmop(0);
444     aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
445     aop->size = getSize(sym->type);
446     
447     /* now assign the address of the variable to 
448     the pointer register */
449     if (aop->type != AOP_STK) {
450       
451       if (sym->onStack) {
452         if ( _G.accInUse )
453           pic14_emitcode("push","acc");
454         
455         pic14_emitcode("mov","a,_bp");
456         pic14_emitcode("add","a,#0x%02x",
457           ((sym->stack < 0) ?
458           ((char)(sym->stack - _G.nRegsSaved )) :
459         ((char)sym->stack)) & 0xff);
460         pic14_emitcode("mov","%s,a",
461           aop->aopu.aop_ptr->name);
462         
463         if ( _G.accInUse )
464           pic14_emitcode("pop","acc");
465       } else
466         pic14_emitcode("mov","%s,#%s",
467         aop->aopu.aop_ptr->name,
468         sym->rname);
469       aop->paged = space->paged;
470     } else
471       aop->aopu.aop_stk = sym->stack;
472     return aop;
473   }
474   
475   if (sym->onStack && options.stack10bit)
476   {
477   /* It's on the 10 bit stack, which is located in
478   * far data space.
479     */
480     
481     //DEBUGpic14_emitcode(";","%d",__LINE__);
482     
483     if ( _G.accInUse )
484       pic14_emitcode("push","acc");
485     
486     pic14_emitcode("mov","a,_bp");
487     pic14_emitcode("add","a,#0x%02x",
488       ((sym->stack < 0) ?
489       ((char)(sym->stack - _G.nRegsSaved )) :
490     ((char)sym->stack)) & 0xff);
491     
492     genSetDPTR(1);
493     pic14_emitcode ("mov","dpx1,#0x40");
494     pic14_emitcode ("mov","dph1,#0x00");
495     pic14_emitcode ("mov","dpl1, a");
496     genSetDPTR(0);
497     
498     if ( _G.accInUse )
499       pic14_emitcode("pop","acc");
500     
501     sym->aop = aop = newAsmop(AOP_DPTR2);
502     aop->size = getSize(sym->type); 
503     return aop;
504   }
505   
506   //DEBUGpic14_emitcode(";","%d",__LINE__);
507   /* if in bit space */
508   if (IN_BITSPACE(space)) {
509     sym->aop = aop = newAsmop (AOP_CRY);
510     aop->aopu.aop_dir = sym->rname ;
511     aop->size = getSize(sym->type);
512     //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
513     return aop;
514   }
515   /* if it is in direct space */
516   if (IN_DIRSPACE(space)) {
517     sym->aop = aop = newAsmop (AOP_DIR);
518     aop->aopu.aop_dir = sym->rname ;
519     aop->size = getSize(sym->type);
520     DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
521     return aop;
522   }
523   
524   /* special case for a function */
525   if (IS_FUNC(sym->type)) {   
526     
527     sym->aop = aop = newAsmop(AOP_PCODE);
528     aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
529     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
530     PCOI(aop->aopu.pcop)->_function = 1;
531     PCOI(aop->aopu.pcop)->index = 0;
532     aop->size = FPTRSIZE; 
533     /*
534     sym->aop = aop = newAsmop(AOP_IMMD);    
535     aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
536     strcpy(aop->aopu.aop_immd,sym->rname);
537     aop->size = FPTRSIZE; 
538     */
539     DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
540     return aop;
541   }
542   
543   
544   /* only remaining is far space */
545   /* in which case DPTR gets the address */
546   sym->aop = aop = newAsmop(AOP_PCODE);
547   
548   aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
549   PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
550   PCOI(aop->aopu.pcop)->index = 0;
551   
552   DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
553     __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
554   
555   allocDirReg (IC_LEFT(ic));
556   
557   aop->size = FPTRSIZE; 
558   /*
559   DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
560   sym->aop = aop = newAsmop(AOP_DPTR);
561   pic14_emitcode ("mov","dptr,#%s", sym->rname);
562   aop->size = getSize(sym->type);
563   
564     DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
565   */
566   
567   /* if it is in code space */
568   if (IN_CODESPACE(space))
569     aop->code = 1;
570   
571   return aop;     
572 }
573
574 /*-----------------------------------------------------------------*/
575 /* aopForRemat - rematerialzes an object                           */
576 /*-----------------------------------------------------------------*/
577 static asmop *aopForRemat (operand *op) // x symbol *sym)
578 {
579   symbol *sym = OP_SYMBOL(op);
580   iCode *ic = NULL;
581   asmop *aop = newAsmop(AOP_PCODE);
582   int val = 0;
583   int offset = 0;
584   
585   ic = sym->rematiCode;
586   
587   DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
588   if(IS_OP_POINTER(op)) {
589     DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
590   }
591   for (;;) {
592     if (ic->op == '+') {
593       val += (int) operandLitValue(IC_RIGHT(ic));
594     } else if (ic->op == '-') {
595       val -= (int) operandLitValue(IC_RIGHT(ic));
596     } else
597       break;
598     
599     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
600   }
601   
602   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
603   aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
604   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
605   PCOI(aop->aopu.pcop)->index = val;
606   
607   DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
608     __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
609     val, IS_PTR_CONST(operandType(op)));
610   
611   //    DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
612   
613   allocDirReg (IC_LEFT(ic));
614   
615   return aop;        
616 }
617
618 int aopIdx (asmop *aop, int offset)
619 {
620   if(!aop)
621     return -1;
622   
623   if(aop->type !=  AOP_REG)
624     return -2;
625   
626   return aop->aopu.aop_reg[offset]->rIdx;
627   
628 }
629 /*-----------------------------------------------------------------*/
630 /* regsInCommon - two operands have some registers in common       */
631 /*-----------------------------------------------------------------*/
632 static bool regsInCommon (operand *op1, operand *op2)
633 {
634   symbol *sym1, *sym2;
635   int i;
636   
637   /* if they have registers in common */
638   if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
639     return FALSE ;
640   
641   sym1 = OP_SYMBOL(op1);
642   sym2 = OP_SYMBOL(op2);
643   
644   if (sym1->nRegs == 0 || sym2->nRegs == 0)
645     return FALSE ;
646   
647   for (i = 0 ; i < sym1->nRegs ; i++) {
648     int j;
649     if (!sym1->regs[i])
650       continue ;
651     
652     for (j = 0 ; j < sym2->nRegs ;j++ ) {
653       if (!sym2->regs[j])
654         continue ;
655       
656       if (sym2->regs[j] == sym1->regs[i])
657         return TRUE ;
658     }
659   }
660   
661   return FALSE ;
662 }
663
664 /*-----------------------------------------------------------------*/
665 /* operandsEqu - equivalent                                        */
666 /*-----------------------------------------------------------------*/
667 static bool operandsEqu ( operand *op1, operand *op2)
668 {
669   symbol *sym1, *sym2;
670   
671   /* if they not symbols */
672   if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
673     return FALSE;
674   
675   sym1 = OP_SYMBOL(op1);
676   sym2 = OP_SYMBOL(op2);
677   
678   /* if both are itemps & one is spilt
679   and the other is not then false */
680   if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
681     sym1->isspilt != sym2->isspilt )
682     return FALSE ;
683   
684   /* if they are the same */
685   if (sym1 == sym2)
686     return TRUE ;
687   
688   if (strcmp(sym1->rname,sym2->rname) == 0)
689     return TRUE;
690   
691   
692   /* if left is a tmp & right is not */
693   if (IS_ITEMP(op1)  && 
694     !IS_ITEMP(op2) &&
695     sym1->isspilt  &&
696     (sym1->usl.spillLoc == sym2))
697     return TRUE;
698   
699   if (IS_ITEMP(op2)  && 
700     !IS_ITEMP(op1) &&
701     sym2->isspilt  &&
702     sym1->level > 0 &&
703     (sym2->usl.spillLoc == sym1))
704     return TRUE ;
705   
706   return FALSE ;
707 }
708
709 /*-----------------------------------------------------------------*/
710 /* pic14_sameRegs - two asmops have the same registers                   */
711 /*-----------------------------------------------------------------*/
712 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
713 {
714   int i;
715   
716   if (aop1 == aop2)
717     return TRUE ;
718   
719   if (aop1->type != AOP_REG ||
720     aop2->type != AOP_REG )
721     return FALSE ;
722   
723   if (aop1->size != aop2->size )
724     return FALSE ;
725   
726   for (i = 0 ; i < aop1->size ; i++ )
727     if (aop1->aopu.aop_reg[i] !=
728       aop2->aopu.aop_reg[i] )
729       return FALSE ;
730     
731     return TRUE ;
732 }
733
734 /*-----------------------------------------------------------------*/
735 /* aopOp - allocates an asmop for an operand  :                    */
736 /*-----------------------------------------------------------------*/
737 void aopOp (operand *op, iCode *ic, bool result)
738 {
739   asmop *aop;
740   symbol *sym;
741   int i;
742   
743   if (!op)
744     return ;
745   
746   //    DEBUGpic14_emitcode(";","%d",__LINE__);
747   /* if this a literal */
748   if (IS_OP_LITERAL(op)) {
749     op->aop = aop = newAsmop(AOP_LIT);
750     aop->aopu.aop_lit = op->operand.valOperand;
751     aop->size = getSize(operandType(op));
752     return;
753   }
754   
755   {
756     sym_link *type = operandType(op);
757     if(IS_PTR_CONST(type))
758       DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
759   }
760   
761   /* if already has a asmop then continue */
762   if (op->aop)
763     return ;
764   
765   /* if the underlying symbol has a aop */
766   if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
767     DEBUGpic14_emitcode(";","%d",__LINE__);
768     op->aop = OP_SYMBOL(op)->aop;
769     return;
770   }
771   
772   /* if this is a true symbol */
773   if (IS_TRUE_SYMOP(op)) {    
774     //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
775     op->aop = aopForSym(ic,OP_SYMBOL(op),result);
776     return ;
777   }
778   
779   /* this is a temporary : this has
780   only four choices :
781   a) register
782   b) spillocation
783   c) rematerialize 
784   d) conditional   
785   e) can be a return use only */
786   
787   sym = OP_SYMBOL(op);
788   
789   
790   /* if the type is a conditional */
791   if (sym->regType == REG_CND) {
792     aop = op->aop = sym->aop = newAsmop(AOP_CRY);
793     aop->size = 0;
794     return;
795   }
796   
797   /* if it is spilt then two situations
798   a) is rematerialize 
799   b) has a spill location */
800   if (sym->isspilt || sym->nRegs == 0) {
801     
802     DEBUGpic14_emitcode(";","%d",__LINE__);
803     /* rematerialize it NOW */
804     if (sym->remat) {
805       
806       sym->aop = op->aop = aop =
807         aopForRemat (op);
808       aop->size = getSize(sym->type);
809       //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
810       return;
811     }
812     
813     if (sym->accuse) {
814       int i;
815       aop = op->aop = sym->aop = newAsmop(AOP_ACC);
816       aop->size = getSize(sym->type);
817       for ( i = 0 ; i < 2 ; i++ )
818         aop->aopu.aop_str[i] = accUse[i];
819       DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
820       return;  
821     }
822     
823     if (sym->ruonly ) {
824       if(sym->isptr) {  // && sym->uptr 
825         aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
826         aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
827         
828         //PCOI(aop->aopu.pcop)->_const = 0;
829         //PCOI(aop->aopu.pcop)->index = 0;
830         /*
831         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
832         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
833         */
834         //allocDirReg (IC_LEFT(ic));
835         
836         aop->size = getSize(sym->type);
837         DEBUGpic14_emitcode(";","%d",__LINE__);
838         return;
839         
840       } else {
841         
842         unsigned i;
843         
844         aop = op->aop = sym->aop = newAsmop(AOP_STR);
845         aop->size = getSize(sym->type);
846         for ( i = 0 ; i < fReturnSizePic ; i++ )
847           aop->aopu.aop_str[i] = fReturn[i];
848         
849         DEBUGpic14_emitcode(";","%d",__LINE__);
850         return;
851       }
852     }
853     
854     /* else spill location  */
855     if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
856       /* force a new aop if sizes differ */
857       sym->usl.spillLoc->aop = NULL;
858     }
859     DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
860       __FUNCTION__,__LINE__,
861       sym->usl.spillLoc->rname,
862       sym->rname, sym->usl.spillLoc->offset);
863     
864     sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
865     //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
866     aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
867       getSize(sym->type), 
868       sym->usl.spillLoc->offset);
869     aop->size = getSize(sym->type);
870     
871     return;
872   }
873   
874   {
875     sym_link *type = operandType(op);
876     if(IS_PTR_CONST(type)) 
877       DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
878   }
879   
880   /* must be in a register */
881   DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
882   sym->aop = op->aop = aop = newAsmop(AOP_REG);
883   aop->size = sym->nRegs;
884   for ( i = 0 ; i < sym->nRegs ;i++)
885     aop->aopu.aop_reg[i] = sym->regs[i];
886 }
887
888 /*-----------------------------------------------------------------*/
889 /* freeAsmop - free up the asmop given to an operand               */
890 /*----------------------------------------------------------------*/
891 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
892 {   
893   asmop *aop ;
894   
895   if (!op)
896     aop = aaop;
897   else 
898     aop = op->aop;
899   
900   if (!aop)
901     return ;
902   
903   if (aop->freed)
904     goto dealloc; 
905   
906   aop->freed = 1;
907   
908   /* depending on the asmop type only three cases need work AOP_RO
909   , AOP_R1 && AOP_STK */
910 #if 0
911   switch (aop->type) {
912   case AOP_R0 :
913     if (_G.r0Pushed ) {
914       if (pop) {
915         pic14_emitcode ("pop","ar0");     
916         _G.r0Pushed--;
917       }
918     }
919     bitVectUnSetBit(ic->rUsed,R0_IDX);
920     break;
921     
922   case AOP_R1 :
923     if (_G.r1Pushed ) {
924       if (pop) {
925         pic14_emitcode ("pop","ar1");
926         _G.r1Pushed--;
927       }
928     }
929     bitVectUnSetBit(ic->rUsed,R1_IDX);          
930     break;
931     
932   case AOP_STK :
933     {
934       int sz = aop->size;    
935       int stk = aop->aopu.aop_stk + aop->size;
936       bitVectUnSetBit(ic->rUsed,R0_IDX);
937       bitVectUnSetBit(ic->rUsed,R1_IDX);          
938       
939       getFreePtr(ic,&aop,FALSE);
940       
941       if (options.stack10bit)
942       {
943         /* I'm not sure what to do here yet... */
944         /* #STUB */
945         fprintf(stderr, 
946           "*** Warning: probably generating bad code for "
947           "10 bit stack mode.\n");
948       }
949       
950       if (stk) {
951         pic14_emitcode ("mov","a,_bp");
952         pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
953         pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
954       } else {
955         pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
956       }
957       
958       while (sz--) {
959         pic14_emitcode("pop","acc");
960         pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
961         if (!sz) break;
962         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
963       }
964       op->aop = aop;
965       freeAsmop(op,NULL,ic,TRUE);
966       if (_G.r0Pushed) {
967         pic14_emitcode("pop","ar0");
968         _G.r0Pushed--;
969       }
970       
971       if (_G.r1Pushed) {
972         pic14_emitcode("pop","ar1");
973         _G.r1Pushed--;
974       }       
975     }
976   }
977 #endif
978   
979 dealloc:
980   /* all other cases just dealloc */
981   if (op ) {
982     op->aop = NULL;
983     if (IS_SYMOP(op)) {
984       OP_SYMBOL(op)->aop = NULL;    
985       /* if the symbol has a spill */
986       if (SPIL_LOC(op))
987         SPIL_LOC(op)->aop = NULL;
988     }
989   }
990 }
991
992 /*-----------------------------------------------------------------*/
993 /* aopGet - for fetching value of the aop                          */
994 /*-----------------------------------------------------------------*/
995 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
996 {
997   char *s = buffer ;
998   char *rs;
999   
1000   //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1001   /* offset is greater than
1002   size then zero */
1003   if (offset > (aop->size - 1) &&
1004     aop->type != AOP_LIT)
1005     return zero;
1006   
1007   /* depending on type */
1008   switch (aop->type) {
1009     
1010   case AOP_R0:
1011   case AOP_R1:
1012     DEBUGpic14_emitcode(";","%d",__LINE__);
1013     /* if we need to increment it */       
1014     while (offset > aop->coff) {        
1015       pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1016       aop->coff++;
1017     }
1018     
1019     while (offset < aop->coff) {
1020       pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1021       aop->coff--;
1022     }
1023     
1024     aop->coff = offset ;
1025     if (aop->paged) {
1026       pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1027       return (dname ? "acc" : "a");
1028     }       
1029     sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1030     rs = Safe_calloc(1,strlen(s)+1);
1031     strcpy(rs,s);   
1032     return rs;
1033     
1034   case AOP_DPTR:
1035   case AOP_DPTR2:
1036     DEBUGpic14_emitcode(";","%d",__LINE__);
1037     if (aop->type == AOP_DPTR2)
1038     {
1039       genSetDPTR(1);
1040     }
1041     
1042     while (offset > aop->coff) {
1043       pic14_emitcode ("inc","dptr");
1044       aop->coff++;
1045     }
1046     
1047     while (offset < aop->coff) {        
1048       pic14_emitcode("lcall","__decdptr");
1049       aop->coff--;
1050     }
1051     
1052     aop->coff = offset;
1053     if (aop->code) {
1054       pic14_emitcode("clr","a");
1055       pic14_emitcode("movc","a,@a+dptr");
1056     }
1057     else {
1058       pic14_emitcode("movx","a,@dptr");
1059     }
1060     
1061     if (aop->type == AOP_DPTR2)
1062     {
1063       genSetDPTR(0);
1064     }
1065     
1066     return (dname ? "acc" : "a");
1067     
1068     
1069   case AOP_IMMD:
1070     if (bit16) 
1071       sprintf (s,"%s",aop->aopu.aop_immd);
1072     else
1073       if (offset) 
1074         sprintf(s,"(%s >> %d)",
1075         aop->aopu.aop_immd,
1076         offset*8);
1077       else
1078         sprintf(s,"%s",
1079         aop->aopu.aop_immd);
1080       DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1081       rs = Safe_calloc(1,strlen(s)+1);
1082       strcpy(rs,s);   
1083       return rs;
1084       
1085   case AOP_DIR:
1086     if (offset) {
1087       sprintf(s,"(%s + %d)",
1088         aop->aopu.aop_dir,
1089         offset);
1090       DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1091     } else
1092       sprintf(s,"%s",aop->aopu.aop_dir);
1093     rs = Safe_calloc(1,strlen(s)+1);
1094     strcpy(rs,s);   
1095     return rs;
1096     
1097   case AOP_REG:
1098     //if (dname) 
1099     //    return aop->aopu.aop_reg[offset]->dname;
1100     //else
1101     return aop->aopu.aop_reg[offset]->name;
1102     
1103   case AOP_CRY:
1104     //pic14_emitcode(";","%d",__LINE__);
1105     return aop->aopu.aop_dir;
1106     
1107   case AOP_ACC:
1108     DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1109     return "AOP_accumulator_bug";
1110     
1111   case AOP_LIT:
1112     sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1113     rs = Safe_calloc(1,strlen(s)+1);
1114     strcpy(rs,s);   
1115     return rs;
1116     
1117   case AOP_STR:
1118     aop->coff = offset ;
1119     if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1120       dname)
1121       return "acc";
1122     DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1123     
1124     return aop->aopu.aop_str[offset];
1125     
1126   case AOP_PCODE:
1127     {
1128       pCodeOp *pcop = aop->aopu.pcop;
1129       DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1130       if(pcop->name) {
1131         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1132         //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1133         sprintf(s,"%s", pcop->name);
1134       } else
1135         sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1136       
1137     }
1138     rs = Safe_calloc(1,strlen(s)+1);
1139     strcpy(rs,s);   
1140     return rs;
1141     
1142   }
1143   
1144   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1145     "aopget got unsupported aop->type");
1146   exit(0);
1147 }
1148
1149
1150 /*-----------------------------------------------------------------*/
1151 /* popGetTempReg - create a new temporary pCodeOp                  */
1152 /*-----------------------------------------------------------------*/
1153 pCodeOp *popGetTempReg(void)
1154 {
1155   
1156   pCodeOp *pcop;
1157   
1158   pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1159   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1160     PCOR(pcop)->r->wasUsed=1;
1161     PCOR(pcop)->r->isFree=0;
1162   }
1163   
1164   return pcop;
1165 }
1166
1167 /*-----------------------------------------------------------------*/
1168 /* popGetTempReg - create a new temporary pCodeOp                  */
1169 /*-----------------------------------------------------------------*/
1170 void popReleaseTempReg(pCodeOp *pcop)
1171 {
1172   
1173   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1174     PCOR(pcop)->r->isFree = 1;
1175   
1176 }
1177 /*-----------------------------------------------------------------*/
1178 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1179 /*-----------------------------------------------------------------*/
1180 pCodeOp *popGetLabel(unsigned int key)
1181 {
1182   
1183   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1184   
1185   if(key>(unsigned int)max_key)
1186     max_key = key;
1187   
1188   return newpCodeOpLabel(NULL,key+100+labelOffset);
1189 }
1190
1191 /*-------------------------------------------------------------------*/
1192 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1193 /*-------------------------------------------------------------------*/
1194 pCodeOp *popGetHighLabel(unsigned int key)
1195 {
1196   pCodeOp *pcop;
1197   pcop = popGetLabel(key);
1198   PCOLAB(pcop)->offset = 1;
1199   return pcop;
1200 }
1201
1202 /*-----------------------------------------------------------------*/
1203 /* popGet - asm operator to pcode operator conversion              */
1204 /*-----------------------------------------------------------------*/
1205 pCodeOp *popGetLit(unsigned int lit)
1206 {
1207   
1208   return newpCodeOpLit(lit);
1209 }
1210
1211 /*-----------------------------------------------------------------*/
1212 /* popGetImmd - asm operator to pcode immediate conversion         */
1213 /*-----------------------------------------------------------------*/
1214 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1215 {
1216   
1217   return newpCodeOpImmd(name, offset,index, 0, is_func);
1218 }
1219
1220
1221 /*-----------------------------------------------------------------*/
1222 /* popGet - asm operator to pcode operator conversion              */
1223 /*-----------------------------------------------------------------*/
1224 pCodeOp *popGetWithString(char *str, int isExtern)
1225 {
1226   pCodeOp *pcop;
1227   
1228   
1229   if(!str) {
1230     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1231     exit (1);
1232   }
1233   
1234   pcop = newpCodeOp(str,PO_STR);
1235   PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1236   
1237   return pcop;
1238 }
1239
1240 /*-----------------------------------------------------------------*/
1241 /* popRegFromString -                                              */
1242 /*-----------------------------------------------------------------*/
1243 pCodeOp *popRegFromString(char *str, int size, int offset)
1244 {
1245   
1246   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1247   pcop->type = PO_DIR;
1248   
1249   DEBUGpic14_emitcode(";","%d",__LINE__);
1250   
1251   if(!str)
1252     str = "BAD_STRING";
1253   
1254   pcop->name = Safe_calloc(1,strlen(str)+1);
1255   strcpy(pcop->name,str);
1256   
1257   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1258   
1259   PCOR(pcop)->r = dirregWithName(pcop->name);
1260   if(PCOR(pcop)->r == NULL) {
1261     //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1262     PCOR(pcop)->r = allocRegByName (pcop->name,size);
1263     DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1264   } else {
1265     DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1266   }
1267   PCOR(pcop)->instance = offset;
1268   
1269   return pcop;
1270 }
1271
1272 /*-----------------------------------------------------------------*/
1273 /*-----------------------------------------------------------------*/
1274 pCodeOp *popRegFromIdx(int rIdx)
1275 {
1276   pCodeOp *pcop;
1277   
1278   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1279     __FUNCTION__,__LINE__,rIdx);
1280   
1281   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1282   
1283   PCOR(pcop)->rIdx = rIdx;
1284   PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1285   PCOR(pcop)->r->isFree = 0;
1286   PCOR(pcop)->r->wasUsed = 1;
1287   
1288   pcop->type = PCOR(pcop)->r->pc_type;
1289   
1290   
1291   return pcop;
1292 }
1293
1294 /*-----------------------------------------------------------------*/
1295 /* popGet - asm operator to pcode operator conversion              */
1296 /*-----------------------------------------------------------------*/
1297 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1298 {
1299   //char *s = buffer ;
1300   //char *rs;
1301   
1302   pCodeOp *pcop;
1303   
1304   //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1305   /* offset is greater than
1306   size then zero */
1307   
1308   if (offset > (aop->size - 1) &&
1309     aop->type != AOP_LIT)
1310     return NULL;  //zero;
1311   
1312   /* depending on type */
1313   switch (aop->type) {
1314     
1315   case AOP_R0:
1316   case AOP_R1:
1317   case AOP_DPTR:
1318   case AOP_DPTR2:
1319   case AOP_ACC:
1320     DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1321     return NULL;
1322     
1323   case AOP_IMMD:
1324     DEBUGpic14_emitcode(";","%d",__LINE__);
1325     return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1326     
1327   case AOP_DIR:
1328     return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1329 #if 0
1330     pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1331     pcop->type = PO_DIR;
1332     
1333     /*
1334     if (offset)
1335     sprintf(s,"(%s + %d)",
1336     aop->aopu.aop_dir,
1337     offset);
1338     else
1339     sprintf(s,"%s",aop->aopu.aop_dir);
1340     pcop->name = Safe_calloc(1,strlen(s)+1);
1341     strcpy(pcop->name,s);   
1342     */
1343     pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1344     strcpy(pcop->name,aop->aopu.aop_dir);   
1345     PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1346     if(PCOR(pcop)->r == NULL) {
1347       //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1348       PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1349       DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1350     } else {
1351       DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1352     }
1353     PCOR(pcop)->instance = offset;
1354     
1355     return pcop;
1356 #endif
1357     
1358   case AOP_REG:
1359     {
1360       int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1361       
1362       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1363       PCOR(pcop)->rIdx = rIdx;
1364       PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1365       PCOR(pcop)->r->wasUsed=1;
1366       PCOR(pcop)->r->isFree=0;
1367       
1368       PCOR(pcop)->instance = offset;
1369       pcop->type = PCOR(pcop)->r->pc_type;
1370       //rs = aop->aopu.aop_reg[offset]->name;
1371       DEBUGpic14_emitcode(";","%d regiser idx = %d ",__LINE__,rIdx);
1372       return pcop;
1373     }
1374     
1375   case AOP_CRY:
1376     pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1377     PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1378     //if(PCOR(pcop)->r == NULL)
1379     //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1380     return pcop;
1381     
1382   case AOP_LIT:
1383     return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1384     
1385   case AOP_STR:
1386     DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1387     return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1388     /*
1389     pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1390     PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1391     PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1392     pcop->type = PCOR(pcop)->r->pc_type;
1393     pcop->name = PCOR(pcop)->r->name;
1394     
1395       return pcop;
1396     */
1397     
1398   case AOP_PCODE:
1399     DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s) %d %s",pCodeOpType(aop->aopu.pcop),
1400       __LINE__, 
1401       ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1402     pcop = pCodeOpCopy(aop->aopu.pcop);
1403     PCOI(pcop)->offset = offset;
1404     return pcop;
1405   }
1406   
1407   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1408     "popGet got unsupported aop->type");
1409   exit(0);
1410 }
1411 /*-----------------------------------------------------------------*/
1412 /* aopPut - puts a string for a aop                                */
1413 /*-----------------------------------------------------------------*/
1414 void aopPut (asmop *aop, char *s, int offset)
1415 {
1416   char *d = buffer ;
1417   symbol *lbl ;
1418   
1419   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1420   
1421   if (aop->size && offset > ( aop->size - 1)) {
1422     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1423       "aopPut got offset > aop->size");
1424     exit(0);
1425   }
1426   
1427   /* will assign value to value */
1428   /* depending on where it is ofcourse */
1429   switch (aop->type) {
1430   case AOP_DIR:
1431     if (offset) {
1432       sprintf(d,"(%s + %d)",
1433         aop->aopu.aop_dir,offset);
1434       fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1435       
1436     } else
1437       sprintf(d,"%s",aop->aopu.aop_dir);
1438     
1439     if (strcmp(d,s)) {
1440       DEBUGpic14_emitcode(";","%d",__LINE__);
1441       if(strcmp(s,"W"))
1442         pic14_emitcode("movf","%s,w",s);
1443       pic14_emitcode("movwf","%s",d);
1444       
1445       if(strcmp(s,"W")) {
1446         pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1447         if(offset >= aop->size) {
1448           emitpcode(POC_CLRF,popGet(aop,offset));
1449           break;
1450         } else
1451           emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1452       }
1453       
1454       emitpcode(POC_MOVWF,popGet(aop,offset));
1455       
1456       
1457     }
1458     break;
1459     
1460   case AOP_REG:
1461     if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1462       //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1463       /*
1464       if (*s == '@'           ||
1465       strcmp(s,"r0") == 0 ||
1466       strcmp(s,"r1") == 0 ||
1467       strcmp(s,"r2") == 0 ||
1468       strcmp(s,"r3") == 0 ||
1469       strcmp(s,"r4") == 0 ||
1470       strcmp(s,"r5") == 0 ||
1471       strcmp(s,"r6") == 0 || 
1472       strcmp(s,"r7") == 0 )
1473       pic14_emitcode("mov","%s,%s  ; %d",
1474       aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1475       else
1476       */
1477       
1478       if(strcmp(s,"W")==0 )
1479         pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1480       
1481       pic14_emitcode("movwf","%s",
1482         aop->aopu.aop_reg[offset]->name);
1483       
1484       if(strcmp(s,zero)==0) {
1485         emitpcode(POC_CLRF,popGet(aop,offset));
1486         
1487       } else if(strcmp(s,"W")==0) {
1488         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1489         pcop->type = PO_GPR_REGISTER;
1490         
1491         PCOR(pcop)->rIdx = -1;
1492         PCOR(pcop)->r = NULL;
1493         
1494         DEBUGpic14_emitcode(";","%d",__LINE__);
1495         pcop->name = Safe_strdup(s);
1496         emitpcode(POC_MOVFW,pcop);
1497         emitpcode(POC_MOVWF,popGet(aop,offset));
1498       } else if(strcmp(s,one)==0) {
1499         emitpcode(POC_CLRF,popGet(aop,offset));
1500         emitpcode(POC_INCF,popGet(aop,offset));
1501       } else {
1502         emitpcode(POC_MOVWF,popGet(aop,offset));
1503       }
1504     }
1505     break;
1506     
1507   case AOP_DPTR:
1508   case AOP_DPTR2:
1509     
1510     if (aop->type == AOP_DPTR2)
1511     {
1512       genSetDPTR(1);
1513     }
1514     
1515     if (aop->code) {
1516       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1517         "aopPut writting to code space");
1518       exit(0);
1519     }
1520     
1521     while (offset > aop->coff) {
1522       aop->coff++;
1523       pic14_emitcode ("inc","dptr");
1524     }
1525     
1526     while (offset < aop->coff) {
1527       aop->coff-- ;
1528       pic14_emitcode("lcall","__decdptr");
1529     }
1530     
1531     aop->coff = offset;
1532     
1533     /* if not in accumulater */
1534     MOVA(s);
1535     
1536     pic14_emitcode ("movx","@dptr,a");
1537     
1538     if (aop->type == AOP_DPTR2)
1539     {
1540       genSetDPTR(0);
1541     }
1542     break;
1543     
1544   case AOP_R0:
1545   case AOP_R1:
1546     while (offset > aop->coff) {
1547       aop->coff++;
1548       pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1549     }
1550     while (offset < aop->coff) {
1551       aop->coff-- ;
1552       pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1553     }
1554     aop->coff = offset;
1555     
1556     if (aop->paged) {
1557       MOVA(s);           
1558       pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1559       
1560     } else
1561       if (*s == '@') {
1562         MOVA(s);
1563         pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1564       } else
1565         if (strcmp(s,"r0") == 0 ||
1566           strcmp(s,"r1") == 0 ||
1567           strcmp(s,"r2") == 0 ||
1568           strcmp(s,"r3") == 0 ||
1569           strcmp(s,"r4") == 0 ||
1570           strcmp(s,"r5") == 0 ||
1571           strcmp(s,"r6") == 0 || 
1572           strcmp(s,"r7") == 0 ) {
1573           char buffer[10];
1574           sprintf(buffer,"a%s",s);
1575           pic14_emitcode("mov","@%s,%s",
1576             aop->aopu.aop_ptr->name,buffer);
1577         } else
1578           pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1579         
1580         break;
1581         
1582   case AOP_STK:
1583     if (strcmp(s,"a") == 0)
1584       pic14_emitcode("push","acc");
1585     else
1586       pic14_emitcode("push","%s",s);
1587     
1588     break;
1589     
1590   case AOP_CRY:
1591     /* if bit variable */
1592     if (!aop->aopu.aop_dir) {
1593       pic14_emitcode("clr","a");
1594       pic14_emitcode("rlc","a");
1595     } else {
1596       if (s == zero) 
1597         pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1598       else
1599         if (s == one)
1600           pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1601         else
1602           if (!strcmp(s,"c"))
1603             pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1604           else {
1605             lbl = newiTempLabel(NULL);
1606             
1607             if (strcmp(s,"a")) {
1608               MOVA(s);
1609             }
1610             pic14_emitcode("clr","c");
1611             pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1612             pic14_emitcode("cpl","c");
1613             pic14_emitcode("","%05d_DS_:",lbl->key+100);
1614             pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1615           }
1616     }
1617     break;
1618     
1619   case AOP_STR:
1620     aop->coff = offset;
1621     if (strcmp(aop->aopu.aop_str[offset],s))
1622       pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1623     break;
1624     
1625   case AOP_ACC:
1626     aop->coff = offset;
1627     if (!offset && (strcmp(s,"acc") == 0))
1628       break;
1629     
1630     if (strcmp(aop->aopu.aop_str[offset],s))
1631       pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1632     break;
1633     
1634   default :
1635     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1636       "aopPut got unsupported aop->type");
1637     exit(0);    
1638   }    
1639   
1640 }
1641
1642 /*-----------------------------------------------------------------*/
1643 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1644 /*-----------------------------------------------------------------*/
1645 void mov2w (asmop *aop, int offset)
1646 {
1647   
1648   if(!aop)
1649     return;
1650   
1651   DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1652   
1653   if ( aop->type == AOP_PCODE ||
1654     aop->type == AOP_LIT ||
1655     aop->type == AOP_IMMD )
1656     emitpcode(POC_MOVLW,popGet(aop,offset));
1657   else
1658     emitpcode(POC_MOVFW,popGet(aop,offset));
1659   
1660 }
1661
1662 /*-----------------------------------------------------------------*/
1663 /* reAdjustPreg - points a register back to where it should        */
1664 /*-----------------------------------------------------------------*/
1665 static void reAdjustPreg (asmop *aop)
1666 {
1667   int size ;
1668   
1669   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1670   aop->coff = 0;
1671   if ((size = aop->size) <= 1)
1672     return ;
1673   size-- ;
1674   switch (aop->type) {
1675   case AOP_R0 :
1676   case AOP_R1 :
1677     while (size--)
1678       pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1679     break;          
1680   case AOP_DPTR :
1681   case AOP_DPTR2:
1682     if (aop->type == AOP_DPTR2)
1683     {
1684       genSetDPTR(1);
1685     } 
1686     while (size--)
1687     {
1688       pic14_emitcode("lcall","__decdptr");
1689     }
1690     
1691     if (aop->type == AOP_DPTR2)
1692     {
1693       genSetDPTR(0);
1694     }
1695     break;
1696     
1697   }
1698   
1699 }
1700
1701
1702 #if 0
1703 /*-----------------------------------------------------------------*/
1704 /* opIsGptr: returns non-zero if the passed operand is       */   
1705 /* a generic pointer type.             */
1706 /*-----------------------------------------------------------------*/ 
1707 static int opIsGptr(operand *op)
1708 {
1709   sym_link *type = operandType(op);
1710   
1711   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1712   if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1713   {
1714     return 1;
1715   }
1716   return 0;        
1717 }
1718 #endif
1719
1720 /*-----------------------------------------------------------------*/
1721 /* pic14_getDataSize - get the operand data size                         */
1722 /*-----------------------------------------------------------------*/
1723 int pic14_getDataSize(operand *op)
1724 {
1725   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1726   
1727   
1728   return AOP_SIZE(op);
1729   
1730   // tsd- in the pic port, the genptr size is 1, so this code here
1731   // fails. ( in the 8051 port, the size was 4).
1732 #if 0
1733   int size;
1734   size = AOP_SIZE(op);
1735   if (size == GPTRSIZE)
1736   {
1737     sym_link *type = operandType(op);
1738     if (IS_GENPTR(type))
1739     {
1740     /* generic pointer; arithmetic operations
1741     * should ignore the high byte (pointer type).
1742       */
1743       size--;
1744       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1745     }
1746   }
1747   return size;
1748 #endif
1749 }
1750
1751 /*-----------------------------------------------------------------*/
1752 /* pic14_outAcc - output Acc                                             */
1753 /*-----------------------------------------------------------------*/
1754 void pic14_outAcc(operand *result)
1755 {
1756   int size,offset;
1757   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1758   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1759   
1760   
1761   size = pic14_getDataSize(result);
1762   if(size){
1763     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1764     size--;
1765     offset = 1;
1766     /* unsigned or positive */
1767     while(size--)
1768       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1769   }
1770   
1771 }
1772
1773 /*-----------------------------------------------------------------*/
1774 /* pic14_outBitC - output a bit C                                        */
1775 /*-----------------------------------------------------------------*/
1776 void pic14_outBitC(operand *result)
1777 {
1778   
1779   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1780   /* if the result is bit */
1781   if (AOP_TYPE(result) == AOP_CRY) 
1782     aopPut(AOP(result),"c",0);
1783   else {
1784     pic14_emitcode("clr","a  ; %d", __LINE__);
1785     pic14_emitcode("rlc","a");
1786     pic14_outAcc(result);
1787   }
1788 }
1789
1790 /*-----------------------------------------------------------------*/
1791 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1792 /*-----------------------------------------------------------------*/
1793 void pic14_toBoolean(operand *oper)
1794 {
1795   int size = AOP_SIZE(oper) - 1;
1796   int offset = 1;
1797   
1798   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1799   
1800   if ( AOP_TYPE(oper) != AOP_ACC) {
1801     emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1802   }
1803   while (size--) {
1804     emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1805   }
1806 }
1807
1808
1809 /*-----------------------------------------------------------------*/
1810 /* genNot - generate code for ! operation                          */
1811 /*-----------------------------------------------------------------*/
1812 static void genNot (iCode *ic)
1813 {
1814   symbol *tlbl;
1815   int size;
1816   
1817   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1818   /* assign asmOps to operand & result */
1819   aopOp (IC_LEFT(ic),ic,FALSE);
1820   aopOp (IC_RESULT(ic),ic,TRUE);
1821   
1822   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1823   /* if in bit space then a special case */
1824   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1825     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1826       emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1827       emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1828     } else {
1829       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1830       emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1831       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1832     }
1833     goto release;
1834   }
1835   
1836   size = AOP_SIZE(IC_LEFT(ic));
1837   if(size == 1) {
1838     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1839     emitpcode(POC_ANDLW,popGetLit(1));
1840     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1841     goto release;
1842   }
1843   pic14_toBoolean(IC_LEFT(ic));
1844   
1845   tlbl = newiTempLabel(NULL);
1846   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1847   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1848   pic14_outBitC(IC_RESULT(ic));
1849   
1850 release:    
1851   /* release the aops */
1852   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1853   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1854 }
1855
1856
1857 /*-----------------------------------------------------------------*/
1858 /* genCpl - generate code for complement                           */
1859 /*-----------------------------------------------------------------*/
1860 static void genCpl (iCode *ic)
1861 {
1862   operand *left, *result;
1863   int size, offset=0;  
1864   
1865   
1866   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1867   aopOp((left = IC_LEFT(ic)),ic,FALSE);
1868   aopOp((result=IC_RESULT(ic)),ic,TRUE);
1869   
1870   /* if both are in bit space then 
1871   a special case */
1872   if (AOP_TYPE(result) == AOP_CRY &&
1873     AOP_TYPE(left) == AOP_CRY ) { 
1874     
1875     pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
1876     pic14_emitcode("cpl","c"); 
1877     pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
1878     goto release; 
1879   } 
1880   
1881   size = AOP_SIZE(result);
1882   while (size--) {
1883     
1884     if(AOP_TYPE(left) == AOP_ACC) 
1885       emitpcode(POC_XORLW, popGetLit(0xff));
1886     else
1887       emitpcode(POC_COMFW,popGet(AOP(left),offset));
1888     
1889     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1890     offset++;
1891   }
1892   
1893   
1894 release:
1895   /* release the aops */
1896   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1897   freeAsmop(result,NULL,ic,TRUE);
1898 }
1899
1900 /*-----------------------------------------------------------------*/
1901 /* genUminusFloat - unary minus for floating points                */
1902 /*-----------------------------------------------------------------*/
1903 static void genUminusFloat(operand *op,operand *result)
1904 {
1905   int size ,offset =0 ;
1906   char *l;
1907   
1908   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1909   /* for this we just need to flip the 
1910   first it then copy the rest in place */
1911   size = AOP_SIZE(op) - 1;
1912   l = aopGet(AOP(op),3,FALSE,FALSE);
1913   
1914   MOVA(l);    
1915   
1916   pic14_emitcode("cpl","acc.7");
1917   aopPut(AOP(result),"a",3);    
1918   
1919   while(size--) {
1920     aopPut(AOP(result),
1921       aopGet(AOP(op),offset,FALSE,FALSE),
1922       offset);
1923     offset++;
1924   }          
1925 }
1926
1927 /*-----------------------------------------------------------------*/
1928 /* genUminus - unary minus code generation                         */
1929 /*-----------------------------------------------------------------*/
1930 static void genUminus (iCode *ic)
1931 {
1932   int size, i;
1933   sym_link *optype, *rtype;
1934   
1935   
1936   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1937   /* assign asmops */
1938   aopOp(IC_LEFT(ic),ic,FALSE);
1939   aopOp(IC_RESULT(ic),ic,TRUE);
1940   
1941   /* if both in bit space then special
1942   case */
1943   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1944     AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1945     
1946     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1947     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1948     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1949     
1950     goto release; 
1951   } 
1952   
1953   optype = operandType(IC_LEFT(ic));
1954   rtype = operandType(IC_RESULT(ic));
1955   
1956   /* if float then do float stuff */
1957   if (IS_FLOAT(optype)) {
1958     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1959     goto release;
1960   }
1961   
1962   /* otherwise subtract from zero by taking the 2's complement */
1963   size = AOP_SIZE(IC_LEFT(ic));
1964   
1965   for(i=0; i<size; i++) {
1966     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1967       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1968     else {
1969       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1970       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1971     }
1972   }
1973   
1974   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
1975   for(i=1; i<size; i++) {
1976     emitSKPNZ;
1977     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
1978   }
1979   
1980 release:
1981   /* release the aops */
1982   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1983   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1984 }
1985
1986 /*-----------------------------------------------------------------*/
1987 /* saveRegisters - will look for a call and save the registers     */
1988 /*-----------------------------------------------------------------*/
1989 static void saveRegisters(iCode *lic) 
1990 {
1991   int i;
1992   iCode *ic;
1993   bitVect *rsave;
1994   sym_link *dtype;
1995   
1996   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1997   /* look for call */
1998   for (ic = lic ; ic ; ic = ic->next) 
1999     if (ic->op == CALL || ic->op == PCALL)
2000       break;
2001     
2002     if (!ic) {
2003       fprintf(stderr,"found parameter push with no function call\n");
2004       return ;
2005     }
2006     
2007     /* if the registers have been saved already then
2008     do nothing */
2009     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2010       return ;
2011     
2012       /* find the registers in use at this time 
2013     and push them away to safety */
2014     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2015       ic->rUsed);
2016     
2017     ic->regsSaved = 1;
2018     if (options.useXstack) {
2019       if (bitVectBitValue(rsave,R0_IDX))
2020         pic14_emitcode("mov","b,r0");
2021       pic14_emitcode("mov","r0,%s",spname);
2022       for (i = 0 ; i < pic14_nRegs ; i++) {
2023         if (bitVectBitValue(rsave,i)) {
2024           if (i == R0_IDX)
2025             pic14_emitcode("mov","a,b");
2026           else
2027             pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2028           pic14_emitcode("movx","@r0,a");
2029           pic14_emitcode("inc","r0");
2030         }
2031       }
2032       pic14_emitcode("mov","%s,r0",spname);
2033       if (bitVectBitValue(rsave,R0_IDX))
2034         pic14_emitcode("mov","r0,b");     
2035     }// else
2036     //for (i = 0 ; i < pic14_nRegs ; i++) {
2037     //    if (bitVectBitValue(rsave,i))
2038     //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2039     //}
2040     
2041     dtype = operandType(IC_LEFT(ic));
2042     if (currFunc && dtype && 
2043       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2044       IFFUNC_ISISR(currFunc->type) &&
2045       !ic->bankSaved) 
2046       
2047       saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2048     
2049 }
2050 /*-----------------------------------------------------------------*/
2051 /* unsaveRegisters - pop the pushed registers                      */
2052 /*-----------------------------------------------------------------*/
2053 static void unsaveRegisters (iCode *ic)
2054 {
2055   int i;
2056   bitVect *rsave;
2057   
2058   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2059   /* find the registers in use at this time 
2060   and push them away to safety */
2061   rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2062     ic->rUsed);
2063   
2064   if (options.useXstack) {
2065     pic14_emitcode("mov","r0,%s",spname); 
2066     for (i =  pic14_nRegs ; i >= 0 ; i--) {
2067       if (bitVectBitValue(rsave,i)) {
2068         pic14_emitcode("dec","r0");
2069         pic14_emitcode("movx","a,@r0");
2070         if (i == R0_IDX)
2071           pic14_emitcode("mov","b,a");
2072         else
2073           pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2074       }     
2075       
2076     }
2077     pic14_emitcode("mov","%s,r0",spname);
2078     if (bitVectBitValue(rsave,R0_IDX))
2079       pic14_emitcode("mov","r0,b");
2080   } //else
2081   //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2082   //    if (bitVectBitValue(rsave,i))
2083   //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2084   //}
2085   
2086 }  
2087
2088
2089 /*-----------------------------------------------------------------*/
2090 /* pushSide -                */
2091 /*-----------------------------------------------------------------*/
2092 static void pushSide(operand * oper, int size)
2093 {
2094 #if 0
2095   int offset = 0;
2096   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2097   while (size--) {
2098     char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2099     if (AOP_TYPE(oper) != AOP_REG &&
2100       AOP_TYPE(oper) != AOP_DIR &&
2101       strcmp(l,"a") ) {
2102       pic14_emitcode("mov","a,%s",l);
2103       pic14_emitcode("push","acc");
2104     } else
2105       pic14_emitcode("push","%s",l);
2106   }
2107 #endif
2108 }
2109
2110 /*-----------------------------------------------------------------*/
2111 /* assignResultValue -               */
2112 /*-----------------------------------------------------------------*/
2113 static void assignResultValue(operand * oper)
2114 {
2115   int size = AOP_SIZE(oper);
2116   
2117   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2118   
2119   DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2120   
2121   while (size--) {
2122     if (GpsuedoStkPtr++)
2123       emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2124     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2125   }
2126 }
2127
2128
2129 /*-----------------------------------------------------------------*/
2130 /* genIpush - genrate code for pushing this gets a little complex  */
2131 /*-----------------------------------------------------------------*/
2132 static void genIpush (iCode *ic)
2133 {
2134   
2135   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2136 #if 0
2137   int size, offset = 0 ;
2138   char *l;
2139   
2140   
2141   /* if this is not a parm push : ie. it is spill push 
2142   and spill push is always done on the local stack */
2143   if (!ic->parmPush) {
2144     
2145     /* and the item is spilt then do nothing */
2146     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2147       return ;
2148     
2149     aopOp(IC_LEFT(ic),ic,FALSE);
2150     size = AOP_SIZE(IC_LEFT(ic));
2151     /* push it on the stack */
2152     while(size--) {
2153       l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2154       if (*l == '#') {
2155         MOVA(l);
2156         l = "acc";
2157       }
2158       pic14_emitcode("push","%s",l);
2159     }
2160     return ;        
2161   }
2162   
2163   /* this is a paramter push: in this case we call
2164   the routine to find the call and save those
2165   registers that need to be saved */   
2166   saveRegisters(ic);
2167   
2168   /* then do the push */
2169   aopOp(IC_LEFT(ic),ic,FALSE);
2170   
2171   
2172   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2173   size = AOP_SIZE(IC_LEFT(ic));
2174   
2175   while (size--) {
2176     l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2177     if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2178       AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2179       strcmp(l,"a") ) {
2180       pic14_emitcode("mov","a,%s",l);
2181       pic14_emitcode("push","acc");
2182     } else
2183       pic14_emitcode("push","%s",l);
2184   }       
2185   
2186   freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2187 #endif
2188 }
2189
2190 /*-----------------------------------------------------------------*/
2191 /* genIpop - recover the registers: can happen only for spilling   */
2192 /*-----------------------------------------------------------------*/
2193 static void genIpop (iCode *ic)
2194 {
2195   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2196 #if 0
2197   int size,offset ;
2198   
2199   
2200   /* if the temp was not pushed then */
2201   if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2202     return ;
2203   
2204   aopOp(IC_LEFT(ic),ic,FALSE);
2205   size = AOP_SIZE(IC_LEFT(ic));
2206   offset = (size-1);
2207   while (size--) 
2208     pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2209     FALSE,TRUE));
2210   
2211   freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2212 #endif
2213 }
2214
2215 /*-----------------------------------------------------------------*/
2216 /* unsaverbank - restores the resgister bank from stack            */
2217 /*-----------------------------------------------------------------*/
2218 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2219 {
2220   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2221 #if 0
2222   int i;
2223   asmop *aop ;
2224   regs *r = NULL;
2225   
2226   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2227   if (popPsw) {
2228     if (options.useXstack) {
2229       aop = newAsmop(0);
2230       r = getFreePtr(ic,&aop,FALSE);
2231       
2232       
2233       pic14_emitcode("mov","%s,_spx",r->name);
2234       pic14_emitcode("movx","a,@%s",r->name);
2235       pic14_emitcode("mov","psw,a");
2236       pic14_emitcode("dec","%s",r->name);
2237       
2238     }else
2239       pic14_emitcode ("pop","psw");
2240   }
2241   
2242   for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2243     if (options.useXstack) {       
2244       pic14_emitcode("movx","a,@%s",r->name);
2245       //pic14_emitcode("mov","(%s+%d),a",
2246       //       regspic14[i].base,8*bank+regspic14[i].offset);
2247       pic14_emitcode("dec","%s",r->name);
2248       
2249     } else 
2250       pic14_emitcode("pop",""); //"(%s+%d)",
2251     //regspic14[i].base,8*bank); //+regspic14[i].offset);
2252   }
2253   
2254   if (options.useXstack) {
2255     
2256     pic14_emitcode("mov","_spx,%s",r->name);
2257     freeAsmop(NULL,aop,ic,TRUE);
2258     
2259   }
2260 #endif 
2261 }
2262
2263 /*-----------------------------------------------------------------*/
2264 /* saverbank - saves an entire register bank on the stack          */
2265 /*-----------------------------------------------------------------*/
2266 static void saverbank (int bank, iCode *ic, bool pushPsw)
2267 {
2268   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2269 #if 0
2270   int i;
2271   asmop *aop ;
2272   regs *r = NULL;
2273   
2274   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2275   if (options.useXstack) {
2276     
2277     aop = newAsmop(0);
2278     r = getFreePtr(ic,&aop,FALSE);  
2279     pic14_emitcode("mov","%s,_spx",r->name);
2280     
2281   }
2282   
2283   for (i = 0 ; i < pic14_nRegs ;i++) {
2284     if (options.useXstack) {
2285       pic14_emitcode("inc","%s",r->name);
2286       //pic14_emitcode("mov","a,(%s+%d)",
2287       //         regspic14[i].base,8*bank+regspic14[i].offset);
2288       pic14_emitcode("movx","@%s,a",r->name);           
2289     } else 
2290       pic14_emitcode("push","");// "(%s+%d)",
2291     //regspic14[i].base,8*bank+regspic14[i].offset);
2292   }
2293   
2294   if (pushPsw) {
2295     if (options.useXstack) {
2296       pic14_emitcode("mov","a,psw");
2297       pic14_emitcode("movx","@%s,a",r->name); 
2298       pic14_emitcode("inc","%s",r->name);
2299       pic14_emitcode("mov","_spx,%s",r->name);       
2300       freeAsmop (NULL,aop,ic,TRUE);
2301       
2302     } else
2303       pic14_emitcode("push","psw");
2304     
2305     pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2306   }
2307   ic->bankSaved = 1;
2308 #endif
2309 }
2310
2311 /*-----------------------------------------------------------------*/
2312 /* genCall - generates a call statement                            */
2313 /*-----------------------------------------------------------------*/
2314 static void genCall (iCode *ic)
2315 {
2316   sym_link *dtype;   
2317   symbol *sym;
2318   unsigned char *name;
2319   int isExtern;
2320   
2321   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2322   
2323   /* if caller saves & we have not saved then */
2324   if (!ic->regsSaved)
2325     saveRegisters(ic);
2326   
2327     /* if we are calling a function that is not using
2328     the same register bank then we need to save the
2329   destination registers on the stack */
2330   dtype = operandType(IC_LEFT(ic));
2331   if (currFunc && dtype && 
2332     (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2333     IFFUNC_ISISR(currFunc->type) &&
2334     !ic->bankSaved) 
2335     
2336     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2337   
2338   /* if send set is not empty the assign */
2339   if (_G.sendSet) {
2340     iCode *sic;
2341     /* For the Pic port, there is no data stack.
2342     * So parameters passed to functions are stored
2343     * in registers. (The pCode optimizer will get
2344     * rid of most of these :).
2345     */
2346     int psuedoStkPtr=-1;
2347     int firstTimeThruLoop = 1;
2348     
2349     _G.sendSet = reverseSet(_G.sendSet);
2350     
2351     /* First figure how many parameters are getting passed */
2352     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2353     sic = setNextItem(_G.sendSet)) {
2354       
2355       aopOp(IC_LEFT(sic),sic,FALSE);
2356       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2357       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2358     }
2359     
2360     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2361     sic = setNextItem(_G.sendSet)) {
2362       int size, offset = 0;
2363       
2364       aopOp(IC_LEFT(sic),sic,FALSE);
2365       size = AOP_SIZE(IC_LEFT(sic));
2366       
2367       while (size--) {
2368         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2369           AopType(AOP_TYPE(IC_LEFT(sic))));
2370         
2371         if(!firstTimeThruLoop) {
2372         /* If this is not the first time we've been through the loop
2373         * then we need to save the parameter in a temporary
2374         * register. The last byte of the last parameter is
2375           * passed in W. */
2376           emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2377           
2378         }
2379         firstTimeThruLoop=0;
2380         
2381         mov2w (AOP(IC_LEFT(sic)),  offset);
2382         offset++;
2383       }
2384       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2385     }
2386     _G.sendSet = NULL;
2387   }
2388   /* make the call */
2389   sym = OP_SYMBOL(IC_LEFT(ic));
2390   name = sym->rname[0] ? sym->rname : sym->name;
2391   isExtern = IS_EXTERN(sym->etype);
2392   if (isExtern) {
2393     emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2394   }
2395   emitpcode(POC_CALL,popGetWithString(name,isExtern));
2396   if (isExtern) {
2397     emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel */
2398   }
2399   GpsuedoStkPtr=0;
2400   /* if we need assign a result value */
2401   if ((IS_ITEMP(IC_RESULT(ic)) && 
2402     (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2403     OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2404     IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2405     
2406     _G.accInUse++;
2407     aopOp(IC_RESULT(ic),ic,FALSE);
2408     _G.accInUse--;
2409     
2410     assignResultValue(IC_RESULT(ic));
2411     
2412     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2413       AopType(AOP_TYPE(IC_RESULT(ic))));
2414     
2415     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2416   }
2417   
2418   /* adjust the stack for parameters if 
2419   required */
2420   if (ic->parmBytes) {
2421     int i;
2422     if (ic->parmBytes > 3) {
2423       pic14_emitcode("mov","a,%s",spname);
2424       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2425       pic14_emitcode("mov","%s,a",spname);
2426     } else 
2427       for ( i = 0 ; i <  ic->parmBytes ;i++)
2428         pic14_emitcode("dec","%s",spname);
2429       
2430   }
2431   
2432   /* if register bank was saved then pop them */
2433   if (ic->bankSaved)
2434     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2435   
2436   /* if we hade saved some registers then unsave them */
2437   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2438     unsaveRegisters (ic);
2439   
2440   
2441 }
2442
2443 /*-----------------------------------------------------------------*/
2444 /* genPcall - generates a call by pointer statement                */
2445 /*-----------------------------------------------------------------*/
2446 static void genPcall (iCode *ic)
2447 {
2448   sym_link *dtype;
2449   symbol *albl = newiTempLabel(NULL);
2450   symbol *blbl = newiTempLabel(NULL);
2451   PIC_OPCODE poc;
2452   pCodeOp *pcop;
2453   operand *left;
2454   
2455   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2456   /* if caller saves & we have not saved then */
2457   if (!ic->regsSaved)
2458     saveRegisters(ic);
2459   
2460     /* if we are calling a function that is not using
2461     the same register bank then we need to save the
2462   destination registers on the stack */
2463   dtype = operandType(IC_LEFT(ic));
2464   if (currFunc && dtype && 
2465     IFFUNC_ISISR(currFunc->type) &&
2466     (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2467     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2468   
2469   left = IC_LEFT(ic);
2470   aopOp(left,ic,FALSE);
2471   DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2472   
2473   pushSide(IC_LEFT(ic), FPTRSIZE);
2474   
2475   /* if send set is not empty, assign parameters */
2476   if (_G.sendSet) {
2477     
2478     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2479     /* no way to pass args - W always gets used to make the call */
2480   }
2481   /* first idea - factor out a common helper function and call it.
2482   But don't know how to get it generated only once in its own block
2483   
2484     if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2485     char *rname;
2486     char *buffer;
2487     rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2488     DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2489     buffer = Safe_calloc(1,strlen(rname)+16);
2490     sprintf(buffer, "%s_goto_helper", rname);
2491     addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2492     free(buffer);
2493     }
2494   */
2495   emitpcode(POC_CALL,popGetLabel(albl->key));
2496   pcop = popGetLabel(blbl->key);
2497   emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2498   emitpcode(POC_GOTO,pcop);
2499   emitpLabel(albl->key);
2500   
2501   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
2502   
2503   emitpcode(poc,popGet(AOP(left),1));
2504   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2505   emitpcode(poc,popGet(AOP(left),0));
2506   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2507   
2508   emitpLabel(blbl->key);
2509   
2510   freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2511   
2512   /* if we need to assign a result value */
2513   if ((IS_ITEMP(IC_RESULT(ic)) &&
2514     (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2515     OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2516     IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2517     
2518     _G.accInUse++;
2519     aopOp(IC_RESULT(ic),ic,FALSE);
2520     _G.accInUse--;
2521     
2522     assignResultValue(IC_RESULT(ic));
2523     
2524     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2525   }
2526   
2527   /* if register bank was saved then unsave them */
2528   if (currFunc && dtype && 
2529     (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2530     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2531   
2532     /* if we hade saved some registers then
2533   unsave them */
2534   if (ic->regsSaved)
2535     unsaveRegisters (ic);
2536   
2537 }
2538
2539 /*-----------------------------------------------------------------*/
2540 /* resultRemat - result  is rematerializable                       */
2541 /*-----------------------------------------------------------------*/
2542 static int resultRemat (iCode *ic)
2543 {
2544   //    DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2545   if (SKIP_IC(ic) || ic->op == IFX)
2546     return 0;
2547   
2548   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2549     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2550     if (sym->remat && !POINTER_SET(ic)) 
2551       return 1;
2552   }
2553   
2554   return 0;
2555 }
2556
2557 #if defined(__BORLANDC__) || defined(_MSC_VER)
2558 #define STRCASECMP stricmp
2559 #else
2560 #define STRCASECMP strcasecmp
2561 #endif
2562
2563 #if 0
2564 /*-----------------------------------------------------------------*/
2565 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2566 /*-----------------------------------------------------------------*/
2567 static bool inExcludeList(char *s)
2568 {
2569   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2570   int i =0;
2571   
2572   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2573   if (options.excludeRegs[i] &&
2574     STRCASECMP(options.excludeRegs[i],"none") == 0)
2575     return FALSE ;
2576   
2577   for ( i = 0 ; options.excludeRegs[i]; i++) {
2578     if (options.excludeRegs[i] &&
2579       STRCASECMP(s,options.excludeRegs[i]) == 0)
2580       return TRUE;
2581   }
2582   return FALSE ;
2583 }
2584 #endif
2585
2586 /*-----------------------------------------------------------------*/
2587 /* genFunction - generated code for function entry                 */
2588 /*-----------------------------------------------------------------*/
2589 static void genFunction (iCode *ic)
2590 {
2591   symbol *sym;
2592   sym_link *ftype;
2593   
2594   DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2595   
2596   labelOffset += (max_key+4);
2597   max_key=0;
2598   GpsuedoStkPtr=0;
2599   _G.nRegsSaved = 0;
2600   /* create the function header */
2601   pic14_emitcode(";","-----------------------------------------");
2602   pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2603   pic14_emitcode(";","-----------------------------------------");
2604   
2605   pic14_emitcode("","%s:",sym->rname);
2606   addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2607   
2608   ftype = operandType(IC_LEFT(ic));
2609   
2610   /* if critical function then turn interrupts off */
2611   if (IFFUNC_ISCRITICAL(ftype))
2612     pic14_emitcode("clr","ea");
2613   
2614     /* here we need to generate the equates for the
2615   register bank if required */
2616 #if 0
2617   if (FUNC_REGBANK(ftype) != rbank) {
2618     int i ;
2619     
2620     rbank = FUNC_REGBANK(ftype);
2621     for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2622       if (strcmp(regspic14[i].base,"0") == 0)
2623         pic14_emitcode("","%s = 0x%02x",
2624         regspic14[i].dname,
2625         8*rbank+regspic14[i].offset);
2626       else
2627         pic14_emitcode ("","%s = %s + 0x%02x",
2628         regspic14[i].dname,
2629         regspic14[i].base,
2630         8*rbank+regspic14[i].offset);
2631     }
2632   }
2633 #endif
2634   
2635   /* if this is an interrupt service routine */
2636   if (IFFUNC_ISISR(sym->type)) {
2637   /*  already done in pic14createInterruptVect() - delete me
2638   addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2639   emitpcodeNULLop(POC_NOP);
2640   emitpcodeNULLop(POC_NOP);
2641   emitpcodeNULLop(POC_NOP);
2642     */
2643     emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2644     emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2645     emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2646     emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2647     emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2648     emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2649     emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2650     
2651     pBlockConvert2ISR(pb);
2652 #if 0  
2653     if (!inExcludeList("acc"))      
2654       pic14_emitcode ("push","acc");  
2655     if (!inExcludeList("b"))
2656       pic14_emitcode ("push","b");
2657     if (!inExcludeList("dpl"))
2658       pic14_emitcode ("push","dpl");
2659     if (!inExcludeList("dph"))
2660       pic14_emitcode ("push","dph");
2661     if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2662     {
2663       pic14_emitcode ("push", "dpx");
2664       /* Make sure we're using standard DPTR */
2665       pic14_emitcode ("push", "dps");
2666       pic14_emitcode ("mov", "dps, #0x00");
2667       if (options.stack10bit)
2668       { 
2669         /* This ISR could conceivably use DPTR2. Better save it. */
2670         pic14_emitcode ("push", "dpl1");
2671         pic14_emitcode ("push", "dph1");
2672         pic14_emitcode ("push", "dpx1");
2673       }
2674     }
2675     /* if this isr has no bank i.e. is going to
2676     run with bank 0 , then we need to save more
2677 registers :-) */
2678     if (!FUNC_REGBANK(sym->type)) {
2679       
2680     /* if this function does not call any other
2681     function then we can be economical and
2682       save only those registers that are used */
2683       if (! IFFUNC_HASFCALL(sym->type)) {
2684         int i;
2685         
2686         /* if any registers used */
2687         if (sym->regsUsed) {
2688           /* save the registers used */
2689           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2690             if (bitVectBitValue(sym->regsUsed,i) ||
2691               (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2692               pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);         
2693           }
2694         }
2695         
2696       } else {
2697       /* this function has  a function call cannot
2698       determines register usage so we will have the
2699         entire bank */
2700         saverbank(0,ic,FALSE);
2701       }     
2702     }
2703 #endif
2704   } else {
2705   /* if callee-save to be used for this function
2706     then save the registers being used in this function */
2707     if (IFFUNC_CALLEESAVES(sym->type)) {
2708       int i;
2709       
2710       /* if any registers used */
2711       if (sym->regsUsed) {
2712         /* save the registers used */
2713         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2714           if (bitVectBitValue(sym->regsUsed,i) ||
2715             (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2716             //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2717             _G.nRegsSaved++;
2718           }
2719         }
2720       }
2721     }
2722   }
2723   
2724   /* set the register bank to the desired value */
2725   if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2726     pic14_emitcode("push","psw");
2727     pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2728   }
2729   
2730   if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2731     
2732     if (options.useXstack) {
2733       pic14_emitcode("mov","r0,%s",spname);
2734       pic14_emitcode("mov","a,_bp");
2735       pic14_emitcode("movx","@r0,a");
2736       pic14_emitcode("inc","%s",spname);
2737     }
2738     else
2739     {
2740       /* set up the stack */
2741       pic14_emitcode ("push","_bp");     /* save the callers stack  */
2742     }
2743     pic14_emitcode ("mov","_bp,%s",spname);
2744   }
2745   
2746   /* adjust the stack for the function */
2747   if (sym->stack) {
2748     
2749     int i = sym->stack;
2750     if (i > 256 ) 
2751       werror(W_STACK_OVERFLOW,sym->name);
2752     
2753     if (i > 3 && sym->recvSize < 4) {        
2754       
2755       pic14_emitcode ("mov","a,sp");
2756       pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2757       pic14_emitcode ("mov","sp,a");
2758       
2759     }
2760     else
2761       while(i--)
2762         pic14_emitcode("inc","sp");
2763   }
2764   
2765   if (sym->xstack) {
2766     
2767     pic14_emitcode ("mov","a,_spx");
2768     pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2769     pic14_emitcode ("mov","_spx,a");
2770   }    
2771   
2772 }
2773
2774 /*-----------------------------------------------------------------*/
2775 /* genEndFunction - generates epilogue for functions               */
2776 /*-----------------------------------------------------------------*/
2777 static void genEndFunction (iCode *ic)
2778 {
2779   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2780   
2781   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2782   
2783   if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2784   {
2785     pic14_emitcode ("mov","%s,_bp",spname);
2786   }
2787   
2788   /* if use external stack but some variables were
2789   added to the local stack then decrement the
2790   local stack */
2791   if (options.useXstack && sym->stack) {      
2792     pic14_emitcode("mov","a,sp");
2793     pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2794     pic14_emitcode("mov","sp,a");
2795   }
2796   
2797   
2798   if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2799     if (options.useXstack) {
2800       pic14_emitcode("mov","r0,%s",spname);
2801       pic14_emitcode("movx","a,@r0");
2802       pic14_emitcode("mov","_bp,a");
2803       pic14_emitcode("dec","%s",spname);
2804     }
2805     else
2806     {
2807       pic14_emitcode ("pop","_bp");
2808     }
2809   }
2810   
2811   /* restore the register bank  */    
2812   if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2813     pic14_emitcode ("pop","psw");
2814   
2815   if (IFFUNC_ISISR(sym->type)) {
2816     
2817     /* now we need to restore the registers */
2818     /* if this isr has no bank i.e. is going to
2819     run with bank 0 , then we need to save more
2820 registers :-) */
2821     if (!FUNC_REGBANK(sym->type)) {
2822       
2823     /* if this function does not call any other
2824     function then we can be economical and
2825       save only those registers that are used */
2826       if (! IFFUNC_HASFCALL(sym->type)) {
2827         int i;
2828         
2829         /* if any registers used */
2830         if (sym->regsUsed) {
2831           /* save the registers used */
2832           for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2833             if (bitVectBitValue(sym->regsUsed,i) ||
2834               (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2835               pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2836           }
2837         }
2838         
2839       } else {
2840       /* this function has  a function call cannot
2841       determines register usage so we will have the
2842         entire bank */
2843         unsaverbank(0,ic,FALSE);
2844       }     
2845     }
2846 #if 0
2847     if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2848     {
2849       if (options.stack10bit)
2850       {
2851         pic14_emitcode ("pop", "dpx1");
2852         pic14_emitcode ("pop", "dph1");
2853         pic14_emitcode ("pop", "dpl1");
2854       } 
2855       pic14_emitcode ("pop", "dps");
2856       pic14_emitcode ("pop", "dpx");
2857     }
2858     if (!inExcludeList("dph"))
2859       pic14_emitcode ("pop","dph");
2860     if (!inExcludeList("dpl"))
2861       pic14_emitcode ("pop","dpl");
2862     if (!inExcludeList("b"))
2863       pic14_emitcode ("pop","b");
2864     if (!inExcludeList("acc"))
2865       pic14_emitcode ("pop","acc");
2866     
2867     if (IFFUNC_ISCRITICAL(sym->type))
2868       pic14_emitcode("setb","ea");
2869 #endif
2870     
2871     /* if debug then send end of function */
2872     /*  if (options.debug && currFunc) { */
2873     if (currFunc) {
2874       _G.debugLine = 1;
2875       pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2876         FileBaseName(ic->filename),currFunc->lastLine,
2877         ic->level,ic->block); 
2878       if (IS_STATIC(currFunc->etype))     
2879         pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2880       else
2881         pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2882       _G.debugLine = 0;
2883     }
2884     
2885     pic14_emitcode ("reti","");
2886     emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
2887     emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
2888     emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2889     emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2890     emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2891     emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2892     emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2893     addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2894     emitpcodeNULLop(POC_RETFIE);
2895   }
2896   else {
2897     if (IFFUNC_ISCRITICAL(sym->type))
2898       pic14_emitcode("setb","ea");
2899     
2900     if (IFFUNC_CALLEESAVES(sym->type)) {
2901       int i;
2902       
2903       /* if any registers used */
2904       if (sym->regsUsed) {
2905         /* save the registers used */
2906         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2907           if (bitVectBitValue(sym->regsUsed,i) ||
2908             (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2909             pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2910         }
2911       }
2912       
2913     }
2914     
2915     /* if debug then send end of function */
2916     if (currFunc) {
2917       _G.debugLine = 1;
2918       pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2919         FileBaseName(ic->filename),currFunc->lastLine,
2920         ic->level,ic->block); 
2921       if (IS_STATIC(currFunc->etype))     
2922         pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2923       else
2924         pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2925       _G.debugLine = 0;
2926     }
2927     
2928     pic14_emitcode ("return","");
2929     emitpcodeNULLop(POC_RETURN);
2930     
2931     /* Mark the end of a function */
2932     addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2933   }
2934   
2935 }
2936
2937 /*-----------------------------------------------------------------*/
2938 /* genRet - generate code for return statement                     */
2939 /*-----------------------------------------------------------------*/
2940 static void genRet (iCode *ic)
2941 {
2942   int size,offset = 0 , pushed = 0;
2943   
2944   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2945   /* if we have no return value then
2946   just generate the "ret" */
2947   if (!IC_LEFT(ic)) 
2948     goto jumpret;       
2949   
2950     /* we have something to return then
2951   move the return value into place */
2952   aopOp(IC_LEFT(ic),ic,FALSE);
2953   size = AOP_SIZE(IC_LEFT(ic));
2954   
2955   while (size--) {
2956     char *l ;
2957     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2958       /* #NOCHANGE */
2959       l = aopGet(AOP(IC_LEFT(ic)),offset++,
2960         FALSE,TRUE);
2961       pic14_emitcode("push","%s",l);
2962       pushed++;
2963     } else {
2964       l = aopGet(AOP(IC_LEFT(ic)),offset,
2965         FALSE,FALSE);
2966       if (strcmp(fReturn[offset],l)) {
2967         if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
2968           AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
2969           ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2970           ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
2971           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
2972         }else {
2973           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
2974         }
2975         if(size) {
2976           emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
2977         }
2978         offset++;
2979       }
2980     }
2981   }    
2982   
2983   if (pushed) {
2984     while(pushed) {
2985       pushed--;
2986       if (strcmp(fReturn[pushed],"a"))
2987         pic14_emitcode("pop",fReturn[pushed]);
2988       else
2989         pic14_emitcode("pop","acc");
2990     }
2991   }
2992   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2993   
2994 jumpret:
2995 /* generate a jump to the return label
2996   if the next is not the return statement */
2997   if (!(ic->next && ic->next->op == LABEL &&
2998     IC_LABEL(ic->next) == returnLabel)) {
2999     
3000     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3001     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3002   }
3003   
3004 }
3005
3006 /*-----------------------------------------------------------------*/
3007 /* genLabel - generates a label                                    */
3008 /*-----------------------------------------------------------------*/
3009 static void genLabel (iCode *ic)
3010 {
3011   /* special case never generate */
3012   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3013   if (IC_LABEL(ic) == entryLabel)
3014     return ;
3015   
3016   emitpLabel(IC_LABEL(ic)->key);
3017   pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3018 }
3019
3020 /*-----------------------------------------------------------------*/
3021 /* genGoto - generates a goto                                      */
3022 /*-----------------------------------------------------------------*/
3023 //tsd
3024 static void genGoto (iCode *ic)
3025 {
3026   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3027   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3028 }
3029
3030
3031 /*-----------------------------------------------------------------*/
3032 /* genMultbits :- multiplication of bits                           */
3033 /*-----------------------------------------------------------------*/
3034 static void genMultbits (operand *left, 
3035              operand *right, 
3036              operand *result)
3037 {
3038   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3039   
3040   if(!pic14_sameRegs(AOP(result),AOP(right)))
3041     emitpcode(POC_BSF,  popGet(AOP(result),0));
3042   
3043   emitpcode(POC_BTFSC,popGet(AOP(right),0));
3044   emitpcode(POC_BTFSS,popGet(AOP(left),0));
3045   emitpcode(POC_BCF,  popGet(AOP(result),0));
3046   
3047 }
3048
3049
3050 /*-----------------------------------------------------------------*/
3051 /* genMultOneByte : 8 bit multiplication & division                */
3052 /*-----------------------------------------------------------------*/
3053 static void genMultOneByte (operand *left,
3054               operand *right,
3055               operand *result)
3056 {
3057   sym_link *opetype = operandType(result);
3058   
3059   // symbol *lbl ;
3060   int size,offset;
3061   
3062   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3063   DEBUGpic14_AopType(__LINE__,left,right,result);
3064   DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3065   
3066   /* (if two literals, the value is computed before) */
3067   /* if one literal, literal on the right */
3068   if (AOP_TYPE(left) == AOP_LIT){
3069     operand *t = right;
3070     right = left;
3071     left = t;
3072   }
3073   
3074   size = AOP_SIZE(result);
3075   if(size == 1) {
3076     
3077     if (AOP_TYPE(right) == AOP_LIT){
3078       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3079         aopGet(AOP(right),0,FALSE,FALSE), 
3080         aopGet(AOP(left),0,FALSE,FALSE), 
3081         aopGet(AOP(result),0,FALSE,FALSE));
3082       pic14_emitcode("call","genMultLit");
3083     } else {
3084       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3085         aopGet(AOP(right),0,FALSE,FALSE), 
3086         aopGet(AOP(left),0,FALSE,FALSE), 
3087         aopGet(AOP(result),0,FALSE,FALSE));
3088       pic14_emitcode("call","genMult8X8_8");
3089       
3090     }
3091     genMult8X8_8 (left, right,result);
3092     
3093     
3094     /* signed or unsigned */
3095     //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3096     //l = aopGet(AOP(left),0,FALSE,FALSE);
3097     //MOVA(l);       
3098     //pic14_emitcode("mul","ab");
3099     /* if result size = 1, mul signed = mul unsigned */
3100     //aopPut(AOP(result),"a",0);
3101     
3102   } else {  // (size > 1)
3103     
3104     pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3105       aopGet(AOP(right),0,FALSE,FALSE), 
3106       aopGet(AOP(left),0,FALSE,FALSE), 
3107       aopGet(AOP(result),0,FALSE,FALSE));
3108     
3109     if (SPEC_USIGN(opetype)){
3110       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3111       genUMult8X8_16 (left, right, result, NULL);
3112       
3113       if (size > 2) {
3114         /* for filling the MSBs */
3115         emitpcode(POC_CLRF,  popGet(AOP(result),2));
3116         emitpcode(POC_CLRF,  popGet(AOP(result),3));
3117       }
3118     }
3119     else{
3120       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3121       
3122       pic14_emitcode("mov","a,b");
3123       
3124       /* adjust the MSB if left or right neg */
3125       
3126       /* if one literal */
3127       if (AOP_TYPE(right) == AOP_LIT){
3128         pic14_emitcode("multiply ","right is a lit");
3129         /* AND literal negative */
3130         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3131           /* adjust MSB (c==0 after mul) */
3132           pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3133         }
3134       }
3135       else{
3136         genSMult8X8_16 (left, right, result, NULL);
3137       }
3138       
3139       if(size > 2){
3140         pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3141         /* get the sign */
3142         pic14_emitcode("rlc","a");
3143         pic14_emitcode("subb","a,acc");
3144       }
3145     }
3146     
3147     size -= 2;   
3148     offset = 2;
3149     if (size > 0)
3150       while (size--)
3151         pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3152       //aopPut(AOP(result),"a",offset++);
3153   }
3154 }
3155
3156 /*-----------------------------------------------------------------*/
3157 /* genMult - generates code for multiplication                     */
3158 /*-----------------------------------------------------------------*/
3159 static void genMult (iCode *ic)
3160 {
3161   operand *left = IC_LEFT(ic);
3162   operand *right = IC_RIGHT(ic);
3163   operand *result= IC_RESULT(ic);   
3164   
3165   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3166   /* assign the amsops */
3167   aopOp (left,ic,FALSE);
3168   aopOp (right,ic,FALSE);
3169   aopOp (result,ic,TRUE);
3170   
3171   DEBUGpic14_AopType(__LINE__,left,right,result);
3172   
3173   /* special cases first */
3174   /* both are bits */
3175   if (AOP_TYPE(left) == AOP_CRY &&
3176     AOP_TYPE(right)== AOP_CRY) {
3177     genMultbits(left,right,result);
3178     goto release ;
3179   }
3180   
3181   /* if both are of size == 1 */
3182   if (AOP_SIZE(left) == 1 &&
3183     AOP_SIZE(right) == 1 ) {
3184     genMultOneByte(left,right,result);
3185     goto release ;
3186   }
3187   
3188   pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3189   
3190   /* should have been converted to function call */
3191   //assert(0) ;
3192   
3193 release :
3194   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3195   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3196   freeAsmop(result,NULL,ic,TRUE); 
3197 }
3198
3199 /*-----------------------------------------------------------------*/
3200 /* genDivbits :- division of bits                                  */
3201 /*-----------------------------------------------------------------*/
3202 static void genDivbits (operand *left, 
3203             operand *right, 
3204             operand *result)
3205 {
3206   
3207   char *l;
3208   
3209   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3210   /* the result must be bit */    
3211   pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3212   l = aopGet(AOP(left),0,FALSE,FALSE);
3213   
3214   MOVA(l);    
3215   
3216   pic14_emitcode("div","ab");
3217   pic14_emitcode("rrc","a");
3218   aopPut(AOP(result),"c",0);
3219 }
3220
3221 /*-----------------------------------------------------------------*/
3222 /* genDivOneByte : 8 bit division                                  */
3223 /*-----------------------------------------------------------------*/
3224 static void genDivOneByte (operand *left,
3225                operand *right,
3226                operand *result)
3227 {
3228   sym_link *opetype = operandType(result);
3229   char *l ;
3230   symbol *lbl ;
3231   int size,offset;
3232   
3233   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3234   size = AOP_SIZE(result) - 1;
3235   offset = 1;
3236   /* signed or unsigned */
3237   if (SPEC_USIGN(opetype)) {
3238     /* unsigned is easy */
3239     pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3240     l = aopGet(AOP(left),0,FALSE,FALSE);
3241     MOVA(l);        
3242     pic14_emitcode("div","ab");
3243     aopPut(AOP(result),"a",0);
3244     while (size--)
3245       aopPut(AOP(result),zero,offset++);
3246     return ;
3247   }
3248   
3249   /* signed is a little bit more difficult */
3250   
3251   /* save the signs of the operands */
3252   l = aopGet(AOP(left),0,FALSE,FALSE);    
3253   MOVA(l);    
3254   pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3255   pic14_emitcode("push","acc"); /* save it on the stack */
3256   
3257   /* now sign adjust for both left & right */
3258   l =  aopGet(AOP(right),0,FALSE,FALSE);    
3259   MOVA(l);       
3260   lbl = newiTempLabel(NULL);
3261   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3262   pic14_emitcode("cpl","a");   
3263   pic14_emitcode("inc","a");
3264   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3265   pic14_emitcode("mov","b,a");
3266   
3267   /* sign adjust left side */
3268   l =  aopGet(AOP(left),0,FALSE,FALSE);    
3269   MOVA(l);
3270   
3271   lbl = newiTempLabel(NULL);
3272   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3273   pic14_emitcode("cpl","a");
3274   pic14_emitcode("inc","a");
3275   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3276   
3277   /* now the division */
3278   pic14_emitcode("div","ab");
3279   /* we are interested in the lower order
3280   only */
3281   pic14_emitcode("mov","b,a");
3282   lbl = newiTempLabel(NULL);
3283   pic14_emitcode("pop","acc");   
3284   /* if there was an over flow we don't 
3285   adjust the sign of the result */
3286   pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3287   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3288   CLRC;
3289   pic14_emitcode("clr","a");
3290   pic14_emitcode("subb","a,b");
3291   pic14_emitcode("mov","b,a");
3292   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3293   
3294   /* now we are done */
3295   aopPut(AOP(result),"b",0);
3296   if(size > 0){
3297     pic14_emitcode("mov","c,b.7");
3298     pic14_emitcode("subb","a,acc");   
3299   }
3300   while (size--)
3301     aopPut(AOP(result),"a",offset++);
3302   
3303 }
3304
3305 /*-----------------------------------------------------------------*/
3306 /* genDiv - generates code for division                            */
3307 /*-----------------------------------------------------------------*/
3308 static void genDiv (iCode *ic)
3309 {
3310   operand *left = IC_LEFT(ic);
3311   operand *right = IC_RIGHT(ic);
3312   operand *result= IC_RESULT(ic);   
3313   
3314   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3315   /* assign the amsops */
3316   aopOp (left,ic,FALSE);
3317   aopOp (right,ic,FALSE);
3318   aopOp (result,ic,TRUE);
3319   
3320   /* special cases first */
3321   /* both are bits */
3322   if (AOP_TYPE(left) == AOP_CRY &&
3323     AOP_TYPE(right)== AOP_CRY) {
3324     genDivbits(left,right,result);
3325     goto release ;
3326   }
3327   
3328   /* if both are of size == 1 */
3329   if (AOP_SIZE(left) == 1 &&
3330     AOP_SIZE(right) == 1 ) {
3331     genDivOneByte(left,right,result);
3332     goto release ;
3333   }
3334   
3335   /* should have been converted to function call */
3336   assert(0);
3337 release :
3338   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3339   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3340   freeAsmop(result,NULL,ic,TRUE); 
3341 }
3342
3343 /*-----------------------------------------------------------------*/
3344 /* genModbits :- modulus of bits                                   */
3345 /*-----------------------------------------------------------------*/
3346 static void genModbits (operand *left, 
3347             operand *right, 
3348             operand *result)
3349 {
3350   
3351   char *l;
3352   
3353   /* the result must be bit */    
3354   pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3355   l = aopGet(AOP(left),0,FALSE,FALSE);
3356   
3357   MOVA(l);       
3358   
3359   pic14_emitcode("div","ab");
3360   pic14_emitcode("mov","a,b");
3361   pic14_emitcode("rrc","a");
3362   aopPut(AOP(result),"c",0);
3363 }
3364
3365 /*-----------------------------------------------------------------*/
3366 /* genModOneByte : 8 bit modulus                                   */
3367 /*-----------------------------------------------------------------*/
3368 static void genModOneByte (operand *left,
3369                operand *right,
3370                operand *result)
3371 {
3372   sym_link *opetype = operandType(result);
3373   char *l ;
3374   symbol *lbl ;
3375   
3376   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3377   /* signed or unsigned */
3378   if (SPEC_USIGN(opetype)) {
3379     /* unsigned is easy */
3380     pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3381     l = aopGet(AOP(left),0,FALSE,FALSE);
3382     MOVA(l);    
3383     pic14_emitcode("div","ab");
3384     aopPut(AOP(result),"b",0);
3385     return ;
3386   }
3387   
3388   /* signed is a little bit more difficult */
3389   
3390   /* save the signs of the operands */
3391   l = aopGet(AOP(left),0,FALSE,FALSE);    
3392   MOVA(l);
3393   
3394   pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3395   pic14_emitcode("push","acc"); /* save it on the stack */
3396   
3397   /* now sign adjust for both left & right */
3398   l =  aopGet(AOP(right),0,FALSE,FALSE);    
3399   MOVA(l);
3400   
3401   lbl = newiTempLabel(NULL);
3402   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3403   pic14_emitcode("cpl","a");   
3404   pic14_emitcode("inc","a");
3405   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3406   pic14_emitcode("mov","b,a"); 
3407   
3408   /* sign adjust left side */
3409   l =  aopGet(AOP(left),0,FALSE,FALSE);    
3410   MOVA(l);
3411   
3412   lbl = newiTempLabel(NULL);
3413   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3414   pic14_emitcode("cpl","a");   
3415   pic14_emitcode("inc","a");
3416   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3417   
3418   /* now the multiplication */
3419   pic14_emitcode("div","ab");
3420   /* we are interested in the lower order
3421   only */
3422   lbl = newiTempLabel(NULL);
3423   pic14_emitcode("pop","acc");   
3424   /* if there was an over flow we don't 
3425   adjust the sign of the result */
3426   pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3427   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3428   CLRC ;
3429   pic14_emitcode("clr","a");
3430   pic14_emitcode("subb","a,b");
3431   pic14_emitcode("mov","b,a");
3432   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3433   
3434   /* now we are done */
3435   aopPut(AOP(result),"b",0);
3436   
3437 }
3438
3439 /*-----------------------------------------------------------------*/
3440 /* genMod - generates code for division                            */
3441 /*-----------------------------------------------------------------*/
3442 static void genMod (iCode *ic)
3443 {
3444   operand *left = IC_LEFT(ic);
3445   operand *right = IC_RIGHT(ic);
3446   operand *result= IC_RESULT(ic);  
3447   
3448   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3449   /* assign the amsops */
3450   aopOp (left,ic,FALSE);
3451   aopOp (right,ic,FALSE);
3452   aopOp (result,ic,TRUE);
3453   
3454   /* special cases first */
3455   /* both are bits */
3456   if (AOP_TYPE(left) == AOP_CRY &&
3457     AOP_TYPE(right)== AOP_CRY) {
3458     genModbits(left,right,result);
3459     goto release ;
3460   }
3461   
3462   /* if both are of size == 1 */
3463   if (AOP_SIZE(left) == 1 &&
3464     AOP_SIZE(right) == 1 ) {
3465     genModOneByte(left,right,result);
3466     goto release ;
3467   }
3468   
3469   /* should have been converted to function call */
3470   assert(0);
3471   
3472 release :
3473   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3474   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3475   freeAsmop(result,NULL,ic,TRUE); 
3476 }
3477
3478 /*-----------------------------------------------------------------*/
3479 /* genIfxJump :- will create a jump depending on the ifx           */
3480 /*-----------------------------------------------------------------*/
3481 /*
3482 note: May need to add parameter to indicate when a variable is in bit space.
3483 */
3484 static void genIfxJump (iCode *ic, char *jval)
3485 {
3486   
3487   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3488   /* if true label then we jump if condition
3489   supplied is true */
3490   if ( IC_TRUE(ic) ) {
3491     
3492     if(strcmp(jval,"a") == 0)
3493       emitSKPZ;
3494     else if (strcmp(jval,"c") == 0)
3495       emitSKPC;
3496     else {
3497       DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);   
3498       emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3499     }
3500     
3501     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3502     pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3503     
3504   }
3505   else {
3506     /* false label is present */
3507     if(strcmp(jval,"a") == 0)
3508       emitSKPNZ;
3509     else if (strcmp(jval,"c") == 0)
3510       emitSKPNC;
3511     else {
3512       DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);   
3513       emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3514     }
3515     
3516     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3517     pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3518     
3519   }
3520   
3521   
3522   /* mark the icode as generated */
3523   ic->generated = 1;
3524 }
3525
3526 /*-----------------------------------------------------------------*/
3527 /* genSkip                                                         */
3528 /*-----------------------------------------------------------------*/
3529 static void genSkip(iCode *ifx,int status_bit)
3530 {
3531   if(!ifx)
3532     return;
3533   
3534   if ( IC_TRUE(ifx) ) {
3535     switch(status_bit) {
3536     case 'z':
3537       emitSKPNZ;
3538       break;
3539       
3540     case 'c':
3541       emitSKPNC;
3542       break;
3543       
3544     case 'd':
3545       emitSKPDC;
3546       break;
3547       
3548     }
3549     
3550     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3551     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3552     
3553   } else {
3554     
3555     switch(status_bit) {
3556       
3557     case 'z':
3558       emitSKPZ;
3559       break;
3560       
3561     case 'c':
3562       emitSKPC;
3563       break;
3564       
3565     case 'd':
3566       emitSKPDC;
3567       break;
3568     }
3569     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3570     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3571     
3572   }
3573   
3574 }
3575
3576 /*-----------------------------------------------------------------*/
3577 /* genSkipc                                                        */
3578 /*-----------------------------------------------------------------*/
3579 static void genSkipc(resolvedIfx *rifx)
3580 {
3581   if(!rifx)
3582     return;
3583   
3584   if(rifx->condition)
3585     emitSKPC;
3586   else
3587     emitSKPNC;
3588   
3589   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3590   rifx->generated = 1;
3591 }
3592
3593 /*-----------------------------------------------------------------*/
3594 /* genSkipz2                                                       */
3595 /*-----------------------------------------------------------------*/
3596 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3597 {
3598   if(!rifx)
3599     return;
3600   
3601   if( (rifx->condition ^ invert_condition) & 1)
3602     emitSKPZ;
3603   else
3604     emitSKPNZ;
3605   
3606   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3607   rifx->generated = 1;
3608 }
3609
3610 /*-----------------------------------------------------------------*/
3611 /* genSkipz                                                        */
3612 /*-----------------------------------------------------------------*/
3613 static void genSkipz(iCode *ifx, int condition)
3614 {
3615   if(!ifx)
3616     return;
3617   
3618   if(condition)
3619     emitSKPNZ;
3620   else
3621     emitSKPZ;
3622   
3623   if ( IC_TRUE(ifx) )
3624     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3625   else
3626     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3627   
3628   if ( IC_TRUE(ifx) )
3629     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3630   else
3631     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3632   
3633 }
3634 /*-----------------------------------------------------------------*/
3635 /* genSkipCond                                                     */
3636 /*-----------------------------------------------------------------*/
3637 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3638 {
3639   if(!rifx)
3640     return;
3641   
3642   if(rifx->condition)
3643     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3644   else
3645     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3646   
3647   
3648   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3649   rifx->generated = 1;
3650 }
3651
3652 #if 0
3653 /*-----------------------------------------------------------------*/
3654 /* genChkZeroes :- greater or less than comparison                 */
3655 /*     For each byte in a literal that is zero, inclusive or the   */
3656 /*     the corresponding byte in the operand with W                */
3657 /*     returns true if any of the bytes are zero                   */
3658 /*-----------------------------------------------------------------*/
3659 static int genChkZeroes(operand *op, int lit,  int size)
3660 {
3661   
3662   int i;
3663   int flag =1;
3664   
3665   while(size--) {
3666     i = (lit >> (size*8)) & 0xff;
3667     
3668     if(i==0) {
3669       if(flag) 
3670         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3671       else
3672         emitpcode(POC_IORFW, popGet(AOP(op),size));
3673       flag = 0;
3674     }
3675   }
3676   
3677   return (flag==0);
3678 }
3679 #endif
3680
3681 /*-----------------------------------------------------------------*/
3682 /* genCmp :- greater or less than comparison                       */
3683 /*-----------------------------------------------------------------*/
3684 static void genCmp (operand *left,operand *right,
3685           operand *result, iCode *ifx, int sign)
3686 {
3687   int size; //, offset = 0 ;
3688   unsigned long lit = 0L,i = 0;
3689   resolvedIfx rFalseIfx;
3690   //  resolvedIfx rTrueIfx;
3691   symbol *truelbl;
3692   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3693   /*
3694   if(ifx) {
3695   DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3696   DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3697   }
3698   */
3699   
3700   resolveIfx(&rFalseIfx,ifx);
3701   truelbl  = newiTempLabel(NULL);
3702   size = max(AOP_SIZE(left),AOP_SIZE(right));
3703   
3704   DEBUGpic14_AopType(__LINE__,left,right,result);
3705   
3706 #define _swapp
3707   
3708   /* if literal is on the right then swap with left */
3709   if ((AOP_TYPE(right) == AOP_LIT)) {
3710     operand *tmp = right ;
3711     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3712     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3713 #ifdef _swapp
3714     
3715     lit = (lit - 1) & mask;
3716     right = left;
3717     left = tmp;
3718     rFalseIfx.condition ^= 1;
3719 #endif
3720     
3721   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3722     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3723   }
3724   
3725   
3726   //if(IC_TRUE(ifx) == NULL)
3727   /* if left & right are bit variables */
3728   if (AOP_TYPE(left) == AOP_CRY &&
3729     AOP_TYPE(right) == AOP_CRY ) {
3730     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3731     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3732   } else {
3733   /* subtract right from left if at the
3734   end the carry flag is set then we know that
3735     left is greater than right */
3736     
3737     //    {
3738     
3739     symbol *lbl  = newiTempLabel(NULL);
3740     
3741 #ifndef _swapp
3742     if(AOP_TYPE(right) == AOP_LIT) {
3743       
3744       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3745       
3746       DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3747       
3748       /* special cases */
3749       
3750       if(lit == 0) {
3751         
3752         if(sign != 0) 
3753           genSkipCond(&rFalseIfx,left,size-1,7);
3754         else 
3755           /* no need to compare to 0...*/
3756           /* NOTE: this is a de-generate compare that most certainly 
3757           *       creates some dead code. */
3758           emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3759         
3760         if(ifx) ifx->generated = 1;
3761         return;
3762         
3763       }
3764       size--;
3765       
3766       if(size == 0) {
3767         //i = (lit >> (size*8)) & 0xff;
3768         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3769         
3770         emitpcode(POC_MOVFW, popGet(AOP(left),size));
3771         
3772         i = ((0-lit) & 0xff);
3773         if(sign) {
3774           if( i == 0x81) { 
3775           /* lit is 0x7f, all signed chars are less than
3776             * this except for 0x7f itself */
3777             emitpcode(POC_XORLW, popGetLit(0x7f));
3778             genSkipz2(&rFalseIfx,0);
3779           } else {
3780             emitpcode(POC_ADDLW, popGetLit(0x80));
3781             emitpcode(POC_ADDLW, popGetLit(i^0x80));
3782             genSkipc(&rFalseIfx);
3783           }
3784           
3785         } else {
3786           if(lit == 1) {
3787             genSkipz2(&rFalseIfx,1);
3788           } else {
3789             emitpcode(POC_ADDLW, popGetLit(i));
3790             genSkipc(&rFalseIfx);
3791           }
3792         }
3793         
3794         if(ifx) ifx->generated = 1;
3795         return;
3796       }
3797       
3798       /* chars are out of the way. now do ints and longs */
3799       
3800       
3801       DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3802       
3803       /* special cases */
3804       
3805       if(sign) {
3806         
3807         if(lit == 0) {
3808           genSkipCond(&rFalseIfx,left,size,7);
3809           if(ifx) ifx->generated = 1;
3810           return;
3811         }
3812         
3813         if(lit <0x100) {
3814           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3815           
3816           //rFalseIfx.condition ^= 1;
3817           //genSkipCond(&rFalseIfx,left,size,7);
3818           //rFalseIfx.condition ^= 1;
3819           
3820           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3821           if(rFalseIfx.condition)
3822             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3823           else
3824             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3825           
3826           emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3827           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3828           emitpcode(POC_MOVFW, popGet(AOP(left),1));
3829           
3830           while(size > 1)
3831             emitpcode(POC_IORFW, popGet(AOP(left),size--));
3832           
3833           if(rFalseIfx.condition) {
3834             emitSKPZ;
3835             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3836             
3837           } else {
3838             emitSKPNZ;
3839           }
3840           
3841           genSkipc(&rFalseIfx);
3842           emitpLabel(truelbl->key);
3843           if(ifx) ifx->generated = 1;
3844           return;
3845           
3846         }
3847         
3848         if(size == 1) {
3849           
3850           if( (lit & 0xff) == 0) {
3851             /* lower byte is zero */
3852             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3853             i = ((lit >> 8) & 0xff) ^0x80;
3854             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3855             emitpcode(POC_ADDLW, popGetLit( 0x80));
3856             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3857             genSkipc(&rFalseIfx);
3858             
3859             
3860             if(ifx) ifx->generated = 1;
3861             return;
3862             
3863           }
3864         } else {
3865           /* Special cases for signed longs */
3866           if( (lit & 0xffffff) == 0) {
3867             /* lower byte is zero */
3868             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3869             i = ((lit >> 8*3) & 0xff) ^0x80;
3870             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3871             emitpcode(POC_ADDLW, popGetLit( 0x80));
3872             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3873             genSkipc(&rFalseIfx);
3874             
3875             
3876             if(ifx) ifx->generated = 1;
3877             return;
3878             
3879           }
3880           
3881         }
3882         
3883         
3884         if(lit & (0x80 << (size*8))) {
3885           /* lit is negative */
3886           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3887           
3888           //genSkipCond(&rFalseIfx,left,size,7);
3889           
3890           emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3891           
3892           if(rFalseIfx.condition)
3893             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3894           else
3895             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3896           
3897           
3898         } else {
3899           /* lit is positive */
3900           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3901           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3902           if(rFalseIfx.condition)
3903             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3904           else
3905             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3906           
3907         }
3908         
3909         /* There are no more special cases, so perform a general compare */
3910         
3911         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3912         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3913         
3914         while(size--) {
3915           
3916           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3917           emitSKPNZ;
3918           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3919         }
3920         //rFalseIfx.condition ^= 1;
3921         genSkipc(&rFalseIfx);
3922         
3923         emitpLabel(truelbl->key);
3924         
3925         if(ifx) ifx->generated = 1;
3926         return;
3927         
3928         
3929     }
3930     
3931     
3932     /* sign is out of the way. So now do an unsigned compare */
3933     DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3934     
3935     
3936     /* General case - compare to an unsigned literal on the right.*/
3937     
3938     i = (lit >> (size*8)) & 0xff;
3939     emitpcode(POC_MOVLW, popGetLit(i));
3940     emitpcode(POC_SUBFW, popGet(AOP(left),size));
3941     while(size--) {
3942       i = (lit >> (size*8)) & 0xff;
3943       
3944       if(i) {
3945         emitpcode(POC_MOVLW, popGetLit(i));
3946         emitSKPNZ;
3947         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3948       } else {
3949       /* this byte of the lit is zero, 
3950         *if it's not the last then OR in the variable */
3951         if(size)
3952           emitpcode(POC_IORFW, popGet(AOP(left),size));
3953       }
3954     }
3955     
3956     
3957     emitpLabel(lbl->key);
3958     //if(emitFinalCheck)
3959     genSkipc(&rFalseIfx);
3960     if(sign)
3961       emitpLabel(truelbl->key);
3962     
3963     if(ifx) ifx->generated = 1;
3964     return;
3965     
3966     
3967   }
3968 #endif  // _swapp
3969   
3970   if(AOP_TYPE(left) == AOP_LIT) {
3971     //symbol *lbl = newiTempLabel(NULL);
3972     
3973     //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3974     
3975     
3976     DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
3977     
3978     /* Special cases */
3979     if((lit == 0) && (sign == 0)){
3980       
3981       size--;
3982       emitpcode(POC_MOVFW, popGet(AOP(right),size));
3983       while(size) 
3984         emitpcode(POC_IORFW, popGet(AOP(right),--size));
3985       
3986       genSkipz2(&rFalseIfx,0);
3987       if(ifx) ifx->generated = 1;
3988       return;
3989     }
3990     
3991     if(size==1) {
3992       /* Special cases */
3993       lit &= 0xff;
3994       if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3995         /* degenerate compare can never be true */
3996         if(rFalseIfx.condition == 0)
3997           emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3998         
3999         if(ifx) ifx->generated = 1;
4000         return;
4001       }
4002       
4003       if(sign) {
4004         /* signed comparisons to a literal byte */
4005         
4006         int lp1 = (lit+1) & 0xff;
4007         
4008         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4009         switch (lp1) {
4010         case 0:
4011           rFalseIfx.condition ^= 1;
4012           genSkipCond(&rFalseIfx,right,0,7);
4013           break;
4014         case 0x7f:
4015           emitpcode(POC_MOVFW, popGet(AOP(right),0));
4016           emitpcode(POC_XORLW, popGetLit(0x7f));
4017           genSkipz2(&rFalseIfx,1);
4018           break;
4019         default:
4020           emitpcode(POC_MOVFW, popGet(AOP(right),0));
4021           emitpcode(POC_ADDLW, popGetLit(0x80));
4022           emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4023           rFalseIfx.condition ^= 1;
4024           genSkipc(&rFalseIfx);
4025           break;
4026         }
4027         if(ifx) ifx->generated = 1;
4028       } else {
4029         /* unsigned comparisons to a literal byte */
4030         
4031         switch(lit & 0xff ) {
4032         case 0:
4033           emitpcode(POC_MOVFW, popGet(AOP(right),0));
4034           genSkipz2(&rFalseIfx,0);
4035           if(ifx) ifx->generated = 1;
4036           break;
4037         case 0x7f:
4038           genSkipCond(&rFalseIfx,right,0,7);
4039           if(ifx) ifx->generated = 1;
4040           break;
4041           
4042         default:
4043           emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4044           emitpcode(POC_SUBFW, popGet(AOP(right),0));
4045           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4046           rFalseIfx.condition ^= 1;
4047           if (AOP_TYPE(result) == AOP_CRY) {
4048             genSkipc(&rFalseIfx);
4049             if(ifx) ifx->generated = 1;
4050           } else {
4051             DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4052             emitpcode(POC_CLRF, popGet(AOP(result),0));
4053             emitpcode(POC_RLF, popGet(AOP(result),0));
4054             emitpcode(POC_MOVLW, popGetLit(0x01));
4055             emitpcode(POC_XORWF, popGet(AOP(result),0));
4056           }       
4057           break;
4058         }
4059       }
4060       
4061       //goto check_carry;
4062       return;
4063       
4064     } else {
4065       
4066       /* Size is greater than 1 */
4067       
4068       if(sign) {
4069         int lp1 = lit+1;
4070         
4071         size--;
4072         
4073         if(lp1 == 0) {
4074           /* this means lit = 0xffffffff, or -1 */
4075           
4076           
4077           DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4078           rFalseIfx.condition ^= 1;
4079           genSkipCond(&rFalseIfx,right,size,7);
4080           if(ifx) ifx->generated = 1;
4081           return;
4082         }
4083         
4084         if(lit == 0) {
4085           int s = size;
4086           
4087           if(rFalseIfx.condition) {
4088             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4089             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4090           }
4091           
4092           emitpcode(POC_MOVFW, popGet(AOP(right),size));
4093           while(size--)
4094             emitpcode(POC_IORFW, popGet(AOP(right),size));
4095           
4096           
4097           emitSKPZ;
4098           if(rFalseIfx.condition) {
4099             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4100             emitpLabel(truelbl->key);
4101           }else {
4102             rFalseIfx.condition ^= 1;
4103             genSkipCond(&rFalseIfx,right,s,7);
4104           }
4105           
4106           if(ifx) ifx->generated = 1;
4107           return;
4108         }
4109         
4110         if((size == 1) &&  (0 == (lp1&0xff))) {
4111           /* lower byte of signed word is zero */
4112           DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4113           i = ((lp1 >> 8) & 0xff) ^0x80;
4114           emitpcode(POC_MOVFW, popGet(AOP(right),size));
4115           emitpcode(POC_ADDLW, popGetLit( 0x80));
4116           emitpcode(POC_ADDLW, popGetLit(0x100-i));
4117           rFalseIfx.condition ^= 1;
4118           genSkipc(&rFalseIfx);
4119           
4120           
4121           if(ifx) ifx->generated = 1;
4122           return;
4123         }
4124         
4125         if(lit & (0x80 << (size*8))) {
4126           /* Lit is less than zero */
4127           DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4128           //rFalseIfx.condition ^= 1;
4129           //genSkipCond(&rFalseIfx,left,size,7);
4130           //rFalseIfx.condition ^= 1;
4131           emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4132           //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4133           
4134           if(rFalseIfx.condition)
4135             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4136           else
4137             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4138           
4139           
4140         } else {
4141           /* Lit is greater than or equal to zero */
4142           DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4143           //rFalseIfx.condition ^= 1;
4144           //genSkipCond(&rFalseIfx,right,size,7);
4145           //rFalseIfx.condition ^= 1;
4146           
4147           //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4148           //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4149           
4150           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4151           if(rFalseIfx.condition)
4152             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4153           else
4154             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4155           
4156         }
4157         
4158         
4159         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4160         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4161         
4162         while(size--) {
4163           
4164           emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4165           emitSKPNZ;
4166           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4167         }
4168         rFalseIfx.condition ^= 1;
4169         //rFalseIfx.condition = 1;
4170         genSkipc(&rFalseIfx);
4171         
4172         emitpLabel(truelbl->key);
4173         
4174         if(ifx) ifx->generated = 1;
4175         return;
4176         // end of if (sign)
4177   } else {
4178     
4179     /* compare word or long to an unsigned literal on the right.*/
4180     
4181     
4182     size--;
4183     if(lit < 0xff) {
4184       DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4185       switch (lit) {
4186       case 0:
4187         break; /* handled above */
4188       /*
4189       case 0xff:
4190       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4191       while(size--)
4192       emitpcode(POC_IORFW, popGet(AOP(right),size));
4193       genSkipz2(&rFalseIfx,0);
4194       break;
4195       */
4196       default:
4197         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4198         while(--size)
4199           emitpcode(POC_IORFW, popGet(AOP(right),size));
4200         
4201         emitSKPZ;
4202         if(rFalseIfx.condition)
4203           emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4204         else
4205           emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4206         
4207         
4208         emitpcode(POC_MOVLW, popGetLit(lit+1));
4209         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4210         
4211         rFalseIfx.condition ^= 1;
4212         genSkipc(&rFalseIfx);
4213       }
4214       
4215       emitpLabel(truelbl->key);
4216       
4217       if(ifx) ifx->generated = 1;
4218       return;
4219     }
4220     
4221     
4222     lit++;
4223     DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4224     i = (lit >> (size*8)) & 0xff;
4225     
4226     emitpcode(POC_MOVLW, popGetLit(i));
4227     emitpcode(POC_SUBFW, popGet(AOP(right),size));
4228     
4229     while(size--) {
4230       i = (lit >> (size*8)) & 0xff;
4231       
4232       if(i) {
4233         emitpcode(POC_MOVLW, popGetLit(i));
4234         emitSKPNZ;
4235         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4236       } else {
4237       /* this byte of the lit is zero, 
4238         *if it's not the last then OR in the variable */
4239         if(size)
4240           emitpcode(POC_IORFW, popGet(AOP(right),size));
4241       }
4242     }
4243     
4244     
4245     emitpLabel(lbl->key);
4246     
4247     rFalseIfx.condition ^= 1;
4248     genSkipc(&rFalseIfx);
4249   }
4250   
4251   if(sign)
4252     emitpLabel(truelbl->key);
4253   if(ifx) ifx->generated = 1;
4254   return;
4255     }
4256   }
4257   /* Compare two variables */
4258   
4259   DEBUGpic14_emitcode(";sign","%d",sign);
4260   
4261   size--;
4262   if(sign) {
4263     /* Sigh. thus sucks... */
4264     if(size) {
4265       emitpcode(POC_MOVFW, popGet(AOP(left),size));
4266       emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4267       emitpcode(POC_MOVLW, popGetLit(0x80));
4268       emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4269       emitpcode(POC_XORFW, popGet(AOP(right),size));
4270       emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4271     } else {
4272       /* Signed char comparison */
4273       /* Special thanks to Nikolai Golovchenko for this snippet */
4274       emitpcode(POC_MOVFW, popGet(AOP(right),0));
4275       emitpcode(POC_SUBFW, popGet(AOP(left),0));
4276       emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4277       emitpcode(POC_XORFW, popGet(AOP(left),0));
4278       emitpcode(POC_XORFW, popGet(AOP(right),0));
4279       emitpcode(POC_ADDLW, popGetLit(0x80));
4280       
4281       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4282       genSkipc(&rFalseIfx);
4283       
4284       if(ifx) ifx->generated = 1;
4285       return;
4286     }
4287     
4288   } else {
4289     
4290     emitpcode(POC_MOVFW, popGet(AOP(right),size));
4291     emitpcode(POC_SUBFW, popGet(AOP(left),size));
4292   }
4293   
4294   
4295   /* The rest of the bytes of a multi-byte compare */
4296   while (size) {
4297     
4298     emitSKPZ;
4299     emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4300     size--;
4301     
4302     emitpcode(POC_MOVFW, popGet(AOP(right),size));
4303     emitpcode(POC_SUBFW, popGet(AOP(left),size));
4304     
4305     
4306   }
4307   
4308   emitpLabel(lbl->key);
4309   
4310   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4311   if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4312     (AOP_TYPE(result) == AOP_REG)) {
4313     emitpcode(POC_CLRF, popGet(AOP(result),0));
4314     emitpcode(POC_RLF, popGet(AOP(result),0));
4315   } else {
4316     genSkipc(&rFalseIfx);
4317   }       
4318   //genSkipc(&rFalseIfx);
4319   if(ifx) ifx->generated = 1;
4320   
4321   return;
4322   
4323   }
4324   
4325   // check_carry:
4326   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4327     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4328     pic14_outBitC(result);
4329   } else {
4330     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4331     /* if the result is used in the next
4332     ifx conditional branch then generate
4333     code a little differently */
4334     if (ifx )
4335       genIfxJump (ifx,"c");
4336     else
4337       pic14_outBitC(result);
4338     /* leave the result in acc */
4339   }
4340   
4341 }
4342
4343 /*-----------------------------------------------------------------*/
4344 /* genCmpGt :- greater than comparison                             */
4345 /*-----------------------------------------------------------------*/
4346 static void genCmpGt (iCode *ic, iCode *ifx)
4347 {
4348   operand *left, *right, *result;
4349   sym_link *letype , *retype;
4350   int sign ;
4351   
4352   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4353   left = IC_LEFT(ic);
4354   right= IC_RIGHT(ic);
4355   result = IC_RESULT(ic);
4356   
4357   letype = getSpec(operandType(left));
4358   retype =getSpec(operandType(right));
4359   sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4360   /* assign the amsops */
4361   aopOp (left,ic,FALSE);
4362   aopOp (right,ic,FALSE);
4363   aopOp (result,ic,TRUE);
4364   
4365   genCmp(right, left, result, ifx, sign);
4366   
4367   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4368   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4369   freeAsmop(result,NULL,ic,TRUE); 
4370 }
4371
4372 /*-----------------------------------------------------------------*/
4373 /* genCmpLt - less than comparisons                                */
4374 /*-----------------------------------------------------------------*/
4375 static void genCmpLt (iCode *ic, iCode *ifx)
4376 {
4377   operand *left, *right, *result;
4378   sym_link *letype , *retype;
4379   int sign ;
4380   
4381   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4382   left = IC_LEFT(ic);
4383   right= IC_RIGHT(ic);
4384   result = IC_RESULT(ic);
4385   
4386   letype = getSpec(operandType(left));
4387   retype =getSpec(operandType(right));
4388   sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4389   
4390   /* assign the amsops */
4391   aopOp (left,ic,FALSE);
4392   aopOp (right,ic,FALSE);
4393   aopOp (result,ic,TRUE);
4394   
4395   genCmp(left, right, result, ifx, sign);
4396   
4397   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4398   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4399   freeAsmop(result,NULL,ic,TRUE); 
4400 }
4401
4402 /*-----------------------------------------------------------------*/
4403 /* genc16bit2lit - compare a 16 bit value to a literal             */
4404 /*-----------------------------------------------------------------*/
4405 static void genc16bit2lit(operand *op, int lit, int offset)
4406 {
4407   int i;
4408   
4409   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4410   if( (lit&0xff) == 0) 
4411     i=1;
4412   else
4413     i=0;
4414   
4415   switch( BYTEofLONG(lit,i)) { 
4416   case 0:
4417     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4418     break;
4419   case 1:
4420     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4421     break;
4422   case 0xff:
4423     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4424     break;
4425   default:
4426     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4427     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4428   }
4429   
4430   i ^= 1;
4431   
4432   switch( BYTEofLONG(lit,i)) { 
4433   case 0:
4434     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4435     break;
4436   case 1:
4437     emitSKPNZ;
4438     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4439     break;
4440   case 0xff:
4441     emitSKPNZ;
4442     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4443     break;
4444   default:
4445     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4446     emitSKPNZ;
4447     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4448     
4449   }
4450   
4451 }
4452
4453 /*-----------------------------------------------------------------*/
4454 /* gencjneshort - compare and jump if not equal                    */
4455 /*-----------------------------------------------------------------*/
4456 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4457 {
4458   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4459   int offset = 0;
4460   int res_offset = 0;  /* the result may be a different size then left or right */
4461   int res_size = AOP_SIZE(result);
4462   resolvedIfx rIfx;
4463   symbol *lbl;
4464   
4465   unsigned long lit = 0L;
4466   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4467   DEBUGpic14_AopType(__LINE__,left,right,result);
4468   if(result)
4469     DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4470   resolveIfx(&rIfx,ifx);
4471   lbl =  newiTempLabel(NULL);
4472   
4473   
4474   /* if the left side is a literal or 
4475   if the right is in a pointer register and left 
4476   is not */
4477   if ((AOP_TYPE(left) == AOP_LIT) || 
4478     (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4479     operand *t = right;
4480     right = left;
4481     left = t;
4482   }
4483   if(AOP_TYPE(right) == AOP_LIT)
4484     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4485   
4486   /* if the right side is a literal then anything goes */
4487   if (AOP_TYPE(right) == AOP_LIT &&
4488     AOP_TYPE(left) != AOP_DIR ) {
4489     switch(size) {
4490     case 2:
4491       genc16bit2lit(left, lit, 0);
4492       emitSKPNZ;
4493       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4494       break;
4495     default:
4496       while (size--) {
4497         if(lit & 0xff) {
4498           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4499           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4500         } else {
4501           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4502         }
4503         
4504         emitSKPNZ;
4505         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4506         offset++;
4507         if(res_offset < res_size-1)
4508           res_offset++;
4509         lit >>= 8;
4510       }
4511       break;
4512     }
4513   }
4514   
4515   /* if the right side is in a register or in direct space or
4516   if the left is a pointer register & right is not */    
4517   else if (AOP_TYPE(right) == AOP_REG ||
4518     AOP_TYPE(right) == AOP_DIR || 
4519     (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4520     (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4521     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4522     int lbl_key = lbl->key;
4523     
4524     if(result) {
4525       emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4526       //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4527     }else {
4528       DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4529       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4530         __FUNCTION__,__LINE__);
4531       return;
4532     }
4533     
4534     /*     switch(size) { */
4535     /*     case 2: */
4536     /*       genc16bit2lit(left, lit, 0); */
4537     /*       emitSKPNZ; */
4538     /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4539     /*       break; */
4540     /*     default: */
4541     while (size--) {
4542       int emit_skip=1;
4543       if((AOP_TYPE(left) == AOP_DIR) && 
4544         ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4545         
4546         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4547         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4548         
4549       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4550         
4551         switch (lit & 0xff) {
4552         case 0:
4553           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4554           break;
4555         case 1:
4556           emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4557           emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4558           //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4559           emit_skip=0;
4560           break;
4561         case 0xff:
4562           emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4563           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4564           //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4565           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4566           emit_skip=0;
4567           break;
4568         default:
4569           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4570           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4571         }
4572         lit >>= 8;
4573         
4574       } else {
4575         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4576       }
4577       if(emit_skip) {
4578         if(AOP_TYPE(result) == AOP_CRY) {
4579           pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4580           if(rIfx.condition)
4581             emitSKPNZ;
4582           else
4583             emitSKPZ;
4584           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4585         } else {
4586           /* fix me. probably need to check result size too */
4587           //emitpcode(POC_CLRF,popGet(AOP(result),0));
4588           if(rIfx.condition)
4589             emitSKPZ;
4590           else
4591             emitSKPNZ;
4592           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4593           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4594         }
4595         if(ifx)
4596           ifx->generated=1;
4597       }
4598       emit_skip++;
4599       offset++;
4600       if(res_offset < res_size-1)
4601         res_offset++;
4602     }
4603     /*       break; */
4604     /*     } */
4605   } else if(AOP_TYPE(right) == AOP_REG &&
4606     AOP_TYPE(left) != AOP_DIR){
4607     
4608     while(size--) {
4609       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4610       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4611       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4612       if(rIfx.condition)
4613         emitSKPNZ;
4614       else
4615         emitSKPZ;
4616       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4617       offset++;
4618       if(res_offset < res_size-1)
4619         res_offset++;
4620     }
4621     
4622   }else{
4623     /* right is a pointer reg need both a & b */
4624     while(size--) {
4625       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4626       if(strcmp(l,"b"))
4627         pic14_emitcode("mov","b,%s",l);
4628       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4629       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4630       offset++;
4631     }
4632   }
4633   
4634   emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4635   if(!rIfx.condition)
4636     emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4637   
4638   emitpLabel(lbl->key);
4639   
4640   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4641   
4642   if(ifx)
4643     ifx->generated = 1;
4644 }
4645
4646 #if 0
4647 /*-----------------------------------------------------------------*/
4648 /* gencjne - compare and jump if not equal                         */
4649 /*-----------------------------------------------------------------*/
4650 static void gencjne(operand *left, operand *right, iCode *ifx)
4651 {
4652   symbol *tlbl  = newiTempLabel(NULL);
4653   
4654   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4655   gencjneshort(left, right, lbl);
4656   
4657   pic14_emitcode("mov","a,%s",one);
4658   pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4659   pic14_emitcode("","%05d_DS_:",lbl->key+100);
4660   pic14_emitcode("clr","a");
4661   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4662   
4663   emitpLabel(lbl->key);
4664   emitpLabel(tlbl->key);
4665   
4666 }
4667 #endif
4668
4669 /*-----------------------------------------------------------------*/
4670 /* genCmpEq - generates code for equal to                          */
4671 /*-----------------------------------------------------------------*/
4672 static void genCmpEq (iCode *ic, iCode *ifx)
4673 {
4674   operand *left, *right, *result;
4675   unsigned long lit = 0L;
4676   int size,offset=0;
4677   
4678   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4679   
4680   if(ifx)
4681     DEBUGpic14_emitcode ("; ifx is non-null","");
4682   else
4683     DEBUGpic14_emitcode ("; ifx is null","");
4684   
4685   aopOp((left=IC_LEFT(ic)),ic,FALSE);
4686   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4687   aopOp((result=IC_RESULT(ic)),ic,TRUE);
4688   
4689   size = max(AOP_SIZE(left),AOP_SIZE(right));
4690   
4691   DEBUGpic14_AopType(__LINE__,left,right,result);
4692   
4693   /* if literal, literal on the right or 
4694   if the right is in a pointer register and left 
4695   is not */
4696   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4697     (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4698     operand *tmp = right ;
4699     right = left;
4700     left = tmp;
4701   }
4702   
4703   
4704   if(ifx && !AOP_SIZE(result)){
4705     symbol *tlbl;
4706     /* if they are both bit variables */
4707     if (AOP_TYPE(left) == AOP_CRY &&
4708       ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4709       if(AOP_TYPE(right) == AOP_LIT){
4710         unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4711         if(lit == 0L){
4712           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4713           pic14_emitcode("cpl","c");
4714         } else if(lit == 1L) {
4715           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4716         } else {
4717           pic14_emitcode("clr","c");
4718         }
4719         /* AOP_TYPE(right) == AOP_CRY */
4720       } else {
4721         symbol *lbl = newiTempLabel(NULL);
4722         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4723         pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4724         pic14_emitcode("cpl","c");
4725         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4726       }
4727       /* if true label then we jump if condition
4728       supplied is true */
4729       tlbl = newiTempLabel(NULL);
4730       if ( IC_TRUE(ifx) ) {
4731         pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4732         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4733       } else {
4734         pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4735         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4736       }
4737       pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4738       
4739       {
4740         /* left and right are both bit variables, result is carry */
4741         resolvedIfx rIfx;
4742         
4743         resolveIfx(&rIfx,ifx);
4744         
4745         emitpcode(POC_MOVLW,popGet(AOP(left),0));
4746         emitpcode(POC_ANDFW,popGet(AOP(left),0));
4747         emitpcode(POC_BTFSC,popGet(AOP(right),0));
4748         emitpcode(POC_ANDLW,popGet(AOP(left),0));
4749         genSkipz2(&rIfx,0);
4750       }
4751     } else {
4752       
4753       /* They're not both bit variables. Is the right a literal? */
4754       if(AOP_TYPE(right) == AOP_LIT) {
4755         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4756         
4757         switch(size) {
4758           
4759         case 1:
4760           switch(lit & 0xff) {
4761           case 1:
4762             if ( IC_TRUE(ifx) ) {
4763               emitpcode(POC_DECFW,popGet(AOP(left),offset));
4764               emitSKPNZ;
4765               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4766             } else {
4767               emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4768               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4769             }
4770             break;
4771           case 0xff:
4772             if ( IC_TRUE(ifx) ) {
4773               emitpcode(POC_INCFW,popGet(AOP(left),offset));
4774               emitSKPNZ;
4775               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4776             } else {
4777               emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4778               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4779             }
4780             break;
4781           default:
4782             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4783             if(lit)
4784               emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4785             genSkip(ifx,'z');
4786           }
4787           
4788           
4789           /* end of size == 1 */
4790           break;
4791           
4792           case 2:
4793             genc16bit2lit(left,lit,offset);
4794             genSkip(ifx,'z');
4795             break;
4796             /* end of size == 2 */
4797             
4798           default:
4799             /* size is 4 */
4800             if(lit==0) {
4801               emitpcode(POC_MOVFW,popGet(AOP(left),0));
4802               emitpcode(POC_IORFW,popGet(AOP(left),1));
4803               emitpcode(POC_IORFW,popGet(AOP(left),2));
4804               emitpcode(POC_IORFW,popGet(AOP(left),3));
4805               
4806             } else {
4807               
4808               /* search for patterns that can be optimized */
4809               
4810               genc16bit2lit(left,lit,0);
4811               lit >>= 16;
4812               if(lit) {
4813                 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4814                 //genSkip(ifx,'z');
4815                 genc16bit2lit(left,lit,2);
4816               } else {
4817                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4818                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4819                 
4820               }
4821               
4822             }
4823             
4824             genSkip(ifx,'z');
4825         }
4826         
4827         ifx->generated = 1;
4828         goto release ;
4829         
4830         
4831       } else if(AOP_TYPE(right) == AOP_CRY ) {
4832         /* we know the left is not a bit, but that the right is */
4833         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4834         emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4835           popGet(AOP(right),offset));
4836         emitpcode(POC_XORLW,popGetLit(1));
4837         
4838         /* if the two are equal, then W will be 0 and the Z bit is set
4839         * we could test Z now, or go ahead and check the high order bytes if
4840         * the variable we're comparing is larger than a byte. */
4841         
4842         while(--size)
4843           emitpcode(POC_IORFW,popGet(AOP(left),offset));
4844         
4845         if ( IC_TRUE(ifx) ) {
4846           emitSKPNZ;
4847           emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4848           pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4849         } else {
4850           emitSKPZ;
4851           emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4852           pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4853         }
4854         
4855       } else {
4856         /* They're both variables that are larger than bits */
4857         int s = size;
4858         
4859         tlbl = newiTempLabel(NULL);
4860         
4861         while(size--) {
4862           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4863           emitpcode(POC_XORFW,popGet(AOP(right),offset));
4864           
4865           if ( IC_TRUE(ifx) ) {
4866             if(size) {
4867               emitSKPZ;
4868               emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4869               pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4870             } else {
4871               emitSKPNZ;
4872               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4873               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4874             }
4875           } else {
4876             emitSKPZ;
4877             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4878             pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4879           }
4880           offset++;
4881         }
4882         if(s>1 && IC_TRUE(ifx)) {
4883           emitpLabel(tlbl->key);
4884           pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4885         }
4886       }
4887     }
4888     /* mark the icode as generated */
4889     ifx->generated = 1;
4890     goto release ;
4891   }
4892   
4893   /* if they are both bit variables */
4894   if (AOP_TYPE(left) == AOP_CRY &&
4895     ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4896     if(AOP_TYPE(right) == AOP_LIT){
4897       unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4898       if(lit == 0L){
4899         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4900         pic14_emitcode("cpl","c");
4901       } else if(lit == 1L) {
4902         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4903       } else {
4904         pic14_emitcode("clr","c");
4905       }
4906       /* AOP_TYPE(right) == AOP_CRY */
4907     } else {
4908       symbol *lbl = newiTempLabel(NULL);
4909       pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4910       pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4911       pic14_emitcode("cpl","c");
4912       pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4913     }
4914     /* c = 1 if egal */
4915     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4916       pic14_outBitC(result);
4917       goto release ;
4918     }
4919     if (ifx) {
4920       genIfxJump (ifx,"c");
4921       goto release ;
4922     }
4923     /* if the result is used in an arithmetic operation
4924     then put the result in place */
4925     pic14_outBitC(result);
4926   } else {
4927     
4928     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4929     gencjne(left,right,result,ifx);
4930     /*
4931     if(ifx) 
4932     gencjne(left,right,newiTempLabel(NULL));
4933     else {
4934     if(IC_TRUE(ifx)->key)
4935     gencjne(left,right,IC_TRUE(ifx)->key);
4936     else
4937     gencjne(left,right,IC_FALSE(ifx)->key);
4938     ifx->generated = 1;
4939     goto release ;
4940     }
4941     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4942     aopPut(AOP(result),"a",0);
4943     goto release ;
4944     }
4945     
4946       if (ifx) {
4947       genIfxJump (ifx,"a");
4948       goto release ;
4949       }
4950     */
4951     /* if the result is used in an arithmetic operation
4952     then put the result in place */
4953     /*
4954     if (AOP_TYPE(result) != AOP_CRY) 
4955     pic14_outAcc(result);
4956     */
4957     /* leave the result in acc */
4958   }
4959   
4960 release:
4961   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4962   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4963   freeAsmop(result,NULL,ic,TRUE);
4964 }
4965
4966 /*-----------------------------------------------------------------*/
4967 /* ifxForOp - returns the icode containing the ifx for operand     */
4968 /*-----------------------------------------------------------------*/
4969 static iCode *ifxForOp ( operand *op, iCode *ic )
4970 {
4971   /* if true symbol then needs to be assigned */
4972   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4973   if (IS_TRUE_SYMOP(op))
4974     return NULL ;
4975   
4976     /* if this has register type condition and
4977     the next instruction is ifx with the same operand
4978   and live to of the operand is upto the ifx only then */
4979   if (ic->next &&
4980     ic->next->op == IFX &&
4981     IC_COND(ic->next)->key == op->key &&
4982     OP_SYMBOL(op)->liveTo <= ic->next->seq )
4983     return ic->next;
4984   
4985   if (ic->next &&
4986     ic->next->op == IFX &&
4987     IC_COND(ic->next)->key == op->key) {
4988     DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4989     return ic->next;
4990   }
4991   
4992   DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4993   if (ic->next &&
4994     ic->next->op == IFX)
4995     DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4996   
4997   if (ic->next &&
4998     ic->next->op == IFX &&
4999     IC_COND(ic->next)->key == op->key) {
5000     DEBUGpic14_emitcode ("; "," key is okay");
5001     DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5002       OP_SYMBOL(op)->liveTo,
5003       ic->next->seq);
5004   }
5005   
5006   
5007   return NULL;
5008 }
5009 /*-----------------------------------------------------------------*/
5010 /* genAndOp - for && operation                                     */
5011 /*-----------------------------------------------------------------*/
5012 static void genAndOp (iCode *ic)
5013 {
5014   operand *left,*right, *result;
5015   /*     symbol *tlbl; */
5016   
5017   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5018   /* note here that && operations that are in an
5019   if statement are taken away by backPatchLabels
5020   only those used in arthmetic operations remain */
5021   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5022   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5023   aopOp((result=IC_RESULT(ic)),ic,FALSE);
5024   
5025   DEBUGpic14_AopType(__LINE__,left,right,result);
5026   
5027   emitpcode(POC_MOVFW,popGet(AOP(left),0));
5028   emitpcode(POC_ANDFW,popGet(AOP(right),0));
5029   emitpcode(POC_MOVWF,popGet(AOP(result),0));
5030   
5031   /* if both are bit variables */
5032   /*     if (AOP_TYPE(left) == AOP_CRY && */
5033   /*         AOP_TYPE(right) == AOP_CRY ) { */
5034   /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5035   /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5036   /*         pic14_outBitC(result); */
5037   /*     } else { */
5038   /*         tlbl = newiTempLabel(NULL); */
5039   /*         pic14_toBoolean(left);     */
5040   /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5041   /*         pic14_toBoolean(right); */
5042   /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5043   /*         pic14_outBitAcc(result); */
5044   /*     } */
5045   
5046   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5047   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5048   freeAsmop(result,NULL,ic,TRUE);
5049 }
5050
5051
5052 /*-----------------------------------------------------------------*/
5053 /* genOrOp - for || operation                                      */
5054 /*-----------------------------------------------------------------*/
5055 /*
5056 tsd pic port -
5057 modified this code, but it doesn't appear to ever get called
5058 */
5059
5060 static void genOrOp (iCode *ic)
5061 {
5062   operand *left,*right, *result;
5063   symbol *tlbl;
5064   
5065   /* note here that || operations that are in an
5066   if statement are taken away by backPatchLabels
5067   only those used in arthmetic operations remain */
5068   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5069   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5070   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5071   aopOp((result=IC_RESULT(ic)),ic,FALSE);
5072   
5073   DEBUGpic14_AopType(__LINE__,left,right,result);
5074   
5075   /* if both are bit variables */
5076   if (AOP_TYPE(left) == AOP_CRY &&
5077     AOP_TYPE(right) == AOP_CRY ) {
5078     pic14_emitcode("clrc","");
5079     pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5080       AOP(left)->aopu.aop_dir,
5081       AOP(left)->aopu.aop_dir);
5082     pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5083       AOP(right)->aopu.aop_dir,
5084       AOP(right)->aopu.aop_dir);
5085     pic14_emitcode("setc","");
5086     
5087   } else {
5088     tlbl = newiTempLabel(NULL);
5089     pic14_toBoolean(left);
5090     emitSKPZ;
5091     pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5092     pic14_toBoolean(right);
5093     pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5094     
5095     pic14_outBitAcc(result);
5096   }
5097   
5098   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5099   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5100   freeAsmop(result,NULL,ic,TRUE);            
5101 }
5102
5103 /*-----------------------------------------------------------------*/
5104 /* isLiteralBit - test if lit == 2^n                               */
5105 /*-----------------------------------------------------------------*/
5106 static int isLiteralBit(unsigned long lit)
5107 {
5108   unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5109     0x100L,0x200L,0x400L,0x800L,
5110     0x1000L,0x2000L,0x4000L,0x8000L,
5111     0x10000L,0x20000L,0x40000L,0x80000L,
5112     0x100000L,0x200000L,0x400000L,0x800000L,
5113     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5114     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5115   int idx;
5116   
5117   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5118   for(idx = 0; idx < 32; idx++)
5119     if(lit == pw[idx])
5120       return idx+1;
5121     return 0;
5122 }
5123
5124 /*-----------------------------------------------------------------*/
5125 /* continueIfTrue -                                                */
5126 /*-----------------------------------------------------------------*/
5127 static void continueIfTrue (iCode *ic)
5128 {
5129   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5130   if(IC_TRUE(ic))
5131     pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5132   ic->generated = 1;
5133 }
5134
5135 /*-----------------------------------------------------------------*/
5136 /* jmpIfTrue -                                                     */
5137 /*-----------------------------------------------------------------*/
5138 static void jumpIfTrue (iCode *ic)
5139 {
5140   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5141   if(!IC_TRUE(ic))
5142     pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5143   ic->generated = 1;
5144 }
5145
5146 /*-----------------------------------------------------------------*/
5147 /* jmpTrueOrFalse -                                                */
5148 /*-----------------------------------------------------------------*/
5149 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5150 {
5151   // ugly but optimized by peephole
5152   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5153   if(IC_TRUE(ic)){
5154     symbol *nlbl = newiTempLabel(NULL);
5155     pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5156     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5157     pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5158     pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5159   }
5160   else{
5161     pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5162     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5163   }
5164   ic->generated = 1;
5165 }
5166
5167 /*-----------------------------------------------------------------*/
5168 /* genAnd  - code for and                                          */
5169 /*-----------------------------------------------------------------*/
5170 static void genAnd (iCode *ic, iCode *ifx)
5171 {
5172   operand *left, *right, *result;
5173   int size, offset=0;  
5174   unsigned long lit = 0L;
5175   int bytelit = 0;
5176   resolvedIfx rIfx;
5177   
5178   
5179   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5180   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5181   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5182   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5183   
5184   resolveIfx(&rIfx,ifx);
5185   
5186   /* if left is a literal & right is not then exchange them */
5187   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5188     AOP_NEEDSACC(left)) {
5189     operand *tmp = right ;
5190     right = left;
5191     left = tmp;
5192   }
5193   
5194   /* if result = right then exchange them */
5195   if(pic14_sameRegs(AOP(result),AOP(right))){
5196     operand *tmp = right ;
5197     right = left;
5198     left = tmp;
5199   }
5200   
5201   /* if right is bit then exchange them */
5202   if (AOP_TYPE(right) == AOP_CRY &&
5203     AOP_TYPE(left) != AOP_CRY){
5204     operand *tmp = right ;
5205     right = left;
5206     left = tmp;
5207   }
5208   if(AOP_TYPE(right) == AOP_LIT)
5209     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5210   
5211   size = AOP_SIZE(result);
5212   
5213   DEBUGpic14_AopType(__LINE__,left,right,result);
5214   
5215   // if(bit & yy)
5216   // result = bit & yy;
5217   if (AOP_TYPE(left) == AOP_CRY){
5218     // c = bit & literal;
5219     if(AOP_TYPE(right) == AOP_LIT){
5220       if(lit & 1) {
5221         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5222           // no change
5223           goto release;
5224         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5225       } else {
5226         // bit(result) = 0;
5227         if(size && (AOP_TYPE(result) == AOP_CRY)){
5228           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5229           goto release;
5230         }
5231         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5232           jumpIfTrue(ifx);
5233           goto release;
5234         }
5235         pic14_emitcode("clr","c");
5236       }
5237     } else {
5238       if (AOP_TYPE(right) == AOP_CRY){
5239         // c = bit & bit;
5240         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5241         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5242       } else {
5243         // c = bit & val;
5244         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5245         // c = lsb
5246         pic14_emitcode("rrc","a");
5247         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5248       }
5249     }
5250     // bit = c
5251     // val = c
5252     if(size)
5253       pic14_outBitC(result);
5254     // if(bit & ...)
5255     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5256       genIfxJump(ifx, "c");           
5257     goto release ;
5258   }
5259   
5260   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5261   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5262   if((AOP_TYPE(right) == AOP_LIT) &&
5263     (AOP_TYPE(result) == AOP_CRY) &&
5264     (AOP_TYPE(left) != AOP_CRY)){
5265     int posbit = isLiteralBit(lit);
5266     /* left &  2^n */
5267     if(posbit){
5268       posbit--;
5269       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5270       // bit = left & 2^n
5271       if(size)
5272         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5273       // if(left &  2^n)
5274       else{
5275         if(ifx){
5276           int offset = 0;
5277           while (posbit > 7) {
5278             posbit -= 8;
5279             offset++;
5280           }
5281           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5282             newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5283           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5284           
5285           ifx->generated = 1;
5286         }
5287         goto release;
5288       }
5289     } else {
5290       symbol *tlbl = newiTempLabel(NULL);
5291       int sizel = AOP_SIZE(left);
5292       if(size)
5293         pic14_emitcode("setb","c");
5294       while(sizel--){
5295         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5296           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5297           // byte ==  2^n ?
5298           if((posbit = isLiteralBit(bytelit)) != 0)
5299             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5300           else{
5301             if(bytelit != 0x0FFL)
5302               pic14_emitcode("anl","a,%s",
5303               aopGet(AOP(right),offset,FALSE,TRUE));
5304             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5305           }
5306         }
5307         offset++;
5308       }
5309       // bit = left & literal
5310       if(size){
5311         pic14_emitcode("clr","c");
5312         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5313       }
5314       // if(left & literal)
5315       else{
5316         if(ifx)
5317           jmpTrueOrFalse(ifx, tlbl);
5318         goto release ;
5319       }
5320     }
5321     pic14_outBitC(result);
5322     goto release ;
5323   }
5324   
5325   /* if left is same as result */
5326   if(pic14_sameRegs(AOP(result),AOP(left))){
5327     int know_W = -1;
5328     for(;size--; offset++,lit>>=8) {
5329       if(AOP_TYPE(right) == AOP_LIT){
5330         switch(lit & 0xff) {
5331         case 0x00:
5332           /*  and'ing with 0 has clears the result */
5333           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5334           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5335           break;
5336         case 0xff:
5337           /* and'ing with 0xff is a nop when the result and left are the same */
5338           break;
5339           
5340         default:
5341           {
5342             int p = my_powof2( (~lit) & 0xff );
5343             if(p>=0) {
5344               /* only one bit is set in the literal, so use a bcf instruction */
5345               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5346               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5347               
5348             } else {
5349               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5350               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5351               if(know_W != (int)(lit&0xff))
5352                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5353               know_W = lit &0xff;
5354               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5355             }
5356           }    
5357         }
5358       } else {
5359         if (AOP_TYPE(left) == AOP_ACC) {
5360           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5361         } else {        
5362           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5363           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5364           
5365         }
5366       }
5367     }
5368     
5369   } else {
5370     // left & result in different registers
5371     if(AOP_TYPE(result) == AOP_CRY){
5372       // result = bit
5373       // if(size), result in bit
5374       // if(!size && ifx), conditional oper: if(left & right)
5375       symbol *tlbl = newiTempLabel(NULL);
5376       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5377       if(size)
5378         pic14_emitcode("setb","c");
5379       while(sizer--){
5380         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5381         pic14_emitcode("anl","a,%s",
5382           aopGet(AOP(left),offset,FALSE,FALSE));
5383         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5384         offset++;
5385       }
5386       if(size){
5387         CLRC;
5388         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5389         pic14_outBitC(result);
5390       } else if(ifx)
5391         jmpTrueOrFalse(ifx, tlbl);
5392     } else {
5393       for(;(size--);offset++) {
5394         // normal case
5395         // result = left & right
5396         if(AOP_TYPE(right) == AOP_LIT){
5397           int t = (lit >> (offset*8)) & 0x0FFL;
5398           switch(t) { 
5399           case 0x00:
5400             pic14_emitcode("clrf","%s",
5401               aopGet(AOP(result),offset,FALSE,FALSE));
5402             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5403             break;
5404           case 0xff:
5405             if(AOP_TYPE(left) != AOP_ACC) {
5406               pic14_emitcode("movf","%s,w",
5407                 aopGet(AOP(left),offset,FALSE,FALSE));
5408               pic14_emitcode("movwf","%s",
5409                 aopGet(AOP(result),offset,FALSE,FALSE));
5410               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5411             }
5412             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5413             break;
5414           default:
5415             if(AOP_TYPE(left) == AOP_ACC) {
5416               emitpcode(POC_ANDLW, popGetLit(t));
5417             } else {
5418               pic14_emitcode("movlw","0x%x",t);
5419               pic14_emitcode("andwf","%s,w",
5420                 aopGet(AOP(left),offset,FALSE,FALSE));
5421               pic14_emitcode("movwf","%s",
5422                 aopGet(AOP(result),offset,FALSE,FALSE));
5423               
5424               emitpcode(POC_MOVLW, popGetLit(t));
5425               emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5426             }
5427             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5428           }
5429           continue;
5430         }
5431         
5432         if (AOP_TYPE(left) == AOP_ACC) {
5433           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5434           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5435         } else {
5436           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5437           pic14_emitcode("andwf","%s,w",
5438             aopGet(AOP(left),offset,FALSE,FALSE));
5439           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5440           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5441         }
5442         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5443         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5444       }
5445     }
5446   }
5447   
5448 release :
5449   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5450   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5451   freeAsmop(result,NULL,ic,TRUE);     
5452 }
5453
5454 /*-----------------------------------------------------------------*/
5455 /* genOr  - code for or                                            */
5456 /*-----------------------------------------------------------------*/
5457 static void genOr (iCode *ic, iCode *ifx)
5458 {
5459   operand *left, *right, *result;
5460   int size, offset=0;
5461   unsigned long lit = 0L;
5462   
5463   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5464   
5465   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5466   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5467   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5468   
5469   DEBUGpic14_AopType(__LINE__,left,right,result);
5470   
5471   /* if left is a literal & right is not then exchange them */
5472   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5473     AOP_NEEDSACC(left)) {
5474     operand *tmp = right ;
5475     right = left;
5476     left = tmp;
5477   }
5478   
5479   /* if result = right then exchange them */
5480   if(pic14_sameRegs(AOP(result),AOP(right))){
5481     operand *tmp = right ;
5482     right = left;
5483     left = tmp;
5484   }
5485   
5486   /* if right is bit then exchange them */
5487   if (AOP_TYPE(right) == AOP_CRY &&
5488     AOP_TYPE(left) != AOP_CRY){
5489     operand *tmp = right ;
5490     right = left;
5491     left = tmp;
5492   }
5493   
5494   DEBUGpic14_AopType(__LINE__,left,right,result);
5495   
5496   if(AOP_TYPE(right) == AOP_LIT)
5497     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5498   
5499   size = AOP_SIZE(result);
5500   
5501   // if(bit | yy)
5502   // xx = bit | yy;
5503   if (AOP_TYPE(left) == AOP_CRY){
5504     if(AOP_TYPE(right) == AOP_LIT){
5505       // c = bit & literal;
5506       if(lit){
5507         // lit != 0 => result = 1
5508         if(AOP_TYPE(result) == AOP_CRY){
5509           if(size)
5510             emitpcode(POC_BSF, popGet(AOP(result),0));
5511           //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5512           //   AOP(result)->aopu.aop_dir,
5513           //   AOP(result)->aopu.aop_dir);
5514           else if(ifx)
5515             continueIfTrue(ifx);
5516           goto release;
5517         }
5518       } else {
5519         // lit == 0 => result = left
5520         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5521           goto release;
5522         pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5523       }
5524     } else {
5525       if (AOP_TYPE(right) == AOP_CRY){
5526         if(pic14_sameRegs(AOP(result),AOP(left))){
5527           // c = bit | bit;
5528           emitpcode(POC_BCF,   popGet(AOP(result),0));
5529           emitpcode(POC_BTFSC, popGet(AOP(right),0));
5530           emitpcode(POC_BSF,   popGet(AOP(result),0));
5531           
5532           pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5533             AOP(result)->aopu.aop_dir,
5534             AOP(result)->aopu.aop_dir);
5535           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5536             AOP(right)->aopu.aop_dir,
5537             AOP(right)->aopu.aop_dir);
5538           pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5539             AOP(result)->aopu.aop_dir,
5540             AOP(result)->aopu.aop_dir);
5541         } else {
5542           if( AOP_TYPE(result) == AOP_ACC) {
5543             emitpcode(POC_MOVLW, popGetLit(0));
5544             emitpcode(POC_BTFSS, popGet(AOP(right),0));
5545             emitpcode(POC_BTFSC, popGet(AOP(left),0));
5546             emitpcode(POC_MOVLW, popGetLit(1));
5547             
5548           } else {
5549             
5550             emitpcode(POC_BCF,   popGet(AOP(result),0));
5551             emitpcode(POC_BTFSS, popGet(AOP(right),0));
5552             emitpcode(POC_BTFSC, popGet(AOP(left),0));
5553             emitpcode(POC_BSF,   popGet(AOP(result),0));
5554             
5555             pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5556               AOP(result)->aopu.aop_dir,
5557               AOP(result)->aopu.aop_dir);
5558             pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5559               AOP(right)->aopu.aop_dir,
5560               AOP(right)->aopu.aop_dir);
5561             pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5562               AOP(left)->aopu.aop_dir,
5563               AOP(left)->aopu.aop_dir);
5564             pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5565               AOP(result)->aopu.aop_dir,
5566               AOP(result)->aopu.aop_dir);
5567           }
5568         }
5569       } else {
5570         // c = bit | val;
5571         symbol *tlbl = newiTempLabel(NULL);
5572         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5573         
5574         
5575         emitpcode(POC_BCF,   popGet(AOP(result),0));
5576         if( AOP_TYPE(right) == AOP_ACC) {
5577           emitpcode(POC_IORLW, popGetLit(0));
5578           emitSKPNZ;
5579           emitpcode(POC_BTFSC, popGet(AOP(left),0));
5580           emitpcode(POC_BSF,   popGet(AOP(result),0));
5581         }
5582         
5583         
5584         
5585         if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5586           pic14_emitcode(";XXX setb","c");
5587         pic14_emitcode(";XXX jb","%s,%05d_DS_",
5588           AOP(left)->aopu.aop_dir,tlbl->key+100);
5589         pic14_toBoolean(right);
5590         pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5591         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5592           jmpTrueOrFalse(ifx, tlbl);
5593           goto release;
5594         } else {
5595           CLRC;
5596           pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5597         }
5598       }
5599     }
5600     // bit = c
5601     // val = c
5602     if(size)
5603       pic14_outBitC(result);
5604     // if(bit | ...)
5605     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5606       genIfxJump(ifx, "c");           
5607     goto release ;
5608   }
5609   
5610   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5611   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5612   if((AOP_TYPE(right) == AOP_LIT) &&
5613     (AOP_TYPE(result) == AOP_CRY) &&
5614     (AOP_TYPE(left) != AOP_CRY)){
5615     if(lit){
5616       pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5617       // result = 1
5618       if(size)
5619         pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5620       else 
5621         continueIfTrue(ifx);
5622       goto release;
5623     } else {
5624       pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5625       // lit = 0, result = boolean(left)
5626       if(size)
5627         pic14_emitcode(";XXX setb","c");
5628       pic14_toBoolean(right);
5629       if(size){
5630         symbol *tlbl = newiTempLabel(NULL);
5631         pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5632         CLRC;
5633         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5634       } else {
5635         genIfxJump (ifx,"a");
5636         goto release;
5637       }
5638     }
5639     pic14_outBitC(result);
5640     goto release ;
5641   }
5642   
5643   /* if left is same as result */
5644   if(pic14_sameRegs(AOP(result),AOP(left))){
5645     int know_W = -1;
5646     for(;size--; offset++,lit>>=8) {
5647       if(AOP_TYPE(right) == AOP_LIT){
5648         if((lit & 0xff) == 0)
5649           /*  or'ing with 0 has no effect */
5650           continue;
5651         else {
5652           int p = my_powof2(lit & 0xff);
5653           if(p>=0) {
5654             /* only one bit is set in the literal, so use a bsf instruction */
5655             emitpcode(POC_BSF,
5656               newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5657           } else {
5658             if(know_W != (int)(lit & 0xff))
5659               emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5660             know_W = lit & 0xff;
5661             emitpcode(POC_IORWF, popGet(AOP(left),offset));
5662           }
5663           
5664         }
5665       } else {
5666         if (AOP_TYPE(left) == AOP_ACC) {
5667           emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5668           pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5669         } else {        
5670           emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5671           emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5672           
5673           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5674           pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5675           
5676         }
5677       }
5678     }
5679   } else {
5680     // left & result in different registers
5681     if(AOP_TYPE(result) == AOP_CRY){
5682       // result = bit
5683       // if(size), result in bit
5684       // if(!size && ifx), conditional oper: if(left | right)
5685       symbol *tlbl = newiTempLabel(NULL);
5686       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5687       pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5688       
5689       
5690       if(size)
5691         pic14_emitcode(";XXX setb","c");
5692       while(sizer--){
5693         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5694         pic14_emitcode(";XXX orl","a,%s",
5695           aopGet(AOP(left),offset,FALSE,FALSE));
5696         pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5697         offset++;
5698       }
5699       if(size){
5700         CLRC;
5701         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5702         pic14_outBitC(result);
5703       } else if(ifx)
5704         jmpTrueOrFalse(ifx, tlbl);
5705     } else for(;(size--);offset++){
5706       // normal case
5707       // result = left & right
5708       if(AOP_TYPE(right) == AOP_LIT){
5709         int t = (lit >> (offset*8)) & 0x0FFL;
5710         switch(t) { 
5711         case 0x00:
5712           if (AOP_TYPE(left) != AOP_ACC) {
5713             emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5714           }
5715           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5716           
5717           break;
5718         default:
5719           if (AOP_TYPE(left) == AOP_ACC) {
5720             emitpcode(POC_IORLW,  popGetLit(t));
5721           } else {
5722             emitpcode(POC_MOVLW,  popGetLit(t));
5723             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5724           }
5725           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
5726         }
5727         continue;
5728       }
5729       
5730       // faster than result <- left, anl result,right
5731       // and better if result is SFR
5732       if (AOP_TYPE(left) == AOP_ACC) {
5733         emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5734         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5735       } else {
5736         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5737         emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5738         
5739         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5740         pic14_emitcode("iorwf","%s,w",
5741           aopGet(AOP(left),offset,FALSE,FALSE));
5742       }
5743       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5744       pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5745     }
5746   }
5747   
5748 release :
5749   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5750   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5751   freeAsmop(result,NULL,ic,TRUE);     
5752 }
5753
5754 /*-----------------------------------------------------------------*/
5755 /* genXor - code for xclusive or                                   */
5756 /*-----------------------------------------------------------------*/
5757 static void genXor (iCode *ic, iCode *ifx)
5758 {
5759   operand *left, *right, *result;
5760   int size, offset=0;
5761   unsigned long lit = 0L;
5762   
5763   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5764   
5765   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5766   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5767   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5768   
5769   /* if left is a literal & right is not ||
5770   if left needs acc & right does not */
5771   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5772     (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5773     operand *tmp = right ;
5774     right = left;
5775     left = tmp;
5776   }
5777   
5778   /* if result = right then exchange them */
5779   if(pic14_sameRegs(AOP(result),AOP(right))){
5780     operand *tmp = right ;
5781     right = left;
5782     left = tmp;
5783   }
5784   
5785   /* if right is bit then exchange them */
5786   if (AOP_TYPE(right) == AOP_CRY &&
5787     AOP_TYPE(left) != AOP_CRY){
5788     operand *tmp = right ;
5789     right = left;
5790     left = tmp;
5791   }
5792   if(AOP_TYPE(right) == AOP_LIT)
5793     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5794   
5795   size = AOP_SIZE(result);
5796   
5797   // if(bit ^ yy)
5798   // xx = bit ^ yy;
5799   if (AOP_TYPE(left) == AOP_CRY){
5800     if(AOP_TYPE(right) == AOP_LIT){
5801       // c = bit & literal;
5802       if(lit>>1){
5803         // lit>>1  != 0 => result = 1
5804         if(AOP_TYPE(result) == AOP_CRY){
5805           if(size)
5806           {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5807           pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5808           else if(ifx)
5809             continueIfTrue(ifx);
5810           goto release;
5811         }
5812         pic14_emitcode("setb","c");
5813       } else{
5814         // lit == (0 or 1)
5815         if(lit == 0){
5816           // lit == 0, result = left
5817           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5818             goto release;
5819           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5820         } else{
5821           // lit == 1, result = not(left)
5822           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5823             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5824             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5825             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5826             goto release;
5827           } else {
5828             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5829             pic14_emitcode("cpl","c");
5830           }
5831         }
5832       }
5833       
5834     } else {
5835       // right != literal
5836       symbol *tlbl = newiTempLabel(NULL);
5837       if (AOP_TYPE(right) == AOP_CRY){
5838         // c = bit ^ bit;
5839         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5840       }
5841       else{
5842         int sizer = AOP_SIZE(right);
5843         // c = bit ^ val
5844         // if val>>1 != 0, result = 1
5845         pic14_emitcode("setb","c");
5846         while(sizer){
5847           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5848           if(sizer == 1)
5849             // test the msb of the lsb
5850             pic14_emitcode("anl","a,#0xfe");
5851           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5852           sizer--;
5853         }
5854         // val = (0,1)
5855         pic14_emitcode("rrc","a");
5856       }
5857       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5858       pic14_emitcode("cpl","c");
5859       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5860     }
5861     // bit = c
5862     // val = c
5863     if(size)
5864       pic14_outBitC(result);
5865     // if(bit | ...)
5866     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5867       genIfxJump(ifx, "c");           
5868     goto release ;
5869   }
5870   
5871   if(pic14_sameRegs(AOP(result),AOP(left))){
5872     /* if left is same as result */
5873     for(;size--; offset++) {
5874       if(AOP_TYPE(right) == AOP_LIT){
5875         int t  = (lit >> (offset*8)) & 0x0FFL;
5876         if(t == 0x00L)
5877           continue;
5878         else
5879           if (IS_AOP_PREG(left)) {
5880             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5881             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5882             aopPut(AOP(result),"a",offset);
5883           } else {
5884             emitpcode(POC_MOVLW, popGetLit(t));
5885             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5886             pic14_emitcode("xrl","%s,%s",
5887               aopGet(AOP(left),offset,FALSE,TRUE),
5888               aopGet(AOP(right),offset,FALSE,FALSE));
5889           }
5890       } else {
5891         if (AOP_TYPE(left) == AOP_ACC)
5892           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5893         else {
5894           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5895           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5896           /*
5897           if (IS_AOP_PREG(left)) {
5898           pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5899           aopPut(AOP(result),"a",offset);
5900           } else
5901           pic14_emitcode("xrl","%s,a",
5902           aopGet(AOP(left),offset,FALSE,TRUE));
5903           */
5904         }
5905       }
5906     }
5907   } else {
5908     // left & result in different registers
5909     if(AOP_TYPE(result) == AOP_CRY){
5910       // result = bit
5911       // if(size), result in bit
5912       // if(!size && ifx), conditional oper: if(left ^ right)
5913       symbol *tlbl = newiTempLabel(NULL);
5914       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5915       if(size)
5916         pic14_emitcode("setb","c");
5917       while(sizer--){
5918         if((AOP_TYPE(right) == AOP_LIT) &&
5919           (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5920           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5921         } else {
5922           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5923           pic14_emitcode("xrl","a,%s",
5924             aopGet(AOP(left),offset,FALSE,FALSE));
5925         }
5926         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5927         offset++;
5928       }
5929       if(size){
5930         CLRC;
5931         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5932         pic14_outBitC(result);
5933       } else if(ifx)
5934         jmpTrueOrFalse(ifx, tlbl);
5935     } else for(;(size--);offset++){
5936       // normal case
5937       // result = left & right
5938       if(AOP_TYPE(right) == AOP_LIT){
5939         int t = (lit >> (offset*8)) & 0x0FFL;
5940         switch(t) { 
5941         case 0x00:
5942           if (AOP_TYPE(left) != AOP_ACC) {
5943             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5944           }
5945           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5946           pic14_emitcode("movf","%s,w",
5947             aopGet(AOP(left),offset,FALSE,FALSE));
5948           pic14_emitcode("movwf","%s",
5949             aopGet(AOP(result),offset,FALSE,FALSE));
5950           break;
5951         case 0xff:
5952           if (AOP_TYPE(left) == AOP_ACC) {
5953             emitpcode(POC_XORLW, popGetLit(t));
5954           } else {
5955             emitpcode(POC_COMFW,popGet(AOP(left),offset));
5956           }
5957           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5958           break;
5959         default:
5960           if (AOP_TYPE(left) == AOP_ACC) {
5961             emitpcode(POC_XORLW, popGetLit(t));
5962           } else {
5963             emitpcode(POC_MOVLW, popGetLit(t));
5964             emitpcode(POC_XORFW,popGet(AOP(left),offset));
5965           }
5966           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5967           pic14_emitcode("movlw","0x%x",t);
5968           pic14_emitcode("xorwf","%s,w",
5969             aopGet(AOP(left),offset,FALSE,FALSE));
5970           pic14_emitcode("movwf","%s",
5971             aopGet(AOP(result),offset,FALSE,FALSE));
5972           
5973         }
5974         continue;
5975       }
5976       
5977       // faster than result <- left, anl result,right
5978       // and better if result is SFR
5979       if (AOP_TYPE(left) == AOP_ACC) {
5980         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5981         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5982       } else {
5983         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5984         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5985         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5986         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5987       }
5988       if ( AOP_TYPE(result) != AOP_ACC){
5989         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5990         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5991       }
5992     }
5993   }
5994   
5995 release :
5996   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5997   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5998   freeAsmop(result,NULL,ic,TRUE);     
5999 }
6000
6001 /*-----------------------------------------------------------------*/
6002 /* genInline - write the inline code out                           */
6003 /*-----------------------------------------------------------------*/
6004 static void genInline (iCode *ic)
6005 {
6006   char *buffer, *bp, *bp1;
6007   
6008   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6009   
6010   _G.inLine += (!options.asmpeep);
6011   
6012   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6013   strcpy(buffer,IC_INLINE(ic));
6014   
6015   /* emit each line as a code */
6016   while (*bp) {
6017     if (*bp == '\n') {
6018       *bp++ = '\0';
6019       
6020       if(*bp1)
6021         addpCode2pBlock(pb,AssembleLine(bp1));
6022       bp1 = bp;
6023     } else {
6024       if (*bp == ':') {
6025         bp++;
6026         *bp = '\0';
6027         bp++;
6028         pic14_emitcode(bp1,"");
6029         bp1 = bp;
6030       } else
6031         bp++;
6032     }
6033   }
6034   if ((bp1 != bp) && *bp1)
6035     addpCode2pBlock(pb,AssembleLine(bp1));
6036   
6037   Safe_free(buffer);
6038   
6039   _G.inLine -= (!options.asmpeep);
6040 }
6041
6042 /*-----------------------------------------------------------------*/
6043 /* genRRC - rotate right with carry                                */
6044 /*-----------------------------------------------------------------*/
6045 static void genRRC (iCode *ic)
6046 {
6047   operand *left , *result ;
6048   int size, offset = 0, same;
6049   
6050   /* rotate right with carry */
6051   left = IC_LEFT(ic);
6052   result=IC_RESULT(ic);
6053   aopOp (left,ic,FALSE);
6054   aopOp (result,ic,FALSE);
6055   
6056   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6057   
6058   same = pic14_sameRegs(AOP(result),AOP(left));
6059   
6060   size = AOP_SIZE(result);    
6061   
6062   /* get the lsb and put it into the carry */
6063   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6064   
6065   offset = 0 ;
6066   
6067   while(size--) {
6068     
6069     if(same) {
6070       emitpcode(POC_RRF, popGet(AOP(left),offset));
6071     } else {
6072       emitpcode(POC_RRFW, popGet(AOP(left),offset));
6073       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6074     }
6075     
6076     offset++;
6077   }
6078   
6079   freeAsmop(left,NULL,ic,TRUE);
6080   freeAsmop(result,NULL,ic,TRUE);
6081 }
6082
6083 /*-----------------------------------------------------------------*/
6084 /* genRLC - generate code for rotate left with carry               */
6085 /*-----------------------------------------------------------------*/
6086 static void genRLC (iCode *ic)
6087 {    
6088   operand *left , *result ;
6089   int size, offset = 0;
6090   int same;
6091   
6092   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6093   /* rotate right with carry */
6094   left = IC_LEFT(ic);
6095   result=IC_RESULT(ic);
6096   aopOp (left,ic,FALSE);
6097   aopOp (result,ic,FALSE);
6098   
6099   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6100   
6101   same = pic14_sameRegs(AOP(result),AOP(left));
6102   
6103   /* move it to the result */
6104   size = AOP_SIZE(result);    
6105   
6106   /* get the msb and put it into the carry */
6107   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6108   
6109   offset = 0 ;
6110   
6111   while(size--) {
6112     
6113     if(same) {
6114       emitpcode(POC_RLF, popGet(AOP(left),offset));
6115     } else {
6116       emitpcode(POC_RLFW, popGet(AOP(left),offset));
6117       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6118     }
6119     
6120     offset++;
6121   }
6122   
6123   
6124   freeAsmop(left,NULL,ic,TRUE);
6125   freeAsmop(result,NULL,ic,TRUE);
6126 }
6127
6128 /*-----------------------------------------------------------------*/
6129 /* genGetHbit - generates code get highest order bit               */
6130 /*-----------------------------------------------------------------*/
6131 static void genGetHbit (iCode *ic)
6132 {
6133   operand *left, *result;
6134   left = IC_LEFT(ic);
6135   result=IC_RESULT(ic);
6136   aopOp (left,ic,FALSE);
6137   aopOp (result,ic,FALSE);
6138   
6139   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6140   /* get the highest order byte into a */
6141   MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6142   if(AOP_TYPE(result) == AOP_CRY){
6143     pic14_emitcode("rlc","a");
6144     pic14_outBitC(result);
6145   }
6146   else{
6147     pic14_emitcode("rl","a");
6148     pic14_emitcode("anl","a,#0x01");
6149     pic14_outAcc(result);
6150   }
6151   
6152   
6153   freeAsmop(left,NULL,ic,TRUE);
6154   freeAsmop(result,NULL,ic,TRUE);
6155 }
6156
6157 /*-----------------------------------------------------------------*/
6158 /* AccRol - rotate left accumulator by known count                 */
6159 /*-----------------------------------------------------------------*/
6160 static void AccRol (int shCount)
6161 {
6162   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6163   shCount &= 0x0007;              // shCount : 0..7
6164   switch(shCount){
6165   case 0 :
6166     break;
6167   case 1 :
6168     pic14_emitcode("rl","a");
6169     break;
6170   case 2 :
6171     pic14_emitcode("rl","a");
6172     pic14_emitcode("rl","a");
6173     break;
6174   case 3 :
6175     pic14_emitcode("swap","a");
6176     pic14_emitcode("rr","a");
6177     break;
6178   case 4 :
6179     pic14_emitcode("swap","a");
6180     break;
6181   case 5 :
6182     pic14_emitcode("swap","a");
6183     pic14_emitcode("rl","a");
6184     break;
6185   case 6 :
6186     pic14_emitcode("rr","a");
6187     pic14_emitcode("rr","a");
6188     break;
6189   case 7 :
6190     pic14_emitcode("rr","a");
6191     break;
6192   }
6193 }
6194
6195 /*-----------------------------------------------------------------*/
6196 /* AccLsh - left shift accumulator by known count                  */
6197 /*-----------------------------------------------------------------*/
6198 static void AccLsh (int shCount)
6199 {
6200   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6201   if(shCount != 0){
6202     if(shCount == 1)
6203       pic14_emitcode("add","a,acc");
6204     else 
6205       if(shCount == 2) {
6206         pic14_emitcode("add","a,acc");
6207         pic14_emitcode("add","a,acc");
6208       } else {
6209         /* rotate left accumulator */
6210         AccRol(shCount);
6211         /* and kill the lower order bits */
6212         pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6213       }
6214   }
6215 }
6216
6217 /*-----------------------------------------------------------------*/
6218 /* AccRsh - right shift accumulator by known count                 */
6219 /*-----------------------------------------------------------------*/
6220 static void AccRsh (int shCount)
6221 {
6222   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6223   if(shCount != 0){
6224     if(shCount == 1){
6225       CLRC;
6226       pic14_emitcode("rrc","a");
6227     } else {
6228       /* rotate right accumulator */
6229       AccRol(8 - shCount);
6230       /* and kill the higher order bits */
6231       pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6232     }
6233   }
6234 }
6235
6236 #if 0
6237 /*-----------------------------------------------------------------*/
6238 /* AccSRsh - signed right shift accumulator by known count                 */
6239 /*-----------------------------------------------------------------*/
6240 static void AccSRsh (int shCount)
6241 {
6242   symbol *tlbl ;
6243   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6244   if(shCount != 0){
6245     if(shCount == 1){
6246       pic14_emitcode("mov","c,acc.7");
6247       pic14_emitcode("rrc","a");
6248     } else if(shCount == 2){
6249       pic14_emitcode("mov","c,acc.7");
6250       pic14_emitcode("rrc","a");
6251       pic14_emitcode("mov","c,acc.7");
6252       pic14_emitcode("rrc","a");
6253     } else {
6254       tlbl = newiTempLabel(NULL);
6255       /* rotate right accumulator */
6256       AccRol(8 - shCount);
6257       /* and kill the higher order bits */
6258       pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6259       pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6260       pic14_emitcode("orl","a,#0x%02x",
6261         (unsigned char)~SRMask[shCount]);
6262       pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6263     }
6264   }
6265 }
6266 #endif
6267 /*-----------------------------------------------------------------*/
6268 /* shiftR1Left2Result - shift right one byte from left to result   */
6269 /*-----------------------------------------------------------------*/
6270 static void shiftR1Left2ResultSigned (operand *left, int offl,
6271                     operand *result, int offr,
6272                     int shCount)
6273 {
6274   int same;
6275   
6276   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6277   
6278   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6279   
6280   switch(shCount) {
6281   case 1:
6282     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6283     if(same) 
6284       emitpcode(POC_RRF, popGet(AOP(result),offr));
6285     else {
6286       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6287       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6288     }
6289     
6290     break;
6291   case 2:
6292     
6293     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6294     if(same) 
6295       emitpcode(POC_RRF, popGet(AOP(result),offr));
6296     else {
6297       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6298       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6299     }
6300     emitpcode(POC_RLFW, popGet(AOP(result),offr));
6301     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6302     
6303     break;
6304     
6305   case 3:
6306     if(same)
6307       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6308     else {
6309       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6310       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6311     }
6312     
6313     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6314     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6315     emitpcode(POC_ANDLW, popGetLit(0x1f));
6316     
6317     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6318     emitpcode(POC_IORLW, popGetLit(0xe0));
6319     
6320     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6321     break;
6322     
6323   case 4:
6324     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6325     emitpcode(POC_ANDLW,  popGetLit(0x0f));
6326     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6327     emitpcode(POC_IORLW,  popGetLit(0xf0));
6328     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6329     break;
6330   case 5:
6331     if(same) {
6332       emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6333     } else {
6334       emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6335       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6336     }
6337     emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6338     emitpcode(POC_ANDLW,  popGetLit(0x07));
6339     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6340     emitpcode(POC_IORLW,  popGetLit(0xf8));
6341     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6342     break;
6343     
6344   case 6:
6345     if(same) {
6346       emitpcode(POC_MOVLW, popGetLit(0x00));
6347       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6348       emitpcode(POC_MOVLW, popGetLit(0xfe));
6349       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6350       emitpcode(POC_IORLW, popGetLit(0x01));
6351       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6352     } else {
6353       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6354       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6355       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6356       emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6357       emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6358     }
6359     break;
6360     
6361   case 7:
6362     if(same) {
6363       emitpcode(POC_MOVLW, popGetLit(0x00));
6364       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6365       emitpcode(POC_MOVLW, popGetLit(0xff));
6366       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6367     } else {
6368       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6369       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6370       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6371     }
6372     
6373   default:
6374     break;
6375   }
6376 }
6377
6378 /*-----------------------------------------------------------------*/
6379 /* shiftR1Left2Result - shift right one byte from left to result   */
6380 /*-----------------------------------------------------------------*/
6381 static void shiftR1Left2Result (operand *left, int offl,
6382                 operand *result, int offr,
6383                 int shCount, int sign)
6384 {
6385   int same;
6386   
6387   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6388   
6389   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6390   
6391   /* Copy the msb into the carry if signed. */
6392   if(sign) {
6393     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6394     return;
6395   }
6396   
6397   
6398   
6399   switch(shCount) {
6400   case 1:
6401     emitCLRC;
6402     if(same) 
6403       emitpcode(POC_RRF, popGet(AOP(result),offr));
6404     else {
6405       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6406       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6407     }
6408     break;
6409   case 2:
6410     emitCLRC;
6411     if(same) {
6412       emitpcode(POC_RRF, popGet(AOP(result),offr));
6413     } else {
6414       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6415       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6416     }
6417     emitCLRC;
6418     emitpcode(POC_RRF, popGet(AOP(result),offr));
6419     
6420     break;
6421   case 3:
6422     if(same)
6423       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6424     else {
6425       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6426       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6427     }
6428     
6429     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6430     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6431     emitpcode(POC_ANDLW, popGetLit(0x1f));
6432     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6433     break;
6434     
6435   case 4:
6436     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6437     emitpcode(POC_ANDLW, popGetLit(0x0f));
6438     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6439     break;
6440     
6441   case 5:
6442     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6443     emitpcode(POC_ANDLW, popGetLit(0x0f));
6444     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6445     emitCLRC;
6446     emitpcode(POC_RRF, popGet(AOP(result),offr));
6447     
6448     break;
6449   case 6:
6450     
6451     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6452     emitpcode(POC_ANDLW, popGetLit(0x80));
6453     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6454     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6455     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6456     break;
6457     
6458   case 7:
6459     
6460     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6461     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6462     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6463     
6464     break;
6465     
6466   default:
6467     break;
6468   }
6469 }
6470
6471 /*-----------------------------------------------------------------*/
6472 /* shiftL1Left2Result - shift left one byte from left to result    */
6473 /*-----------------------------------------------------------------*/
6474 static void shiftL1Left2Result (operand *left, int offl,
6475                 operand *result, int offr, int shCount)
6476 {
6477   int same;
6478   
6479   //    char *l;
6480   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6481   
6482   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6483   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6484   //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6485   //    MOVA(l);
6486   /* shift left accumulator */
6487   //AccLsh(shCount); // don't comment out just yet...
6488   //    aopPut(AOP(result),"a",offr);
6489   
6490   switch(shCount) {
6491   case 1:
6492     /* Shift left 1 bit position */
6493     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6494     if(same) {
6495       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6496     } else {
6497       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6498       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6499     }
6500     break;
6501   case 2:
6502     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6503     emitpcode(POC_ANDLW,popGetLit(0x7e));
6504     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6505     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6506     break;
6507   case 3:
6508     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6509     emitpcode(POC_ANDLW,popGetLit(0x3e));
6510     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6511     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6512     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6513     break;
6514   case 4:
6515     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6516     emitpcode(POC_ANDLW, popGetLit(0xf0));
6517     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6518     break;
6519   case 5:
6520     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6521     emitpcode(POC_ANDLW, popGetLit(0xf0));
6522     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6523     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6524     break;
6525   case 6:
6526     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6527     emitpcode(POC_ANDLW, popGetLit(0x30));
6528     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6529     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6530     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6531     break;
6532   case 7:
6533     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6534     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6535     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6536     break;
6537     
6538   default:
6539     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6540   }
6541   
6542 }
6543
6544 /*-----------------------------------------------------------------*/
6545 /* movLeft2Result - move byte from left to result                  */
6546 /*-----------------------------------------------------------------*/
6547 static void movLeft2Result (operand *left, int offl,
6548               operand *result, int offr)
6549 {
6550   char *l;
6551   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6552   if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6553     l = aopGet(AOP(left),offl,FALSE,FALSE);
6554     
6555     if (*l == '@' && (IS_AOP_PREG(result))) {
6556       pic14_emitcode("mov","a,%s",l);
6557       aopPut(AOP(result),"a",offr);
6558     } else {
6559       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6560       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6561     }
6562   }
6563 }
6564
6565 /*-----------------------------------------------------------------*/
6566 /* shiftL2Left2Result - shift left two bytes from left to result   */
6567 /*-----------------------------------------------------------------*/
6568 static void shiftL2Left2Result (operand *left, int offl,
6569                 operand *result, int offr, int shCount)
6570 {
6571   
6572   
6573   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6574   
6575   if(pic14_sameRegs(AOP(result), AOP(left))) {
6576     switch(shCount) {
6577     case 0:
6578       break;
6579     case 1:
6580     case 2:
6581     case 3:
6582       
6583       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6584       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6585       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6586       
6587       while(--shCount) {
6588         emitCLRC;
6589         emitpcode(POC_RLF, popGet(AOP(result),offr));
6590         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6591       }
6592       
6593       break;
6594     case 4:
6595     case 5:
6596       emitpcode(POC_MOVLW, popGetLit(0x0f));
6597       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6598       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6599       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6600       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6601       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6602       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6603       if(shCount >=5) {
6604         emitpcode(POC_RLF, popGet(AOP(result),offr));
6605         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6606       }
6607       break;
6608     case 6:
6609       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6610       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6611       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6612       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6613       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6614       emitpcode(POC_ANDLW,popGetLit(0xc0));
6615       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6616       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6617       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6618       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6619       break;
6620     case 7:
6621       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6622       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6623       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6624       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6625       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6626     }
6627     
6628   } else {
6629     switch(shCount) {
6630     case 0:
6631       break;
6632     case 1:
6633     case 2:
6634     case 3:
6635     /* note, use a mov/add for the shift since the mov has a
6636       chance of getting optimized out */
6637       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6638       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6639       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6640       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6641       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6642       
6643       while(--shCount) {
6644         emitCLRC;
6645         emitpcode(POC_RLF, popGet(AOP(result),offr));
6646         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6647       }
6648       break;
6649       
6650     case 4:
6651     case 5:
6652       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6653       emitpcode(POC_ANDLW, popGetLit(0xF0));
6654       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6655       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6656       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6657       emitpcode(POC_ANDLW, popGetLit(0xF0));
6658       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6659       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6660       
6661       
6662       if(shCount == 5) {
6663         emitpcode(POC_RLF, popGet(AOP(result),offr));
6664         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6665       }
6666       break;
6667     case 6:
6668       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6669       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6670       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6671       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6672       
6673       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6674       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6675       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6676       emitpcode(POC_ANDLW,popGetLit(0xc0));
6677       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6678       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6679       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6680       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6681       break;
6682     case 7:
6683       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6684       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6685       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6686       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6687       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6688     }
6689   }
6690   
6691 }
6692 /*-----------------------------------------------------------------*/
6693 /* shiftR2Left2Result - shift right two bytes from left to result  */
6694 /*-----------------------------------------------------------------*/
6695 static void shiftR2Left2Result (operand *left, int offl,
6696                 operand *result, int offr,
6697                 int shCount, int sign)
6698 {
6699   int same=0;
6700   
6701   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6702   same = pic14_sameRegs(AOP(result), AOP(left));
6703   
6704   if(same && ((offl + MSB16) == offr)){
6705     same=1;
6706     /* don't crash result[offr] */
6707     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6708     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6709   }
6710   /* else {
6711   movLeft2Result(left,offl, result, offr);
6712   MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6713   }
6714   */
6715   /* a:x >> shCount (x = lsb(result))*/
6716   /*
6717   if(sign)
6718   AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6719   else {
6720   AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6721   */
6722   switch(shCount) {
6723   case 0:
6724     break;
6725   case 1:
6726   case 2:
6727   case 3:
6728     if(sign)
6729       emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6730     else
6731       emitCLRC;
6732     
6733     if(same) {
6734       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6735       emitpcode(POC_RRF,popGet(AOP(result),offr));
6736     } else {
6737       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6738       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6739       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6740       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6741     }
6742     
6743     while(--shCount) {
6744       if(sign)
6745         emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6746       else
6747         emitCLRC;
6748       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6749       emitpcode(POC_RRF,popGet(AOP(result),offr));
6750     }
6751     break;
6752   case 4:
6753   case 5:
6754     if(same) {
6755       
6756       emitpcode(POC_MOVLW, popGetLit(0xf0));
6757       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6758       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6759       
6760       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6761       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6762       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6763       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6764     } else {
6765       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6766       emitpcode(POC_ANDLW, popGetLit(0x0f));
6767       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6768       
6769       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6770       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6771       emitpcode(POC_ANDLW, popGetLit(0xf0));
6772       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6773       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6774     }
6775     
6776     if(shCount >=5) {
6777       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6778       emitpcode(POC_RRF, popGet(AOP(result),offr));
6779     }
6780     
6781     if(sign) {
6782       emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6783       emitpcode(POC_BTFSC, 
6784         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6785       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6786     }
6787     
6788     break;
6789     
6790   case 6:
6791     if(same) {
6792       
6793       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6794       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6795       
6796       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6797       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6798       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6799       emitpcode(POC_ANDLW,popGetLit(0x03));
6800       if(sign) {
6801         emitpcode(POC_BTFSC, 
6802           newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6803         emitpcode(POC_IORLW,popGetLit(0xfc));
6804       }
6805       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6806       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6807       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6808       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6809     } else {
6810       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6811       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6812       emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6813       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6814       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6815       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6816       emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6817       emitpcode(POC_ANDLW,popGetLit(0x03));
6818       if(sign) {
6819         emitpcode(POC_BTFSC, 
6820           newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6821         emitpcode(POC_IORLW,popGetLit(0xfc));
6822       }
6823       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6824       //emitpcode(POC_RLF,  popGet(AOP(result),offr));
6825       
6826       
6827     }
6828     
6829     break;
6830   case 7:
6831     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6832     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6833     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6834     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6835     if(sign) {
6836       emitSKPNC;
6837       emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6838     } else 
6839       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6840   }
6841 }
6842
6843
6844 /*-----------------------------------------------------------------*/
6845 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6846 /*-----------------------------------------------------------------*/
6847 static void shiftLLeftOrResult (operand *left, int offl,
6848                 operand *result, int offr, int shCount)
6849 {
6850   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6851   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6852   /* shift left accumulator */
6853   AccLsh(shCount);
6854   /* or with result */
6855   pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6856   /* back to result */
6857   aopPut(AOP(result),"a",offr);
6858 }
6859
6860 /*-----------------------------------------------------------------*/
6861 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6862 /*-----------------------------------------------------------------*/
6863 static void shiftRLeftOrResult (operand *left, int offl,
6864                 operand *result, int offr, int shCount)
6865 {
6866   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6867   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6868   /* shift right accumulator */
6869   AccRsh(shCount);
6870   /* or with result */
6871   pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6872   /* back to result */
6873   aopPut(AOP(result),"a",offr);
6874 }
6875
6876 /*-----------------------------------------------------------------*/
6877 /* genlshOne - left shift a one byte quantity by known count       */
6878 /*-----------------------------------------------------------------*/
6879 static void genlshOne (operand *result, operand *left, int shCount)
6880 {       
6881   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6882   shiftL1Left2Result(left, LSB, result, LSB, shCount);
6883 }
6884
6885 /*-----------------------------------------------------------------*/
6886 /* genlshTwo - left shift two bytes by known amount != 0           */
6887 /*-----------------------------------------------------------------*/
6888 static void genlshTwo (operand *result,operand *left, int shCount)
6889 {
6890   int size;
6891   
6892   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6893   size = pic14_getDataSize(result);
6894   
6895   /* if shCount >= 8 */
6896   if (shCount >= 8) {
6897     shCount -= 8 ;
6898     
6899     if (size > 1){
6900       if (shCount)
6901         shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6902       else 
6903         movLeft2Result(left, LSB, result, MSB16);
6904     }
6905     emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6906   }
6907   
6908   /*  1 <= shCount <= 7 */
6909   else {  
6910     if(size == 1)
6911       shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6912     else 
6913       shiftL2Left2Result(left, LSB, result, LSB, shCount);
6914   }
6915 }
6916
6917 /*-----------------------------------------------------------------*/
6918 /* shiftLLong - shift left one long from left to result            */
6919 /* offl = LSB or MSB16                                             */
6920 /*-----------------------------------------------------------------*/
6921 static void shiftLLong (operand *left, operand *result, int offr )
6922 {
6923   char *l;
6924   int size = AOP_SIZE(result);
6925   
6926   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6927   if(size >= LSB+offr){
6928     l = aopGet(AOP(left),LSB,FALSE,FALSE);
6929     MOVA(l);
6930     pic14_emitcode("add","a,acc");
6931     if (pic14_sameRegs(AOP(left),AOP(result)) && 
6932       size >= MSB16+offr && offr != LSB )
6933       pic14_emitcode("xch","a,%s",
6934       aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6935     else      
6936       aopPut(AOP(result),"a",LSB+offr);
6937   }
6938   
6939   if(size >= MSB16+offr){
6940     if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6941       l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6942       MOVA(l);
6943     }
6944     pic14_emitcode("rlc","a");
6945     if (pic14_sameRegs(AOP(left),AOP(result)) && 
6946       size >= MSB24+offr && offr != LSB)
6947       pic14_emitcode("xch","a,%s",
6948       aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6949     else      
6950       aopPut(AOP(result),"a",MSB16+offr);
6951   }
6952   
6953   if(size >= MSB24+offr){
6954     if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6955       l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6956       MOVA(l);
6957     }
6958     pic14_emitcode("rlc","a");
6959     if (pic14_sameRegs(AOP(left),AOP(result)) && 
6960       size >= MSB32+offr && offr != LSB )
6961       pic14_emitcode("xch","a,%s",
6962       aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6963     else      
6964       aopPut(AOP(result),"a",MSB24+offr);
6965   }
6966   
6967   if(size > MSB32+offr){
6968     if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6969       l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6970       MOVA(l);  
6971     }
6972     pic14_emitcode("rlc","a");
6973     aopPut(AOP(result),"a",MSB32+offr);
6974   }
6975   if(offr != LSB)
6976     aopPut(AOP(result),zero,LSB);       
6977 }
6978
6979 /*-----------------------------------------------------------------*/
6980 /* genlshFour - shift four byte by a known amount != 0             */
6981 /*-----------------------------------------------------------------*/
6982 static void genlshFour (operand *result, operand *left, int shCount)
6983 {
6984   int size;
6985   
6986   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6987   size = AOP_SIZE(result);
6988   
6989   /* if shifting more that 3 bytes */
6990   if (shCount >= 24 ) {
6991     shCount -= 24;
6992     if (shCount)
6993     /* lowest order of left goes to the highest
6994     order of the destination */
6995     shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6996     else
6997       movLeft2Result(left, LSB, result, MSB32);
6998     aopPut(AOP(result),zero,LSB);
6999     aopPut(AOP(result),zero,MSB16);
7000     aopPut(AOP(result),zero,MSB32);
7001     return;
7002   }
7003   
7004   /* more than two bytes */
7005   else if ( shCount >= 16 ) {
7006     /* lower order two bytes goes to higher order two bytes */
7007     shCount -= 16;
7008     /* if some more remaining */
7009     if (shCount)
7010       shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7011     else {
7012       movLeft2Result(left, MSB16, result, MSB32);
7013       movLeft2Result(left, LSB, result, MSB24);
7014     }
7015     aopPut(AOP(result),zero,MSB16);
7016     aopPut(AOP(result),zero,LSB);
7017     return;
7018   }    
7019   
7020   /* if more than 1 byte */
7021   else if ( shCount >= 8 ) {
7022     /* lower order three bytes goes to higher order  three bytes */
7023     shCount -= 8;
7024     if(size == 2){
7025       if(shCount)
7026         shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7027       else
7028         movLeft2Result(left, LSB, result, MSB16);
7029     }
7030     else{   /* size = 4 */
7031       if(shCount == 0){
7032         movLeft2Result(left, MSB24, result, MSB32);
7033         movLeft2Result(left, MSB16, result, MSB24);
7034         movLeft2Result(left, LSB, result, MSB16);
7035         aopPut(AOP(result),zero,LSB);
7036       }
7037       else if(shCount == 1)
7038         shiftLLong(left, result, MSB16);
7039       else{
7040         shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7041         shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7042         shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7043         aopPut(AOP(result),zero,LSB);
7044       }
7045     }
7046   }
7047   
7048   /* 1 <= shCount <= 7 */
7049   else if(shCount <= 2){
7050     shiftLLong(left, result, LSB);
7051     if(shCount == 2)
7052       shiftLLong(result, result, LSB);
7053   }
7054   /* 3 <= shCount <= 7, optimize */
7055   else{
7056     shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7057     shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7058     shiftL2Left2Result(left, LSB, result, LSB, shCount);
7059   }
7060 }
7061
7062 /*-----------------------------------------------------------------*/
7063 /* genLeftShiftLiteral - left shifting by known count              */
7064 /*-----------------------------------------------------------------*/
7065 static void genLeftShiftLiteral (operand *left,
7066                  operand *right,
7067                  operand *result,
7068                  iCode *ic)
7069 {    
7070   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7071   int size;
7072   
7073   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7074   freeAsmop(right,NULL,ic,TRUE);
7075   
7076   aopOp(left,ic,FALSE);
7077   aopOp(result,ic,FALSE);
7078   
7079   size = getSize(operandType(result));
7080   
7081 #if VIEW_SIZE
7082   pic14_emitcode("; shift left ","result %d, left %d",size,
7083     AOP_SIZE(left));
7084 #endif
7085   
7086   /* I suppose that the left size >= result size */
7087   if(shCount == 0){
7088     while(size--){
7089       movLeft2Result(left, size, result, size);
7090     }
7091   }
7092   
7093   else if(shCount >= (size * 8))
7094     while(size--)
7095       aopPut(AOP(result),zero,size);
7096     else{
7097       switch (size) {
7098       case 1:
7099         genlshOne (result,left,shCount);
7100         break;
7101         
7102       case 2:
7103       case 3:
7104         genlshTwo (result,left,shCount);
7105         break;
7106         
7107       case 4:
7108         genlshFour (result,left,shCount);
7109         break;
7110       }
7111     }
7112     freeAsmop(left,NULL,ic,TRUE);
7113     freeAsmop(result,NULL,ic,TRUE);
7114 }
7115
7116 /*-----------------------------------------------------------------*
7117 * genMultiAsm - repeat assembly instruction for size of register.
7118 * if endian == 1, then the high byte (i.e base address + size of 
7119 * register) is used first else the low byte is used first;
7120 *-----------------------------------------------------------------*/
7121 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7122 {
7123   
7124   int offset = 0;
7125   
7126   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7127   
7128   if(!reg)
7129     return;
7130   
7131   if(!endian) {
7132     endian = 1;
7133   } else {
7134     endian = -1;
7135     offset = size-1;
7136   }
7137   
7138   while(size--) {
7139     emitpcode(poc,    popGet(AOP(reg),offset));
7140     offset += endian;
7141   }
7142   
7143 }
7144 /*-----------------------------------------------------------------*/
7145 /* genLeftShift - generates code for left shifting                 */
7146 /*-----------------------------------------------------------------*/
7147 static void genLeftShift (iCode *ic)
7148 {
7149   operand *left,*right, *result;
7150   int size, offset;
7151   char *l;
7152   symbol *tlbl , *tlbl1;
7153   pCodeOp *pctemp;
7154   
7155   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7156   
7157   right = IC_RIGHT(ic);
7158   left  = IC_LEFT(ic);
7159   result = IC_RESULT(ic);
7160   
7161   aopOp(right,ic,FALSE);
7162   
7163   /* if the shift count is known then do it 
7164   as efficiently as possible */
7165   if (AOP_TYPE(right) == AOP_LIT) {
7166     genLeftShiftLiteral (left,right,result,ic);
7167     return ;
7168   }
7169   
7170   /* shift count is unknown then we have to form 
7171   a loop get the loop count in B : Note: we take
7172   only the lower order byte since shifting
7173   more that 32 bits make no sense anyway, ( the
7174   largest size of an object can be only 32 bits ) */  
7175   
7176   
7177   aopOp(left,ic,FALSE);
7178   aopOp(result,ic,FALSE);
7179   
7180   /* now move the left to the result if they are not the
7181   same */
7182   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7183     AOP_SIZE(result) > 1) {
7184     
7185     size = AOP_SIZE(result);
7186     offset=0;
7187     while (size--) {
7188       l = aopGet(AOP(left),offset,FALSE,TRUE);
7189       if (*l == '@' && (IS_AOP_PREG(result))) {
7190         
7191         pic14_emitcode("mov","a,%s",l);
7192         aopPut(AOP(result),"a",offset);
7193       } else {
7194         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7195         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7196         //aopPut(AOP(result),l,offset);
7197       }
7198       offset++;
7199     }
7200   }
7201   
7202   size = AOP_SIZE(result);
7203   
7204   /* if it is only one byte then */
7205   if (size == 1) {
7206     if(optimized_for_speed) {
7207       emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7208       emitpcode(POC_ANDLW,  popGetLit(0xf0));
7209       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7210       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7211       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7212       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7213       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7214       emitpcode(POC_RLFW,   popGet(AOP(result),0));
7215       emitpcode(POC_ANDLW,  popGetLit(0xfe));
7216       emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7217       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7218       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7219     } else {
7220       
7221       tlbl = newiTempLabel(NULL);
7222       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7223         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7224         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7225       }
7226       
7227       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7228       emitpcode(POC_RRF,    popGet(AOP(result),0));
7229       emitpLabel(tlbl->key);
7230       emitpcode(POC_RLF,    popGet(AOP(result),0));
7231       emitpcode(POC_ADDLW,  popGetLit(1));
7232       emitSKPC;
7233       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7234     }
7235     goto release ;
7236   }
7237   
7238   if (pic14_sameRegs(AOP(left),AOP(result))) {
7239     
7240     tlbl = newiTempLabel(NULL);
7241     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7242     genMultiAsm(POC_RRF, result, size,1);
7243     emitpLabel(tlbl->key);
7244     genMultiAsm(POC_RLF, result, size,0);
7245     emitpcode(POC_ADDLW,  popGetLit(1));
7246     emitSKPC;
7247     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7248     goto release;
7249   }
7250   
7251   //tlbl = newiTempLabel(NULL);
7252   //offset = 0 ;   
7253   //tlbl1 = newiTempLabel(NULL);
7254   
7255   //reAdjustPreg(AOP(result));    
7256   
7257   //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7258   //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7259   //l = aopGet(AOP(result),offset,FALSE,FALSE);
7260   //MOVA(l);
7261   //pic14_emitcode("add","a,acc");         
7262   //aopPut(AOP(result),"a",offset++);
7263   //while (--size) {
7264   //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7265   //  MOVA(l);
7266   //  pic14_emitcode("rlc","a");         
7267   //  aopPut(AOP(result),"a",offset++);
7268   //}
7269   //reAdjustPreg(AOP(result));
7270   
7271   //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7272   //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7273   
7274   
7275   tlbl = newiTempLabel(NULL);
7276   tlbl1= newiTempLabel(NULL);
7277   
7278   size = AOP_SIZE(result);
7279   offset = 1;
7280   
7281   pctemp = popGetTempReg();  /* grab a temporary working register. */
7282   
7283   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7284   
7285   /* offset should be 0, 1 or 3 */
7286   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7287   emitSKPNZ;
7288   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7289   
7290   emitpcode(POC_MOVWF, pctemp);
7291   
7292   
7293   emitpLabel(tlbl->key);
7294   
7295   emitCLRC;
7296   emitpcode(POC_RLF,  popGet(AOP(result),0));
7297   while(--size)
7298     emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7299   
7300   emitpcode(POC_DECFSZ,  pctemp);
7301   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7302   emitpLabel(tlbl1->key);
7303   
7304   popReleaseTempReg(pctemp);
7305   
7306   
7307 release:
7308   freeAsmop (right,NULL,ic,TRUE);
7309   freeAsmop(left,NULL,ic,TRUE);
7310   freeAsmop(result,NULL,ic,TRUE);
7311 }
7312
7313 /*-----------------------------------------------------------------*/
7314 /* genrshOne - right shift a one byte quantity by known count      */
7315 /*-----------------------------------------------------------------*/
7316 static void genrshOne (operand *result, operand *left,
7317              int shCount, int sign)
7318 {
7319   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7320   shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7321 }
7322
7323 /*-----------------------------------------------------------------*/
7324 /* genrshTwo - right shift two bytes by known amount != 0          */
7325 /*-----------------------------------------------------------------*/
7326 static void genrshTwo (operand *result,operand *left,
7327              int shCount, int sign)
7328 {
7329   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7330   /* if shCount >= 8 */
7331   if (shCount >= 8) {
7332     shCount -= 8 ;
7333     if (shCount)
7334       shiftR1Left2Result(left, MSB16, result, LSB,
7335       shCount, sign);
7336     else
7337       movLeft2Result(left, MSB16, result, LSB);
7338     
7339     emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7340     
7341     if(sign) {
7342       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7343       emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7344     }
7345   }
7346   
7347   /*  1 <= shCount <= 7 */
7348   else
7349     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7350 }
7351
7352 /*-----------------------------------------------------------------*/
7353 /* shiftRLong - shift right one long from left to result           */
7354 /* offl = LSB or MSB16                                             */
7355 /*-----------------------------------------------------------------*/
7356 static void shiftRLong (operand *left, int offl,
7357             operand *result, int sign)
7358 {
7359   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7360   if(!sign)
7361     pic14_emitcode("clr","c");
7362   MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7363   if(sign)
7364     pic14_emitcode("mov","c,acc.7");
7365   pic14_emitcode("rrc","a");
7366   aopPut(AOP(result),"a",MSB32-offl);
7367   if(offl == MSB16)
7368     /* add sign of "a" */
7369     addSign(result, MSB32, sign);
7370   
7371   MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7372   pic14_emitcode("rrc","a");
7373   aopPut(AOP(result),"a",MSB24-offl);
7374   
7375   MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7376   pic14_emitcode("rrc","a");
7377   aopPut(AOP(result),"a",MSB16-offl);
7378   
7379   if(offl == LSB){
7380     MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7381     pic14_emitcode("rrc","a");
7382     aopPut(AOP(result),"a",LSB);
7383   }
7384 }
7385
7386 /*-----------------------------------------------------------------*/
7387 /* genrshFour - shift four byte by a known amount != 0             */
7388 /*-----------------------------------------------------------------*/
7389 static void genrshFour (operand *result, operand *left,
7390             int shCount, int sign)
7391 {
7392   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7393   /* if shifting more that 3 bytes */
7394   if(shCount >= 24 ) {
7395     shCount -= 24;
7396     if(shCount)
7397       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7398     else
7399       movLeft2Result(left, MSB32, result, LSB);
7400     
7401     addSign(result, MSB16, sign);
7402   }
7403   else if(shCount >= 16){
7404     shCount -= 16;
7405     if(shCount)
7406       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7407     else{
7408       movLeft2Result(left, MSB24, result, LSB);
7409       movLeft2Result(left, MSB32, result, MSB16);
7410     }
7411     addSign(result, MSB24, sign);
7412   }
7413   else if(shCount >= 8){
7414     shCount -= 8;
7415     if(shCount == 1)
7416       shiftRLong(left, MSB16, result, sign);
7417     else if(shCount == 0){
7418       movLeft2Result(left, MSB16, result, LSB);
7419       movLeft2Result(left, MSB24, result, MSB16);
7420       movLeft2Result(left, MSB32, result, MSB24);
7421       addSign(result, MSB32, sign);
7422     }
7423     else{
7424       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7425       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7426       /* the last shift is signed */
7427       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7428       addSign(result, MSB32, sign);
7429     }
7430   }
7431   else{   /* 1 <= shCount <= 7 */
7432     if(shCount <= 2){
7433       shiftRLong(left, LSB, result, sign);
7434       if(shCount == 2)
7435         shiftRLong(result, LSB, result, sign);
7436     }
7437     else{
7438       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7439       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7440       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7441     }
7442   }
7443 }
7444
7445 /*-----------------------------------------------------------------*/
7446 /* genRightShiftLiteral - right shifting by known count            */
7447 /*-----------------------------------------------------------------*/
7448 static void genRightShiftLiteral (operand *left,
7449                   operand *right,
7450                   operand *result,
7451                   iCode *ic,
7452                   int sign)
7453 {    
7454   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7455   int lsize,res_size;
7456   
7457   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7458   freeAsmop(right,NULL,ic,TRUE);
7459   
7460   aopOp(left,ic,FALSE);
7461   aopOp(result,ic,FALSE);
7462   
7463 #if VIEW_SIZE
7464   pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7465     AOP_SIZE(left));
7466 #endif
7467   
7468   lsize = pic14_getDataSize(left);
7469   res_size = pic14_getDataSize(result);
7470   /* test the LEFT size !!! */
7471   
7472   /* I suppose that the left size >= result size */
7473   if(shCount == 0){
7474     while(res_size--)
7475       movLeft2Result(left, lsize, result, res_size);
7476   }
7477   
7478   else if(shCount >= (lsize * 8)){
7479     
7480     if(res_size == 1) {
7481       emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7482       if(sign) {
7483         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7484         emitpcode(POC_DECF, popGet(AOP(result),LSB));
7485       }
7486     } else {
7487       
7488       if(sign) {
7489         emitpcode(POC_MOVLW, popGetLit(0));
7490         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7491         emitpcode(POC_MOVLW, popGetLit(0xff));
7492         while(res_size--)
7493           emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7494         
7495       } else {
7496         
7497         while(res_size--)
7498           emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7499       }
7500     }
7501   } else {
7502     
7503     switch (res_size) {
7504     case 1:
7505       genrshOne (result,left,shCount,sign);
7506       break;
7507       
7508     case 2:
7509       genrshTwo (result,left,shCount,sign);
7510       break;
7511       
7512     case 4:
7513       genrshFour (result,left,shCount,sign);
7514       break;
7515     default :
7516       break;
7517     }
7518     
7519   }
7520   
7521   freeAsmop(left,NULL,ic,TRUE);
7522   freeAsmop(result,NULL,ic,TRUE);
7523 }
7524
7525 /*-----------------------------------------------------------------*/
7526 /* genSignedRightShift - right shift of signed number              */
7527 /*-----------------------------------------------------------------*/
7528 static void genSignedRightShift (iCode *ic)
7529 {
7530   operand *right, *left, *result;
7531   int size, offset;
7532   //  char *l;
7533   symbol *tlbl, *tlbl1 ;
7534   pCodeOp *pctemp;
7535   
7536   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7537   
7538   /* we do it the hard way put the shift count in b
7539   and loop thru preserving the sign */
7540   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7541   
7542   right = IC_RIGHT(ic);
7543   left  = IC_LEFT(ic);
7544   result = IC_RESULT(ic);
7545   
7546   aopOp(right,ic,FALSE);  
7547   aopOp(left,ic,FALSE);
7548   aopOp(result,ic,FALSE);
7549   
7550   
7551   if ( AOP_TYPE(right) == AOP_LIT) {
7552     genRightShiftLiteral (left,right,result,ic,1);
7553     return ;
7554   }
7555   /* shift count is unknown then we have to form 
7556   a loop get the loop count in B : Note: we take
7557   only the lower order byte since shifting
7558   more that 32 bits make no sense anyway, ( the
7559   largest size of an object can be only 32 bits ) */  
7560   
7561   //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7562   //pic14_emitcode("inc","b");
7563   //freeAsmop (right,NULL,ic,TRUE);
7564   //aopOp(left,ic,FALSE);
7565   //aopOp(result,ic,FALSE);
7566   
7567   /* now move the left to the result if they are not the
7568   same */
7569   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7570     AOP_SIZE(result) > 1) {
7571     
7572     size = AOP_SIZE(result);
7573     offset=0;
7574     while (size--) { 
7575     /*
7576     l = aopGet(AOP(left),offset,FALSE,TRUE);
7577     if (*l == '@' && IS_AOP_PREG(result)) {
7578     
7579       pic14_emitcode("mov","a,%s",l);
7580       aopPut(AOP(result),"a",offset);
7581       } else
7582       aopPut(AOP(result),l,offset);
7583       */
7584       emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7585       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7586       
7587       offset++;
7588     }
7589   }
7590   
7591   /* mov the highest order bit to OVR */    
7592   tlbl = newiTempLabel(NULL);
7593   tlbl1= newiTempLabel(NULL);
7594   
7595   size = AOP_SIZE(result);
7596   offset = size - 1;
7597   
7598   pctemp = popGetTempReg();  /* grab a temporary working register. */
7599   
7600   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7601   
7602   /* offset should be 0, 1 or 3 */
7603   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7604   emitSKPNZ;
7605   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7606   
7607   emitpcode(POC_MOVWF, pctemp);
7608   
7609   
7610   emitpLabel(tlbl->key);
7611   
7612   emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7613   emitpcode(POC_RRF,   popGet(AOP(result),offset));
7614   
7615   while(--size) {
7616     emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7617   }
7618   
7619   emitpcode(POC_DECFSZ,  pctemp);
7620   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7621   emitpLabel(tlbl1->key);
7622   
7623   popReleaseTempReg(pctemp);
7624 #if 0
7625   size = AOP_SIZE(result);
7626   offset = size - 1;
7627   pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7628   pic14_emitcode("rlc","a");
7629   pic14_emitcode("mov","ov,c");
7630   /* if it is only one byte then */
7631   if (size == 1) {
7632     l = aopGet(AOP(left),0,FALSE,FALSE);
7633     MOVA(l);
7634     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7635     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7636     pic14_emitcode("mov","c,ov");
7637     pic14_emitcode("rrc","a");
7638     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7639     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7640     aopPut(AOP(result),"a",0);
7641     goto release ;
7642   }
7643   
7644   reAdjustPreg(AOP(result));
7645   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7646   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7647   pic14_emitcode("mov","c,ov");
7648   while (size--) {
7649     l = aopGet(AOP(result),offset,FALSE,FALSE);
7650     MOVA(l);
7651     pic14_emitcode("rrc","a");         
7652     aopPut(AOP(result),"a",offset--);
7653   }
7654   reAdjustPreg(AOP(result));
7655   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7656   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7657   
7658 release:
7659 #endif
7660   
7661   freeAsmop(left,NULL,ic,TRUE);
7662   freeAsmop(result,NULL,ic,TRUE);
7663   freeAsmop(right,NULL,ic,TRUE);
7664 }
7665
7666 /*-----------------------------------------------------------------*/
7667 /* genRightShift - generate code for right shifting                */
7668 /*-----------------------------------------------------------------*/
7669 static void genRightShift (iCode *ic)
7670 {
7671   operand *right, *left, *result;
7672   sym_link *retype ;
7673   int size, offset;
7674   char *l;
7675   symbol *tlbl, *tlbl1 ;
7676   
7677   /* if signed then we do it the hard way preserve the
7678   sign bit moving it inwards */
7679   retype = getSpec(operandType(IC_RESULT(ic)));
7680   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7681   
7682   if (!SPEC_USIGN(retype)) {
7683     genSignedRightShift (ic);
7684     return ;
7685   }
7686   
7687   /* signed & unsigned types are treated the same : i.e. the
7688   signed is NOT propagated inwards : quoting from the
7689   ANSI - standard : "for E1 >> E2, is equivalent to division
7690   by 2**E2 if unsigned or if it has a non-negative value,
7691   otherwise the result is implementation defined ", MY definition
7692   is that the sign does not get propagated */
7693   
7694   right = IC_RIGHT(ic);
7695   left  = IC_LEFT(ic);
7696   result = IC_RESULT(ic);
7697   
7698   aopOp(right,ic,FALSE);
7699   
7700   /* if the shift count is known then do it 
7701   as efficiently as possible */
7702   if (AOP_TYPE(right) == AOP_LIT) {
7703     genRightShiftLiteral (left,right,result,ic, 0);
7704     return ;
7705   }
7706   
7707   /* shift count is unknown then we have to form 
7708   a loop get the loop count in B : Note: we take
7709   only the lower order byte since shifting
7710   more that 32 bits make no sense anyway, ( the
7711   largest size of an object can be only 32 bits ) */  
7712   
7713   pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7714   pic14_emitcode("inc","b");
7715   aopOp(left,ic,FALSE);
7716   aopOp(result,ic,FALSE);
7717   
7718   /* now move the left to the result if they are not the
7719   same */
7720   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7721     AOP_SIZE(result) > 1) {
7722     
7723     size = AOP_SIZE(result);
7724     offset=0;
7725     while (size--) {
7726       l = aopGet(AOP(left),offset,FALSE,TRUE);
7727       if (*l == '@' && IS_AOP_PREG(result)) {
7728         
7729         pic14_emitcode("mov","a,%s",l);
7730         aopPut(AOP(result),"a",offset);
7731       } else
7732         aopPut(AOP(result),l,offset);
7733       offset++;
7734     }
7735   }
7736   
7737   tlbl = newiTempLabel(NULL);
7738   tlbl1= newiTempLabel(NULL);
7739   size = AOP_SIZE(result);
7740   offset = size - 1;
7741   
7742   /* if it is only one byte then */
7743   if (size == 1) {
7744     
7745     tlbl = newiTempLabel(NULL);
7746     if (!pic14_sameRegs(AOP(left),AOP(result))) {
7747       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7748       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7749     }
7750     
7751     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7752     emitpcode(POC_RLF,    popGet(AOP(result),0));
7753     emitpLabel(tlbl->key);
7754     emitpcode(POC_RRF,    popGet(AOP(result),0));
7755     emitpcode(POC_ADDLW,  popGetLit(1));
7756     emitSKPC;
7757     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7758     
7759     goto release ;
7760   }
7761   
7762   reAdjustPreg(AOP(result));
7763   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7764   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7765   CLRC;
7766   while (size--) {
7767     l = aopGet(AOP(result),offset,FALSE,FALSE);
7768     MOVA(l);
7769     pic14_emitcode("rrc","a");         
7770     aopPut(AOP(result),"a",offset--);
7771   }
7772   reAdjustPreg(AOP(result));
7773   
7774   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7775   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7776   
7777 release:
7778   freeAsmop(left,NULL,ic,TRUE);
7779   freeAsmop (right,NULL,ic,TRUE);
7780   freeAsmop(result,NULL,ic,TRUE);
7781 }
7782
7783 /*-----------------------------------------------------------------*/
7784 /* genUnpackBits - generates code for unpacking bits               */
7785 /*-----------------------------------------------------------------*/
7786 static void genUnpackBits (operand *result, char *rname, int ptype)
7787 {    
7788   int shCnt ;
7789   int rlen = 0 ;
7790   sym_link *etype;
7791   int offset = 0 ;
7792   
7793   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7794   etype = getSpec(operandType(result));
7795   
7796   /* read the first byte  */
7797   switch (ptype) {
7798     
7799   case POINTER:
7800   case IPOINTER:
7801     pic14_emitcode("mov","a,@%s",rname);
7802     break;
7803     
7804   case PPOINTER:
7805     pic14_emitcode("movx","a,@%s",rname);
7806     break;
7807     
7808   case FPOINTER:
7809     pic14_emitcode("movx","a,@dptr");
7810     break;
7811     
7812   case CPOINTER:
7813     pic14_emitcode("clr","a");
7814     pic14_emitcode("movc","a","@a+dptr");
7815     break;
7816     
7817   case GPOINTER:
7818     pic14_emitcode("lcall","__gptrget");
7819     break;
7820   }
7821   
7822   /* if we have bitdisplacement then it fits   */
7823   /* into this byte completely or if length is */
7824   /* less than a byte                          */
7825   if ((shCnt = SPEC_BSTR(etype)) || 
7826     (SPEC_BLEN(etype) <= 8))  {
7827     
7828     /* shift right acc */
7829     AccRsh(shCnt);
7830     
7831     pic14_emitcode("anl","a,#0x%02x",
7832       ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7833     aopPut(AOP(result),"a",offset);
7834     return ;
7835   }
7836   
7837   /* bit field did not fit in a byte  */
7838   rlen = SPEC_BLEN(etype) - 8;
7839   aopPut(AOP(result),"a",offset++);
7840   
7841   while (1)  {
7842     
7843     switch (ptype) {
7844     case POINTER:
7845     case IPOINTER:
7846       pic14_emitcode("inc","%s",rname);
7847       pic14_emitcode("mov","a,@%s",rname);
7848       break;
7849       
7850     case PPOINTER:
7851       pic14_emitcode("inc","%s",rname);
7852       pic14_emitcode("movx","a,@%s",rname);
7853       break;
7854       
7855     case FPOINTER:
7856       pic14_emitcode("inc","dptr");
7857       pic14_emitcode("movx","a,@dptr");
7858       break;
7859       
7860     case CPOINTER:
7861       pic14_emitcode("clr","a");
7862       pic14_emitcode("inc","dptr");
7863       pic14_emitcode("movc","a","@a+dptr");
7864       break;
7865       
7866     case GPOINTER:
7867       pic14_emitcode("inc","dptr");
7868       pic14_emitcode("lcall","__gptrget");
7869       break;
7870     }
7871     
7872     rlen -= 8;            
7873     /* if we are done */
7874     if ( rlen <= 0 )
7875       break ;
7876     
7877     aopPut(AOP(result),"a",offset++);
7878     
7879   }
7880   
7881   if (rlen) {
7882     pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7883     aopPut(AOP(result),"a",offset);        
7884   }
7885   
7886   return ;
7887 }
7888
7889 #if 0
7890 /*-----------------------------------------------------------------*/
7891 /* genDataPointerGet - generates code when ptr offset is known     */
7892 /*-----------------------------------------------------------------*/
7893 static void genDataPointerGet (operand *left, 
7894                  operand *result, 
7895                  iCode *ic)
7896 {
7897   int size , offset = 0;
7898   
7899   
7900   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7901   
7902   
7903   /* optimization - most of the time, left and result are the same
7904   * address, but different types. for the pic code, we could omit
7905   * the following
7906   */
7907   
7908   aopOp(result,ic,TRUE);
7909   
7910   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7911   
7912   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7913   
7914   size = AOP_SIZE(result);
7915   
7916   while (size--) {
7917     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7918     offset++;
7919   }
7920   
7921   freeAsmop(left,NULL,ic,TRUE);
7922   freeAsmop(result,NULL,ic,TRUE);
7923 }
7924 #endif
7925 /*-----------------------------------------------------------------*/
7926 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7927 /*-----------------------------------------------------------------*/
7928 static void genNearPointerGet (operand *left, 
7929                  operand *result, 
7930                  iCode *ic)
7931 {
7932   asmop *aop = NULL;
7933   //regs *preg = NULL ;
7934   char *rname ;
7935   sym_link *rtype, *retype;
7936   sym_link *ltype = operandType(left);    
7937   //char buffer[80];
7938   
7939   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7940   
7941   rtype = operandType(result);
7942   retype= getSpec(rtype);
7943   
7944   aopOp(left,ic,FALSE);
7945   
7946   /* if left is rematerialisable and
7947   result is not bit variable type and
7948   the left is pointer to data space i.e
7949   lower 128 bytes of space */
7950   if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
7951     !IS_BITVAR(retype)         &&
7952     DCL_TYPE(ltype) == POINTER) {
7953     //genDataPointerGet (left,result,ic);
7954     return ;
7955   }
7956   
7957   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7958   
7959   /* if the value is already in a pointer register
7960   then don't need anything more */
7961   if (!AOP_INPREG(AOP(left))) {
7962     /* otherwise get a free pointer register */
7963     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7964     /*
7965     aop = newAsmop(0);
7966     preg = getFreePtr(ic,&aop,FALSE);
7967     pic14_emitcode("mov","%s,%s",
7968     preg->name,
7969     aopGet(AOP(left),0,FALSE,TRUE));
7970     rname = preg->name ;
7971     */
7972     rname ="BAD";
7973   } else
7974     rname = aopGet(AOP(left),0,FALSE,FALSE);
7975   
7976   aopOp (result,ic,FALSE);
7977   
7978   /* if bitfield then unpack the bits */
7979   if (IS_BITFIELD(retype)) 
7980     genUnpackBits (result,rname,POINTER);
7981   else {
7982     /* we have can just get the values */
7983     int size = AOP_SIZE(result);
7984     int offset = 0 ;  
7985     
7986     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7987     
7988     emitpcode(POC_MOVFW,popGet(AOP(left),0));
7989     emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7990     while(size--) {
7991       emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7992       emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
7993       if(size)
7994         emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7995     }
7996     /*
7997     while (size--) {
7998     if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7999
8000       pic14_emitcode("mov","a,@%s",rname);
8001       aopPut(AOP(result),"a",offset);
8002       } else {
8003       sprintf(buffer,"@%s",rname);
8004       aopPut(AOP(result),buffer,offset);
8005       }
8006       offset++ ;
8007       if (size)
8008       pic14_emitcode("inc","%s",rname);
8009     }
8010     */
8011   }
8012   
8013   /* now some housekeeping stuff */
8014   if (aop) {
8015     /* we had to allocate for this iCode */
8016     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8017     freeAsmop(NULL,aop,ic,TRUE);
8018   } else { 
8019   /* we did not allocate which means left
8020      already in a pointer register, then
8021      if size > 0 && this could be used again
8022      we have to point it back to where it 
8023     belongs */
8024     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8025     if (AOP_SIZE(result) > 1 &&
8026       !OP_SYMBOL(left)->remat &&
8027       ( OP_SYMBOL(left)->liveTo > ic->seq ||
8028       ic->depth )) {
8029       int size = AOP_SIZE(result) - 1;
8030       while (size--)
8031         pic14_emitcode("dec","%s",rname);
8032     }
8033   }
8034   
8035   /* done */
8036   freeAsmop(left,NULL,ic,TRUE);
8037   freeAsmop(result,NULL,ic,TRUE);
8038   
8039 }
8040
8041 /*-----------------------------------------------------------------*/
8042 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8043 /*-----------------------------------------------------------------*/
8044 static void genPagedPointerGet (operand *left, 
8045                 operand *result, 
8046                 iCode *ic)
8047 {
8048   asmop *aop = NULL;
8049   regs *preg = NULL ;
8050   char *rname ;
8051   sym_link *rtype, *retype;    
8052   
8053   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8054   
8055   rtype = operandType(result);
8056   retype= getSpec(rtype);
8057   
8058   aopOp(left,ic,FALSE);
8059   
8060   /* if the value is already in a pointer register
8061   then don't need anything more */
8062   if (!AOP_INPREG(AOP(left))) {
8063     /* otherwise get a free pointer register */
8064     aop = newAsmop(0);
8065     preg = getFreePtr(ic,&aop,FALSE);
8066     pic14_emitcode("mov","%s,%s",
8067       preg->name,
8068       aopGet(AOP(left),0,FALSE,TRUE));
8069     rname = preg->name ;
8070   } else
8071     rname = aopGet(AOP(left),0,FALSE,FALSE);
8072   
8073   freeAsmop(left,NULL,ic,TRUE);
8074   aopOp (result,ic,FALSE);
8075   
8076   /* if bitfield then unpack the bits */
8077   if (IS_BITFIELD(retype)) 
8078     genUnpackBits (result,rname,PPOINTER);
8079   else {
8080     /* we have can just get the values */
8081     int size = AOP_SIZE(result);
8082     int offset = 0 ;  
8083     
8084     while (size--) {
8085       
8086       pic14_emitcode("movx","a,@%s",rname);
8087       aopPut(AOP(result),"a",offset);
8088       
8089       offset++ ;
8090       
8091       if (size)
8092         pic14_emitcode("inc","%s",rname);
8093     }
8094   }
8095   
8096   /* now some housekeeping stuff */
8097   if (aop) {
8098     /* we had to allocate for this iCode */
8099     freeAsmop(NULL,aop,ic,TRUE);
8100   } else { 
8101   /* we did not allocate which means left
8102      already in a pointer register, then
8103      if size > 0 && this could be used again
8104      we have to point it back to where it 
8105     belongs */
8106     if (AOP_SIZE(result) > 1 &&
8107       !OP_SYMBOL(left)->remat &&
8108       ( OP_SYMBOL(left)->liveTo > ic->seq ||
8109       ic->depth )) {
8110       int size = AOP_SIZE(result) - 1;
8111       while (size--)
8112         pic14_emitcode("dec","%s",rname);
8113     }
8114   }
8115   
8116   /* done */
8117   freeAsmop(result,NULL,ic,TRUE);
8118   
8119   
8120 }
8121
8122 /*-----------------------------------------------------------------*/
8123 /* genFarPointerGet - gget value from far space                    */
8124 /*-----------------------------------------------------------------*/
8125 static void genFarPointerGet (operand *left,
8126                 operand *result, iCode *ic)
8127 {
8128   int size, offset ;
8129   sym_link *retype = getSpec(operandType(result));
8130   
8131   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8132   
8133   aopOp(left,ic,FALSE);
8134   
8135   /* if the operand is already in dptr 
8136   then we do nothing else we move the value to dptr */
8137   if (AOP_TYPE(left) != AOP_STR) {
8138     /* if this is remateriazable */
8139     if (AOP_TYPE(left) == AOP_IMMD)
8140       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8141     else { /* we need to get it byte by byte */
8142       pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8143       pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8144       if (options.model == MODEL_FLAT24)
8145       {
8146         pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8147       }
8148     }
8149   }
8150   /* so dptr know contains the address */
8151   freeAsmop(left,NULL,ic,TRUE);
8152   aopOp(result,ic,FALSE);
8153   
8154   /* if bit then unpack */
8155   if (IS_BITFIELD(retype)) 
8156     genUnpackBits(result,"dptr",FPOINTER);
8157   else {
8158     size = AOP_SIZE(result);
8159     offset = 0 ;
8160     
8161     while (size--) {
8162       pic14_emitcode("movx","a,@dptr");
8163       aopPut(AOP(result),"a",offset++);
8164       if (size)
8165         pic14_emitcode("inc","dptr");
8166     }
8167   }
8168   
8169   freeAsmop(result,NULL,ic,TRUE);
8170 }
8171 #if 0
8172 /*-----------------------------------------------------------------*/
8173 /* genCodePointerGet - get value from code space                  */
8174 /*-----------------------------------------------------------------*/
8175 static void genCodePointerGet (operand *left,
8176                  operand *result, iCode *ic)
8177 {
8178   int size, offset ;
8179   sym_link *retype = getSpec(operandType(result));
8180   
8181   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8182   
8183   aopOp(left,ic,FALSE);
8184   
8185   /* if the operand is already in dptr 
8186   then we do nothing else we move the value to dptr */
8187   if (AOP_TYPE(left) != AOP_STR) {
8188     /* if this is remateriazable */
8189     if (AOP_TYPE(left) == AOP_IMMD)
8190       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8191     else { /* we need to get it byte by byte */
8192       pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8193       pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8194       if (options.model == MODEL_FLAT24)
8195       {
8196         pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8197       }
8198     }
8199   }
8200   /* so dptr know contains the address */
8201   freeAsmop(left,NULL,ic,TRUE);
8202   aopOp(result,ic,FALSE);
8203   
8204   /* if bit then unpack */
8205   if (IS_BITFIELD(retype)) 
8206     genUnpackBits(result,"dptr",CPOINTER);
8207   else {
8208     size = AOP_SIZE(result);
8209     offset = 0 ;
8210     
8211     while (size--) {
8212       pic14_emitcode("clr","a");
8213       pic14_emitcode("movc","a,@a+dptr");
8214       aopPut(AOP(result),"a",offset++);
8215       if (size)
8216         pic14_emitcode("inc","dptr");
8217     }
8218   }
8219   
8220   freeAsmop(result,NULL,ic,TRUE);
8221 }
8222 #endif
8223 /*-----------------------------------------------------------------*/
8224 /* genGenPointerGet - gget value from generic pointer space        */
8225 /*-----------------------------------------------------------------*/
8226 static void genGenPointerGet (operand *left,
8227                 operand *result, iCode *ic)
8228 {
8229   int size, offset ;
8230   sym_link *retype = getSpec(operandType(result));
8231   
8232   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8233   aopOp(left,ic,FALSE);
8234   aopOp(result,ic,FALSE);
8235   
8236   
8237   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8238   
8239   /* if the operand is already in dptr 
8240   then we do nothing else we move the value to dptr */
8241   //  if (AOP_TYPE(left) != AOP_STR) {
8242   /* if this is remateriazable */
8243   if (AOP_TYPE(left) == AOP_IMMD) {
8244     pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8245     pic14_emitcode("mov","b,#%d",pointerCode(retype));
8246   }
8247   else { /* we need to get it byte by byte */
8248     
8249     emitpcode(POC_MOVFW,popGet(AOP(left),0));
8250     emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8251     
8252     size = AOP_SIZE(result);
8253     offset = 0 ;
8254     
8255     while(size--) {
8256       emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8257       emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8258       if(size)
8259         emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8260     }
8261     goto release;
8262   }
8263   //}
8264   /* so dptr know contains the address */
8265   
8266   /* if bit then unpack */
8267   //if (IS_BITFIELD(retype)) 
8268   //  genUnpackBits(result,"dptr",GPOINTER);
8269   
8270 release:
8271   freeAsmop(left,NULL,ic,TRUE);
8272   freeAsmop(result,NULL,ic,TRUE);
8273   
8274 }
8275
8276 /*-----------------------------------------------------------------*/
8277 /* genConstPointerGet - get value from const generic pointer space */
8278 /*-----------------------------------------------------------------*/
8279 static void genConstPointerGet (operand *left,
8280                 operand *result, iCode *ic)
8281 {
8282   //sym_link *retype = getSpec(operandType(result));
8283   symbol *albl = newiTempLabel(NULL);
8284   symbol *blbl = newiTempLabel(NULL);
8285   PIC_OPCODE poc;
8286   pCodeOp *pcop;
8287   
8288   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8289   aopOp(left,ic,FALSE);
8290   aopOp(result,ic,FALSE);
8291   
8292   
8293   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8294   
8295   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8296   
8297   emitpcode(POC_CALL,popGetLabel(albl->key));
8298   pcop = popGetLabel(blbl->key);
8299   emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8300   emitpcode(POC_GOTO,pcop);
8301   emitpLabel(albl->key);
8302   
8303   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8304   
8305   emitpcode(poc,popGet(AOP(left),1));
8306   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8307   emitpcode(poc,popGet(AOP(left),0));
8308   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8309   
8310   emitpLabel(blbl->key);
8311   
8312   emitpcode(POC_MOVWF,popGet(AOP(result),0));
8313   
8314   
8315   freeAsmop(left,NULL,ic,TRUE);
8316   freeAsmop(result,NULL,ic,TRUE);
8317   
8318 }
8319 /*-----------------------------------------------------------------*/
8320 /* genPointerGet - generate code for pointer get                   */
8321 /*-----------------------------------------------------------------*/
8322 static void genPointerGet (iCode *ic)
8323 {
8324   operand *left, *result ;
8325   sym_link *type, *etype;
8326   int p_type;
8327   
8328   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8329   
8330   left = IC_LEFT(ic);
8331   result = IC_RESULT(ic) ;
8332   
8333   /* depending on the type of pointer we need to
8334   move it to the correct pointer register */
8335   type = operandType(left);
8336   etype = getSpec(type);
8337   
8338   if (IS_PTR_CONST(type))
8339     DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8340   
8341   /* if left is of type of pointer then it is simple */
8342   if (IS_PTR(type) && !IS_FUNC(type->next)) 
8343     p_type = DCL_TYPE(type);
8344   else {
8345     /* we have to go by the storage class */
8346     p_type = PTR_TYPE(SPEC_OCLS(etype));
8347     
8348     DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8349     
8350     if (SPEC_OCLS(etype)->codesp ) {
8351       DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8352       //p_type = CPOINTER ; 
8353     }
8354     else
8355       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8356         DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8357       /*p_type = FPOINTER ;*/ 
8358       else
8359         if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8360           DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8361         /*        p_type = PPOINTER; */
8362         else
8363           if (SPEC_OCLS(etype) == idata )
8364             DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8365           /*      p_type = IPOINTER; */
8366           else
8367             DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8368           /*      p_type = POINTER ; */
8369   }
8370   
8371   /* now that we have the pointer type we assign
8372   the pointer values */
8373   switch (p_type) {
8374     
8375   case POINTER: 
8376   case IPOINTER:
8377     genNearPointerGet (left,result,ic);
8378     break;
8379     
8380   case PPOINTER:
8381     genPagedPointerGet(left,result,ic);
8382     break;
8383     
8384   case FPOINTER:
8385     genFarPointerGet (left,result,ic);
8386     break;
8387     
8388   case CPOINTER:
8389     genConstPointerGet (left,result,ic);
8390     //pic14_emitcodePointerGet (left,result,ic);
8391     break;
8392     
8393   case GPOINTER:
8394     if (IS_PTR_CONST(type))
8395       genConstPointerGet (left,result,ic);
8396     else
8397       genGenPointerGet (left,result,ic);
8398     break;
8399   }
8400   
8401 }
8402
8403 /*-----------------------------------------------------------------*/
8404 /* genPackBits - generates code for packed bit storage             */
8405 /*-----------------------------------------------------------------*/
8406 static void genPackBits (sym_link    *etype ,
8407              operand *right ,
8408              char *rname, int p_type)
8409 {
8410   int shCount = 0 ;
8411   int offset = 0  ;
8412   int rLen = 0 ;
8413   int blen, bstr ;   
8414   char *l ;
8415   
8416   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8417   blen = SPEC_BLEN(etype);
8418   bstr = SPEC_BSTR(etype);
8419   
8420   l = aopGet(AOP(right),offset++,FALSE,FALSE);
8421   MOVA(l);   
8422   
8423   /* if the bit lenth is less than or    */
8424   /* it exactly fits a byte then         */
8425   if (SPEC_BLEN(etype) <= 8 )  {
8426     shCount = SPEC_BSTR(etype) ;
8427     
8428     /* shift left acc */
8429     AccLsh(shCount);
8430     
8431     if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8432       
8433       
8434       switch (p_type) {
8435       case POINTER:
8436         pic14_emitcode ("mov","b,a");
8437         pic14_emitcode("mov","a,@%s",rname);
8438         break;
8439         
8440       case FPOINTER:
8441         pic14_emitcode ("mov","b,a");
8442         pic14_emitcode("movx","a,@dptr");
8443         break;
8444         
8445       case GPOINTER:
8446         pic14_emitcode ("push","b");
8447         pic14_emitcode ("push","acc");
8448         pic14_emitcode ("lcall","__gptrget");
8449         pic14_emitcode ("pop","b");
8450         break;
8451       }
8452       
8453       pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8454         ((unsigned char)(0xFF << (blen+bstr)) | 
8455         (unsigned char)(0xFF >> (8-bstr)) ) );
8456       pic14_emitcode ("orl","a,b");
8457       if (p_type == GPOINTER)
8458         pic14_emitcode("pop","b");
8459     }
8460   }
8461   
8462   switch (p_type) {
8463   case POINTER:
8464     pic14_emitcode("mov","@%s,a",rname);
8465     break;
8466     
8467   case FPOINTER:
8468     pic14_emitcode("movx","@dptr,a");
8469     break;
8470     
8471   case GPOINTER:
8472     DEBUGpic14_emitcode(";lcall","__gptrput");
8473     break;
8474   }
8475   
8476   /* if we r done */
8477   if ( SPEC_BLEN(etype) <= 8 )
8478     return ;
8479   
8480   pic14_emitcode("inc","%s",rname);
8481   rLen = SPEC_BLEN(etype) ;     
8482   
8483   /* now generate for lengths greater than one byte */
8484   while (1) {
8485     
8486     l = aopGet(AOP(right),offset++,FALSE,TRUE);
8487     
8488     rLen -= 8 ;
8489     if (rLen <= 0 )
8490       break ;
8491     
8492     switch (p_type) {
8493     case POINTER:
8494       if (*l == '@') {
8495         MOVA(l);
8496         pic14_emitcode("mov","@%s,a",rname);
8497       } else
8498         pic14_emitcode("mov","@%s,%s",rname,l);
8499       break;
8500       
8501     case FPOINTER:
8502       MOVA(l);
8503       pic14_emitcode("movx","@dptr,a");
8504       break;
8505       
8506     case GPOINTER:
8507       MOVA(l);
8508       DEBUGpic14_emitcode(";lcall","__gptrput");
8509       break;  
8510     }   
8511     pic14_emitcode ("inc","%s",rname);
8512   }
8513   
8514   MOVA(l);
8515   
8516   /* last last was not complete */
8517   if (rLen)   {
8518     /* save the byte & read byte */
8519     switch (p_type) {
8520     case POINTER:
8521       pic14_emitcode ("mov","b,a");
8522       pic14_emitcode("mov","a,@%s",rname);
8523       break;
8524       
8525     case FPOINTER:
8526       pic14_emitcode ("mov","b,a");
8527       pic14_emitcode("movx","a,@dptr");
8528       break;
8529       
8530     case GPOINTER:
8531       pic14_emitcode ("push","b");
8532       pic14_emitcode ("push","acc");
8533       pic14_emitcode ("lcall","__gptrget");
8534       pic14_emitcode ("pop","b");
8535       break;
8536     }
8537     
8538     pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8539     pic14_emitcode ("orl","a,b");
8540   }
8541   
8542   if (p_type == GPOINTER)
8543     pic14_emitcode("pop","b");
8544   
8545   switch (p_type) {
8546     
8547   case POINTER:
8548     pic14_emitcode("mov","@%s,a",rname);
8549     break;
8550     
8551   case FPOINTER:
8552     pic14_emitcode("movx","@dptr,a");
8553     break;
8554     
8555   case GPOINTER:
8556     DEBUGpic14_emitcode(";lcall","__gptrput");
8557     break;      
8558   }
8559 }
8560 /*-----------------------------------------------------------------*/
8561 /* genDataPointerSet - remat pointer to data space                 */
8562 /*-----------------------------------------------------------------*/
8563 static void genDataPointerSet(operand *right,
8564                 operand *result,
8565                 iCode *ic)
8566 {
8567   int size, offset = 0 ;
8568   char *l, buffer[256];
8569   
8570   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8571   aopOp(right,ic,FALSE);
8572   
8573   l = aopGet(AOP(result),0,FALSE,TRUE);
8574   size = AOP_SIZE(right);
8575   /*
8576   if ( AOP_TYPE(result) == AOP_PCODE) {
8577   fprintf(stderr,"genDataPointerSet   %s, %d\n",
8578   AOP(result)->aopu.pcop->name,
8579   PCOI(AOP(result)->aopu.pcop)->offset);
8580   }
8581   */
8582   
8583   // tsd, was l+1 - the underline `_' prefix was being stripped
8584   while (size--) {
8585     if (offset) {
8586       sprintf(buffer,"(%s + %d)",l,offset);
8587       fprintf(stderr,"oops  %s\n",buffer);
8588     } else
8589       sprintf(buffer,"%s",l);
8590     
8591     if (AOP_TYPE(right) == AOP_LIT) {
8592       unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8593       lit = lit >> (8*offset);
8594       if(lit&0xff) {
8595         pic14_emitcode("movlw","%d",lit);
8596         pic14_emitcode("movwf","%s",buffer);
8597         
8598         emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8599         //emitpcode(POC_MOVWF, popRegFromString(buffer));
8600         emitpcode(POC_MOVWF, popGet(AOP(result),0));
8601         
8602       } else {
8603         pic14_emitcode("clrf","%s",buffer);
8604         //emitpcode(POC_CLRF, popRegFromString(buffer));
8605         emitpcode(POC_CLRF, popGet(AOP(result),0));
8606       }
8607     }else {
8608       pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8609       pic14_emitcode("movwf","%s",buffer);
8610       
8611       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8612       //emitpcode(POC_MOVWF, popRegFromString(buffer));
8613       emitpcode(POC_MOVWF, popGet(AOP(result),0));
8614       
8615     }
8616     
8617     offset++;
8618   }
8619   
8620   freeAsmop(right,NULL,ic,TRUE);
8621   freeAsmop(result,NULL,ic,TRUE);
8622 }
8623
8624 /*-----------------------------------------------------------------*/
8625 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8626 /*-----------------------------------------------------------------*/
8627 static void genNearPointerSet (operand *right,
8628                  operand *result, 
8629                  iCode *ic)
8630 {
8631   asmop *aop = NULL;
8632   char *l;
8633   sym_link *retype;
8634   sym_link *ptype = operandType(result);
8635   
8636   
8637   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8638   retype= getSpec(operandType(right));
8639   
8640   aopOp(result,ic,FALSE);
8641   
8642   
8643   /* if the result is rematerializable &
8644   in data space & not a bit variable */
8645   //if (AOP_TYPE(result) == AOP_IMMD &&
8646   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8647     DCL_TYPE(ptype) == POINTER   &&
8648     !IS_BITFIELD(retype)) {
8649     genDataPointerSet (right,result,ic);
8650     freeAsmop(result,NULL,ic,TRUE);
8651     return;
8652   }
8653   
8654   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8655   aopOp(right,ic,FALSE);
8656   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8657   
8658   /* if the value is already in a pointer register
8659   then don't need anything more */
8660   if (!AOP_INPREG(AOP(result))) {
8661     /* otherwise get a free pointer register */
8662     //aop = newAsmop(0);
8663     //preg = getFreePtr(ic,&aop,FALSE);
8664     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8665     //pic14_emitcode("mov","%s,%s",
8666     //         preg->name,
8667     //         aopGet(AOP(result),0,FALSE,TRUE));
8668     //rname = preg->name ;
8669     //pic14_emitcode("movwf","fsr");
8670     emitpcode(POC_MOVFW, popGet(AOP(result),0));
8671     emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8672     emitpcode(POC_MOVFW, popGet(AOP(right),0));
8673     emitpcode(POC_MOVWF, popCopyReg(&pc_indf));
8674     goto release;
8675     
8676   }// else
8677   //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8678   
8679   
8680   /* if bitfield then unpack the bits */
8681   if (IS_BITFIELD(retype)) {
8682     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8683       "The programmer is obviously confused");
8684     //genPackBits (retype,right,rname,POINTER);
8685     exit(1);
8686   }
8687   else {
8688     /* we have can just get the values */
8689     int size = AOP_SIZE(right);
8690     int offset = 0 ;    
8691     
8692     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8693     while (size--) {
8694       l = aopGet(AOP(right),offset,FALSE,TRUE);
8695       if (*l == '@' ) {
8696         //MOVA(l);
8697         //pic14_emitcode("mov","@%s,a",rname);
8698         pic14_emitcode("movf","indf,w ;1");
8699       } else {
8700         
8701         if (AOP_TYPE(right) == AOP_LIT) {
8702           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8703           if(lit) {
8704             pic14_emitcode("movlw","%s",l);
8705             pic14_emitcode("movwf","indf ;2");
8706           } else 
8707             pic14_emitcode("clrf","indf");
8708         }else {
8709           pic14_emitcode("movf","%s,w",l);
8710           pic14_emitcode("movwf","indf ;2");
8711         }
8712         //pic14_emitcode("mov","@%s,%s",rname,l);
8713       }
8714       if (size)
8715         pic14_emitcode("incf","fsr,f ;3");
8716       //pic14_emitcode("inc","%s",rname);
8717       offset++;
8718     }
8719   }
8720   
8721   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8722   /* now some housekeeping stuff */
8723   if (aop) {
8724     /* we had to allocate for this iCode */
8725     freeAsmop(NULL,aop,ic,TRUE);
8726   } else { 
8727   /* we did not allocate which means left
8728   already in a pointer register, then
8729   if size > 0 && this could be used again
8730   we have to point it back to where it 
8731     belongs */
8732     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8733     if (AOP_SIZE(right) > 1 &&
8734       !OP_SYMBOL(result)->remat &&
8735       ( OP_SYMBOL(result)->liveTo > ic->seq ||
8736       ic->depth )) {
8737       int size = AOP_SIZE(right) - 1;
8738       while (size--)
8739         pic14_emitcode("decf","fsr,f");
8740       //pic14_emitcode("dec","%s",rname);
8741     }
8742   }
8743   
8744   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8745   /* done */
8746 release:
8747   freeAsmop(right,NULL,ic,TRUE);
8748   freeAsmop(result,NULL,ic,TRUE);
8749 }
8750
8751 /*-----------------------------------------------------------------*/
8752 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8753 /*-----------------------------------------------------------------*/
8754 static void genPagedPointerSet (operand *right,
8755                 operand *result, 
8756                 iCode *ic)
8757 {
8758   asmop *aop = NULL;
8759   regs *preg = NULL ;
8760   char *rname , *l;
8761   sym_link *retype;
8762   
8763   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8764   
8765   retype= getSpec(operandType(right));
8766   
8767   aopOp(result,ic,FALSE);
8768   
8769   /* if the value is already in a pointer register
8770   then don't need anything more */
8771   if (!AOP_INPREG(AOP(result))) {
8772     /* otherwise get a free pointer register */
8773     aop = newAsmop(0);
8774     preg = getFreePtr(ic,&aop,FALSE);
8775     pic14_emitcode("mov","%s,%s",
8776       preg->name,
8777       aopGet(AOP(result),0,FALSE,TRUE));
8778     rname = preg->name ;
8779   } else
8780     rname = aopGet(AOP(result),0,FALSE,FALSE);
8781   
8782   freeAsmop(result,NULL,ic,TRUE);
8783   aopOp (right,ic,FALSE);
8784   
8785   /* if bitfield then unpack the bits */
8786   if (IS_BITFIELD(retype)) 
8787     genPackBits (retype,right,rname,PPOINTER);
8788   else {
8789     /* we have can just get the values */
8790     int size = AOP_SIZE(right);
8791     int offset = 0 ;  
8792     
8793     while (size--) {
8794       l = aopGet(AOP(right),offset,FALSE,TRUE);
8795       
8796       MOVA(l);
8797       pic14_emitcode("movx","@%s,a",rname);
8798       
8799       if (size)
8800         pic14_emitcode("inc","%s",rname);
8801       
8802       offset++;
8803     }
8804   }
8805   
8806   /* now some housekeeping stuff */
8807   if (aop) {
8808     /* we had to allocate for this iCode */
8809     freeAsmop(NULL,aop,ic,TRUE);
8810   } else { 
8811   /* we did not allocate which means left
8812      already in a pointer register, then
8813      if size > 0 && this could be used again
8814      we have to point it back to where it 
8815     belongs */
8816     if (AOP_SIZE(right) > 1 &&
8817       !OP_SYMBOL(result)->remat &&
8818       ( OP_SYMBOL(result)->liveTo > ic->seq ||
8819       ic->depth )) {
8820       int size = AOP_SIZE(right) - 1;
8821       while (size--)
8822         pic14_emitcode("dec","%s",rname);
8823     }
8824   }
8825   
8826   /* done */
8827   freeAsmop(right,NULL,ic,TRUE);
8828   
8829   
8830 }
8831
8832 /*-----------------------------------------------------------------*/
8833 /* genFarPointerSet - set value from far space                     */
8834 /*-----------------------------------------------------------------*/
8835 static void genFarPointerSet (operand *right,
8836                 operand *result, iCode *ic)
8837 {
8838   int size, offset ;
8839   sym_link *retype = getSpec(operandType(right));
8840   
8841   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8842   aopOp(result,ic,FALSE);
8843   
8844   /* if the operand is already in dptr 
8845   then we do nothing else we move the value to dptr */
8846   if (AOP_TYPE(result) != AOP_STR) {
8847     /* if this is remateriazable */
8848     if (AOP_TYPE(result) == AOP_IMMD)
8849       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8850     else { /* we need to get it byte by byte */
8851       pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8852       pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8853       if (options.model == MODEL_FLAT24)
8854       {
8855         pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8856       }
8857     }
8858   }
8859   /* so dptr know contains the address */
8860   freeAsmop(result,NULL,ic,TRUE);
8861   aopOp(right,ic,FALSE);
8862   
8863   /* if bit then unpack */
8864   if (IS_BITFIELD(retype)) 
8865     genPackBits(retype,right,"dptr",FPOINTER);
8866   else {
8867     size = AOP_SIZE(right);
8868     offset = 0 ;
8869     
8870     while (size--) {
8871       char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8872       MOVA(l);
8873       pic14_emitcode("movx","@dptr,a");
8874       if (size)
8875         pic14_emitcode("inc","dptr");
8876     }
8877   }
8878   
8879   freeAsmop(right,NULL,ic,TRUE);
8880 }
8881
8882 /*-----------------------------------------------------------------*/
8883 /* genGenPointerSet - set value from generic pointer space         */
8884 /*-----------------------------------------------------------------*/
8885 static void genGenPointerSet (operand *right,
8886                 operand *result, iCode *ic)
8887 {
8888   int size, offset ;
8889   sym_link *retype = getSpec(operandType(right));
8890   
8891   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8892   
8893   aopOp(result,ic,FALSE);
8894   aopOp(right,ic,FALSE);
8895   size = AOP_SIZE(right);
8896   
8897   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8898   
8899   /* if the operand is already in dptr 
8900   then we do nothing else we move the value to dptr */
8901   if (AOP_TYPE(result) != AOP_STR) {
8902     /* if this is remateriazable */
8903     if (AOP_TYPE(result) == AOP_IMMD) {
8904       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8905       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8906     }
8907     else { /* we need to get it byte by byte */
8908       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8909       size = AOP_SIZE(right);
8910       offset = 0 ;
8911       
8912       /* hack hack! see if this the FSR. If so don't load W */
8913       if(AOP_TYPE(right) != AOP_ACC) {
8914         
8915         
8916         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8917         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8918         
8919         if(AOP_SIZE(result) > 1) {
8920           emitpcode(POC_BCF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8921           emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8922           emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8923           
8924         }
8925         
8926         //if(size==2)
8927         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8928         //if(size==4) {
8929         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8930         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8931         //}
8932         
8933         while(size--) {
8934           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
8935           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8936           
8937           if(size)
8938             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8939         }
8940         
8941         
8942         goto release;
8943       } 
8944       
8945       if(aopIdx(AOP(result),0) != 4) {
8946         
8947         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8948         goto release;
8949       }
8950       
8951       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8952       goto release;
8953       
8954     }
8955   }
8956   /* so dptr know contains the address */
8957   
8958   
8959   /* if bit then unpack */
8960   if (IS_BITFIELD(retype)) 
8961     genPackBits(retype,right,"dptr",GPOINTER);
8962   else {
8963     size = AOP_SIZE(right);
8964     offset = 0 ;
8965     
8966     DEBUGpic14_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
8967     
8968     while (size--) {
8969       
8970       emitpcode(POC_MOVFW,popGet(AOP(result),offset));
8971       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8972       
8973       if (AOP_TYPE(right) == AOP_LIT) 
8974         emitpcode(POC_MOVLW, popGet(AOP(right),offset));
8975       else
8976         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8977       
8978       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8979       
8980       offset++;
8981     }
8982   }
8983   
8984 release:
8985   freeAsmop(right,NULL,ic,TRUE);
8986   freeAsmop(result,NULL,ic,TRUE);
8987 }
8988
8989 /*-----------------------------------------------------------------*/
8990 /* genPointerSet - stores the value into a pointer location        */
8991 /*-----------------------------------------------------------------*/
8992 static void genPointerSet (iCode *ic)
8993 {    
8994   operand *right, *result ;
8995   sym_link *type, *etype;
8996   int p_type;
8997   
8998   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8999   
9000   right = IC_RIGHT(ic);
9001   result = IC_RESULT(ic) ;
9002   
9003   /* depending on the type of pointer we need to
9004   move it to the correct pointer register */
9005   type = operandType(result);
9006   etype = getSpec(type);
9007   /* if left is of type of pointer then it is simple */
9008   if (IS_PTR(type) && !IS_FUNC(type->next)) {
9009     p_type = DCL_TYPE(type);
9010   }
9011   else {
9012     /* we have to go by the storage class */
9013     p_type = PTR_TYPE(SPEC_OCLS(etype));
9014     
9015     /*  if (SPEC_OCLS(etype)->codesp ) { */
9016     /*      p_type = CPOINTER ;  */
9017     /*  } */
9018     /*  else */
9019     /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9020     /*    p_type = FPOINTER ; */
9021     /*      else */
9022     /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9023     /*        p_type = PPOINTER ; */
9024     /*    else */
9025     /*        if (SPEC_OCLS(etype) == idata ) */
9026     /*      p_type = IPOINTER ; */
9027     /*        else */
9028     /*      p_type = POINTER ; */
9029   }
9030   
9031   /* now that we have the pointer type we assign
9032   the pointer values */
9033   switch (p_type) {
9034     
9035   case POINTER:
9036   case IPOINTER:
9037     genNearPointerSet (right,result,ic);
9038     break;
9039     
9040   case PPOINTER:
9041     genPagedPointerSet (right,result,ic);
9042     break;
9043     
9044   case FPOINTER:
9045     genFarPointerSet (right,result,ic);
9046     break;
9047     
9048   case GPOINTER:
9049     genGenPointerSet (right,result,ic);
9050     break;
9051     
9052   default:
9053     werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9054       "genPointerSet: illegal pointer type");
9055   }
9056 }
9057
9058 /*-----------------------------------------------------------------*/
9059 /* genIfx - generate code for Ifx statement                        */
9060 /*-----------------------------------------------------------------*/
9061 static void genIfx (iCode *ic, iCode *popIc)
9062 {
9063   operand *cond = IC_COND(ic);
9064   int isbit =0;
9065   
9066   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9067   
9068   aopOp(cond,ic,FALSE);
9069   
9070   /* get the value into acc */
9071   if (AOP_TYPE(cond) != AOP_CRY)
9072     pic14_toBoolean(cond);
9073   else
9074     isbit = 1;
9075   /* the result is now in the accumulator */
9076   freeAsmop(cond,NULL,ic,TRUE);
9077   
9078   /* if there was something to be popped then do it */
9079   if (popIc)
9080     genIpop(popIc);
9081   
9082   /* if the condition is  a bit variable */
9083   if (isbit && IS_ITEMP(cond) && 
9084     SPIL_LOC(cond)) {
9085     genIfxJump(ic,SPIL_LOC(cond)->rname);
9086     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9087   }
9088   else {
9089     if (isbit && !IS_ITEMP(cond))
9090       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9091     else
9092       genIfxJump(ic,"a");
9093   }
9094   ic->generated = 1;
9095   
9096 }
9097
9098 /*-----------------------------------------------------------------*/
9099 /* genAddrOf - generates code for address of                       */
9100 /*-----------------------------------------------------------------*/
9101 static void genAddrOf (iCode *ic)
9102 {
9103   operand *right, *result, *left;
9104   int size, offset ;
9105   
9106   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9107   
9108   
9109   //aopOp(IC_RESULT(ic),ic,FALSE);
9110   
9111   aopOp((left=IC_LEFT(ic)),ic,FALSE);
9112   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9113   aopOp((result=IC_RESULT(ic)),ic,TRUE);
9114   
9115   DEBUGpic14_AopType(__LINE__,left,right,result);
9116   
9117   size = AOP_SIZE(IC_RESULT(ic));
9118   offset = 0;
9119   
9120   while (size--) {
9121     /* fixing bug #863624, reported from (errolv) */
9122     emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9123     emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9124     
9125 #if 0
9126     emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9127     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9128 #endif
9129     offset++;
9130   }
9131   
9132   freeAsmop(left,NULL,ic,FALSE);
9133   freeAsmop(result,NULL,ic,TRUE);
9134   
9135 }
9136
9137 #if 0
9138 /*-----------------------------------------------------------------*/
9139 /* genFarFarAssign - assignment when both are in far space         */
9140 /*-----------------------------------------------------------------*/
9141 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9142 {
9143   int size = AOP_SIZE(right);
9144   int offset = 0;
9145   char *l ;
9146   /* first push the right side on to the stack */
9147   while (size--) {
9148     l = aopGet(AOP(right),offset++,FALSE,FALSE);
9149     MOVA(l);
9150     pic14_emitcode ("push","acc");
9151   }
9152   
9153   freeAsmop(right,NULL,ic,FALSE);
9154   /* now assign DPTR to result */
9155   aopOp(result,ic,FALSE);
9156   size = AOP_SIZE(result);
9157   while (size--) {
9158     pic14_emitcode ("pop","acc");
9159     aopPut(AOP(result),"a",--offset);
9160   }
9161   freeAsmop(result,NULL,ic,FALSE);
9162   
9163 }
9164 #endif
9165
9166 /*-----------------------------------------------------------------*/
9167 /* genAssign - generate code for assignment                        */
9168 /*-----------------------------------------------------------------*/
9169 static void genAssign (iCode *ic)
9170 {
9171   operand *result, *right;
9172   int size, offset,know_W;
9173   unsigned long lit = 0L;
9174   
9175   result = IC_RESULT(ic);
9176   right  = IC_RIGHT(ic) ;
9177   
9178   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9179   
9180   /* if they are the same */
9181   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9182     return ;
9183   
9184   aopOp(right,ic,FALSE);
9185   aopOp(result,ic,TRUE);
9186   
9187   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9188   
9189   /* if they are the same registers */
9190   if (pic14_sameRegs(AOP(right),AOP(result)))
9191     goto release;
9192   
9193   /* if the result is a bit */
9194   if (AOP_TYPE(result) == AOP_CRY) {
9195     
9196   /* if the right size is a literal then
9197     we know what the value is */
9198     if (AOP_TYPE(right) == AOP_LIT) {
9199       
9200       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9201         popGet(AOP(result),0));
9202       
9203       if (((int) operandLitValue(right))) 
9204         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9205         AOP(result)->aopu.aop_dir,
9206         AOP(result)->aopu.aop_dir);
9207       else
9208         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9209         AOP(result)->aopu.aop_dir,
9210         AOP(result)->aopu.aop_dir);
9211       goto release;
9212     }
9213     
9214     /* the right is also a bit variable */
9215     if (AOP_TYPE(right) == AOP_CRY) {
9216       emitpcode(POC_BCF,    popGet(AOP(result),0));
9217       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9218       emitpcode(POC_BSF,    popGet(AOP(result),0));
9219       
9220       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9221         AOP(result)->aopu.aop_dir,
9222         AOP(result)->aopu.aop_dir);
9223       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9224         AOP(right)->aopu.aop_dir,
9225         AOP(right)->aopu.aop_dir);
9226       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9227         AOP(result)->aopu.aop_dir,
9228         AOP(result)->aopu.aop_dir);
9229       goto release ;
9230     }
9231     
9232     /* we need to or */
9233     emitpcode(POC_BCF,    popGet(AOP(result),0));
9234     pic14_toBoolean(right);
9235     emitSKPZ;
9236     emitpcode(POC_BSF,    popGet(AOP(result),0));
9237     //aopPut(AOP(result),"a",0);
9238     goto release ;
9239   }
9240   
9241   /* bit variables done */
9242   /* general case */
9243   size = AOP_SIZE(result);
9244   offset = 0 ;
9245   if(AOP_TYPE(right) == AOP_LIT)
9246     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9247   
9248   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9249     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9250     if(aopIdx(AOP(result),0) == 4) {
9251       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9252       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9253       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9254       goto release;
9255     } else
9256       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9257   }
9258   
9259   know_W=-1;
9260   while (size--) {
9261     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9262     if(AOP_TYPE(right) == AOP_LIT) {
9263       if(lit&0xff) {
9264         if(know_W != (int)(lit&0xff))
9265           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9266         know_W = lit&0xff;
9267         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9268       } else
9269         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9270       
9271       lit >>= 8;
9272       
9273     } else if (AOP_TYPE(right) == AOP_CRY) {
9274       emitpcode(POC_CLRF, popGet(AOP(result),offset));
9275       if(offset == 0) {
9276         emitpcode(POC_BTFSS, popGet(AOP(right),0));
9277         emitpcode(POC_INCF, popGet(AOP(result),0));
9278       }
9279     } else {
9280       mov2w (AOP(right), offset);
9281       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9282     }
9283     
9284     offset++;
9285   }
9286   
9287   
9288 release:
9289   freeAsmop (right,NULL,ic,FALSE);
9290   freeAsmop (result,NULL,ic,TRUE);
9291 }   
9292
9293 /*-----------------------------------------------------------------*/
9294 /* genJumpTab - genrates code for jump table                       */
9295 /*-----------------------------------------------------------------*/
9296 static void genJumpTab (iCode *ic)
9297 {
9298   symbol *jtab;
9299   char *l;
9300   
9301   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9302   
9303   aopOp(IC_JTCOND(ic),ic,FALSE);
9304   /* get the condition into accumulator */
9305   l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9306   MOVA(l);
9307   /* multiply by three */
9308   pic14_emitcode("add","a,acc");
9309   pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9310   
9311   jtab = newiTempLabel(NULL);
9312   pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9313   pic14_emitcode("jmp","@a+dptr");
9314   pic14_emitcode("","%05d_DS_:",jtab->key+100);
9315   
9316   emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
9317   emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
9318   emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9319   emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9320   emitSKPNC;
9321   emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9322   emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9323   emitpLabel(jtab->key);
9324   
9325   freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9326   
9327   /* now generate the jump labels */
9328   for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9329   jtab = setNextItem(IC_JTLABELS(ic))) {
9330     pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9331     emitpcode(POC_GOTO,popGetLabel(jtab->key));
9332     
9333   }
9334   
9335 }
9336
9337 /*-----------------------------------------------------------------*/
9338 /* genMixedOperation - gen code for operators between mixed types  */
9339 /*-----------------------------------------------------------------*/
9340 /*
9341 TSD - Written for the PIC port - but this unfortunately is buggy.
9342 This routine is good in that it is able to efficiently promote 
9343 types to different (larger) sizes. Unfortunately, the temporary
9344 variables that are optimized out by this routine are sometimes
9345 used in other places. So until I know how to really parse the 
9346 iCode tree, I'm going to not be using this routine :(.
9347 */
9348 static int genMixedOperation (iCode *ic)
9349 {
9350 #if 0
9351   operand *result = IC_RESULT(ic);
9352   sym_link *ctype = operandType(IC_LEFT(ic));
9353   operand *right = IC_RIGHT(ic);
9354   int ret = 0;
9355   int big,small;
9356   int offset;
9357   
9358   iCode *nextic;
9359   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9360   
9361   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9362   
9363   nextic = ic->next;
9364   if(!nextic)
9365     return 0;
9366   
9367   nextright = IC_RIGHT(nextic);
9368   nextleft  = IC_LEFT(nextic);
9369   nextresult = IC_RESULT(nextic);
9370   
9371   aopOp(right,ic,FALSE);
9372   aopOp(result,ic,FALSE);
9373   aopOp(nextright,  nextic, FALSE);
9374   aopOp(nextleft,   nextic, FALSE);
9375   aopOp(nextresult, nextic, FALSE);
9376   
9377   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9378     
9379     operand *t = right;
9380     right = nextright;
9381     nextright = t; 
9382     
9383     pic14_emitcode(";remove right +","");
9384     
9385   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9386   /*
9387   operand *t = right;
9388   right = nextleft;
9389   nextleft = t; 
9390     */
9391     pic14_emitcode(";remove left +","");
9392   } else
9393     return 0;
9394   
9395   big = AOP_SIZE(nextleft);
9396   small = AOP_SIZE(nextright);
9397   
9398   switch(nextic->op) {
9399     
9400   case '+':
9401     pic14_emitcode(";optimize a +","");
9402     /* if unsigned or not an integral type */
9403     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9404       pic14_emitcode(";add a bit to something","");
9405     } else {
9406       
9407       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9408       
9409       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9410         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9411         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9412       } else
9413         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9414       
9415       offset = 0;
9416       while(--big) {
9417         
9418         offset++;
9419         
9420         if(--small) {
9421           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9422             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9423             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9424           }
9425           
9426           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9427           emitSKPNC;
9428           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9429             AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9430             AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9431           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9432           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9433           
9434         } else {
9435           pic14_emitcode("rlf","known_zero,w");
9436           
9437           /*
9438           if right is signed
9439           btfsc  right,7
9440           addlw ff
9441           */
9442           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9443             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9444             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9445           } else {
9446             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9447           }
9448         }
9449       }
9450       ret = 1;
9451     }
9452   }
9453   ret = 1;
9454   
9455 release:
9456   freeAsmop(right,NULL,ic,TRUE);
9457   freeAsmop(result,NULL,ic,TRUE);
9458   freeAsmop(nextright,NULL,ic,TRUE);
9459   freeAsmop(nextleft,NULL,ic,TRUE);
9460   if(ret)
9461     nextic->generated = 1;
9462   
9463   return ret;
9464 #else
9465   return 0;
9466 #endif
9467 }
9468 /*-----------------------------------------------------------------*/
9469 /* genCast - gen code for casting                                  */
9470 /*-----------------------------------------------------------------*/
9471 static void genCast (iCode *ic)
9472 {
9473   operand *result = IC_RESULT(ic);
9474   sym_link *ctype = operandType(IC_LEFT(ic));
9475   sym_link *rtype = operandType(IC_RIGHT(ic));
9476   operand *right = IC_RIGHT(ic);
9477   int size, offset ;
9478   
9479   DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9480   /* if they are equivalent then do nothing */
9481   if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9482     return ;
9483   
9484   aopOp(right,ic,FALSE) ;
9485   aopOp(result,ic,FALSE);
9486   
9487   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9488   
9489   /* if the result is a bit */
9490   if (AOP_TYPE(result) == AOP_CRY) {
9491   /* if the right size is a literal then
9492     we know what the value is */
9493     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9494     if (AOP_TYPE(right) == AOP_LIT) {
9495       
9496       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9497         popGet(AOP(result),0));
9498       
9499       if (((int) operandLitValue(right))) 
9500         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9501         AOP(result)->aopu.aop_dir,
9502         AOP(result)->aopu.aop_dir);
9503       else
9504         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9505         AOP(result)->aopu.aop_dir,
9506         AOP(result)->aopu.aop_dir);
9507       
9508       goto release;
9509     }
9510     
9511     /* the right is also a bit variable */
9512     if (AOP_TYPE(right) == AOP_CRY) {
9513       
9514       emitCLRC;
9515       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9516       
9517       pic14_emitcode("clrc","");
9518       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9519         AOP(right)->aopu.aop_dir,
9520         AOP(right)->aopu.aop_dir);
9521       aopPut(AOP(result),"c",0);
9522       goto release ;
9523     }
9524     
9525     /* we need to or */
9526     if (AOP_TYPE(right) == AOP_REG) {
9527       emitpcode(POC_BCF,    popGet(AOP(result),0));
9528       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9529       emitpcode(POC_BSF,    popGet(AOP(result),0));
9530     }
9531     pic14_toBoolean(right);
9532     aopPut(AOP(result),"a",0);
9533     goto release ;
9534   }
9535   
9536   if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9537     int offset = 1;
9538     size = AOP_SIZE(result);
9539     
9540     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9541     
9542     emitpcode(POC_CLRF,   popGet(AOP(result),0));
9543     emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9544     emitpcode(POC_INCF,   popGet(AOP(result),0));
9545     
9546     while (size--)
9547       emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9548     
9549     goto release;
9550   }
9551   
9552   /* if they are the same size : or less */
9553   if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9554     
9555     /* if they are in the same place */
9556     if (pic14_sameRegs(AOP(right),AOP(result)))
9557       goto release;
9558     
9559     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9560     if (IS_PTR_CONST(rtype))
9561       DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9562     if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9563       DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9564     
9565     if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9566       emitpcode(POC_MOVLW, popGet(AOP(right),0));
9567       emitpcode(POC_MOVWF, popGet(AOP(result),0));
9568       emitpcode(POC_MOVLW, popGet(AOP(right),1));
9569       emitpcode(POC_MOVWF, popGet(AOP(result),1));
9570       if(AOP_SIZE(result) <2)
9571         fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9572       
9573     } else {
9574       
9575       /* if they in different places then copy */
9576       size = AOP_SIZE(result);
9577       offset = 0 ;
9578       while (size--) {
9579         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9580         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9581         
9582         //aopPut(AOP(result),
9583         // aopGet(AOP(right),offset,FALSE,FALSE),
9584         // offset);
9585         
9586         offset++;
9587       }
9588     }
9589     goto release;
9590   }
9591   
9592   
9593   /* if the result is of type pointer */
9594   if (IS_PTR(ctype)) {
9595     
9596     int p_type;
9597     sym_link *type = operandType(right);
9598     sym_link *etype = getSpec(type);
9599     DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9600     
9601     /* pointer to generic pointer */
9602     if (IS_GENPTR(ctype)) {
9603       char *l = zero;
9604       
9605       if (IS_PTR(type)) 
9606         p_type = DCL_TYPE(type);
9607       else {
9608         /* we have to go by the storage class */
9609         p_type = PTR_TYPE(SPEC_OCLS(etype));
9610         
9611         /*    if (SPEC_OCLS(etype)->codesp )  */
9612         /*        p_type = CPOINTER ;  */
9613         /*    else */
9614         /*        if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9615         /*      p_type = FPOINTER ; */
9616         /*        else */
9617         /*      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9618         /*          p_type = PPOINTER; */
9619         /*      else */
9620         /*          if (SPEC_OCLS(etype) == idata ) */
9621         /*        p_type = IPOINTER ; */
9622         /*          else */
9623         /*        p_type = POINTER ; */
9624       }
9625       
9626       /* the first two bytes are known */
9627       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9628       size = GPTRSIZE - 1; 
9629       offset = 0 ;
9630       while (size--) {
9631         if(offset < AOP_SIZE(right)) {
9632           DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9633           if ((AOP_TYPE(right) == AOP_PCODE) && 
9634             AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9635             emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9636             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9637           } else { 
9638             aopPut(AOP(result),
9639               aopGet(AOP(right),offset,FALSE,FALSE),
9640               offset);
9641           }
9642         } else 
9643           emitpcode(POC_CLRF,popGet(AOP(result),offset));
9644         offset++;
9645       }
9646       /* the last byte depending on type */
9647       switch (p_type) {
9648       case IPOINTER:
9649       case POINTER:
9650         emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9651         break;
9652       case FPOINTER:
9653         pic14_emitcode(";BUG!? ","%d",__LINE__);
9654         l = one;
9655         break;
9656       case CPOINTER:
9657         pic14_emitcode(";BUG!? ","%d",__LINE__);
9658         l = "#0x02";
9659         break;        
9660       case PPOINTER:
9661         pic14_emitcode(";BUG!? ","%d",__LINE__);
9662         l = "#0x03";
9663         break;
9664         
9665       default:
9666         /* this should never happen */
9667         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9668           "got unknown pointer type");
9669         exit(1);
9670       }
9671       //aopPut(AOP(result),l, GPTRSIZE - 1);      
9672       goto release ;
9673     }
9674     
9675     /* just copy the pointers */
9676     size = AOP_SIZE(result);
9677     offset = 0 ;
9678     while (size--) {
9679       aopPut(AOP(result),
9680         aopGet(AOP(right),offset,FALSE,FALSE),
9681         offset);
9682       offset++;
9683     }
9684     goto release ;
9685   }
9686   
9687   
9688   
9689   /* so we now know that the size of destination is greater
9690   than the size of the source.
9691   Now, if the next iCode is an operator then we might be
9692   able to optimize the operation without performing a cast.
9693   */
9694   if(genMixedOperation(ic))
9695     goto release;
9696   
9697   DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9698   
9699   /* we move to result for the size of source */
9700   size = AOP_SIZE(right);
9701   offset = 0 ;
9702   while (size--) {
9703     emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9704     emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9705     offset++;
9706   }
9707   
9708   /* now depending on the sign of the destination */
9709   size = AOP_SIZE(result) - AOP_SIZE(right);
9710   /* if unsigned or not an integral type */
9711   if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9712     while (size--)
9713       emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9714   } else {
9715     /* we need to extend the sign :{ */
9716     
9717     if(size == 1) {
9718       /* Save one instruction of casting char to int */
9719       emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9720       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9721       emitpcode(POC_DECF,   popGet(AOP(result),offset));
9722     } else {
9723       emitpcodeNULLop(POC_CLRW);
9724       
9725       if(offset)
9726         emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9727       else
9728         emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9729       
9730       emitpcode(POC_MOVLW,   popGetLit(0xff));
9731       
9732       while (size--)
9733         emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9734     }
9735   }
9736   
9737 release:
9738   freeAsmop(right,NULL,ic,TRUE);
9739   freeAsmop(result,NULL,ic,TRUE);
9740   
9741 }
9742
9743 /*-----------------------------------------------------------------*/
9744 /* genDjnz - generate decrement & jump if not zero instrucion      */
9745 /*-----------------------------------------------------------------*/
9746 static int genDjnz (iCode *ic, iCode *ifx)
9747 {
9748   symbol *lbl, *lbl1;
9749   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9750   
9751   if (!ifx)
9752     return 0;
9753   
9754     /* if the if condition has a false label
9755   then we cannot save */
9756   if (IC_FALSE(ifx))
9757     return 0;
9758   
9759     /* if the minus is not of the form 
9760   a = a - 1 */
9761   if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9762     !IS_OP_LITERAL(IC_RIGHT(ic)))
9763     return 0;
9764   
9765   if (operandLitValue(IC_RIGHT(ic)) != 1)
9766     return 0;
9767   
9768     /* if the size of this greater than one then no
9769   saving */
9770   if (getSize(operandType(IC_RESULT(ic))) > 1)
9771     return 0;
9772   
9773   /* otherwise we can save BIG */
9774   lbl = newiTempLabel(NULL);
9775   lbl1= newiTempLabel(NULL);
9776   
9777   aopOp(IC_RESULT(ic),ic,FALSE);
9778   
9779   if (IS_AOP_PREG(IC_RESULT(ic))) {
9780     pic14_emitcode("dec","%s",
9781       aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9782     pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9783     pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9784   } else {  
9785     
9786     
9787     emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9788     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9789     
9790     pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9791     pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9792     
9793   }
9794   /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9795   /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9796   /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9797   /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9798   
9799   
9800   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9801   ifx->generated = 1;
9802   return 1;
9803 }
9804
9805 /*-----------------------------------------------------------------*/
9806 /* genReceive - generate code for a receive iCode                  */
9807 /*-----------------------------------------------------------------*/
9808 static void genReceive (iCode *ic)
9809 {
9810   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9811   
9812   if (isOperandInFarSpace(IC_RESULT(ic)) &&
9813     ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9814     IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9815     
9816     int size = getSize(operandType(IC_RESULT(ic)));
9817     int offset =  fReturnSizePic - size;
9818     while (size--) {
9819       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9820         fReturn[fReturnSizePic - offset - 1] : "acc"));
9821       offset++;
9822     }
9823     aopOp(IC_RESULT(ic),ic,FALSE);
9824     size = AOP_SIZE(IC_RESULT(ic));
9825     offset = 0;
9826     while (size--) {
9827       pic14_emitcode ("pop","acc");
9828       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9829     }
9830     
9831   } else {
9832     _G.accInUse++;
9833     aopOp(IC_RESULT(ic),ic,FALSE);
9834     _G.accInUse--;
9835     assignResultValue(IC_RESULT(ic));
9836   }
9837   
9838   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9839 }
9840
9841 /*-----------------------------------------------------------------*/
9842 /* genDummyRead - generate code for dummy read of volatiles        */
9843 /*-----------------------------------------------------------------*/
9844 static void
9845 genDummyRead (iCode * ic)
9846 {
9847   pic14_emitcode ("; genDummyRead","");
9848   pic14_emitcode ("; not implemented","");
9849   
9850   ic = ic;
9851 }
9852
9853 /*-----------------------------------------------------------------*/
9854 /* genpic14Code - generate code for pic14 based controllers        */
9855 /*-----------------------------------------------------------------*/
9856 /*
9857 * At this point, ralloc.c has gone through the iCode and attempted
9858 * to optimize in a way suitable for a PIC. Now we've got to generate
9859 * PIC instructions that correspond to the iCode.
9860 *
9861 * Once the instructions are generated, we'll pass through both the
9862 * peep hole optimizer and the pCode optimizer.
9863 *-----------------------------------------------------------------*/
9864
9865 void genpic14Code (iCode *lic)
9866 {
9867   iCode *ic;
9868   int cln = 0;
9869   
9870   lineHead = lineCurr = NULL;
9871   
9872   pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9873   addpBlock(pb);
9874   
9875   /* if debug information required */
9876   if (options.debug && currFunc) { 
9877     if (currFunc) {
9878       debugFile->writeFunction(currFunc);
9879       _G.debugLine = 1;
9880       if (IS_STATIC(currFunc->etype)) {
9881         pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9882         //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9883       } else {
9884         pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9885         //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9886       }
9887       _G.debugLine = 0;
9888     }
9889   }
9890   
9891   
9892   for (ic = lic ; ic ; ic = ic->next ) {
9893     
9894     DEBUGpic14_emitcode(";ic","");
9895     if ( cln != ic->lineno ) {
9896       if ( options.debug ) {
9897         _G.debugLine = 1;
9898         pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9899           FileBaseName(ic->filename),ic->lineno,
9900           ic->level,ic->block);
9901         _G.debugLine = 0;
9902       }
9903       /*
9904       pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9905       pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9906       printCLine(ic->filename, ic->lineno));
9907       */
9908       if (!options.noCcodeInAsm) {
9909         addpCode2pBlock(pb,
9910           newpCodeCSource(ic->lineno, 
9911           ic->filename, 
9912           printCLine(ic->filename, ic->lineno)));
9913       }
9914       
9915       cln = ic->lineno ;
9916     }
9917     
9918     // if you want printILine too, look at ../mcs51/gen.c, i don't understand this :)
9919     
9920     /* if the result is marked as
9921     spilt and rematerializable or code for
9922     this has already been generated then
9923     do nothing */
9924     if (resultRemat(ic) || ic->generated ) 
9925       continue ;
9926     
9927     /* depending on the operation */
9928     switch (ic->op) {
9929     case '!' :
9930       genNot(ic);
9931       break;
9932       
9933     case '~' :
9934       genCpl(ic);
9935       break;
9936       
9937     case UNARYMINUS:
9938       genUminus (ic);
9939       break;
9940       
9941     case IPUSH:
9942       genIpush (ic);
9943       break;
9944       
9945     case IPOP:
9946     /* IPOP happens only when trying to restore a 
9947     spilt live range, if there is an ifx statement
9948     following this pop then the if statement might
9949     be using some of the registers being popped which
9950     would destory the contents of the register so
9951       we need to check for this condition and handle it */
9952       if (ic->next            && 
9953         ic->next->op == IFX &&
9954         regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9955         genIfx (ic->next,ic);
9956       else
9957         genIpop (ic);
9958       break; 
9959       
9960     case CALL:
9961       genCall (ic);
9962       break;
9963       
9964     case PCALL:
9965       genPcall (ic);
9966       break;
9967       
9968     case FUNCTION:
9969       genFunction (ic);
9970       break;
9971       
9972     case ENDFUNCTION:
9973       genEndFunction (ic);
9974       break;
9975       
9976     case RETURN:
9977       genRet (ic);
9978       break;
9979       
9980     case LABEL:
9981       genLabel (ic);
9982       break;
9983       
9984     case GOTO:
9985       genGoto (ic);
9986       break;
9987       
9988     case '+' :
9989       genPlus (ic) ;
9990       break;
9991       
9992     case '-' :
9993       if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9994         genMinus (ic);
9995       break;
9996       
9997     case '*' :
9998       genMult (ic);
9999       break;
10000       
10001     case '/' :
10002       genDiv (ic) ;
10003       break;
10004       
10005     case '%' :
10006       genMod (ic);
10007       break;
10008       
10009     case '>' :
10010       genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10011       break;
10012       
10013     case '<' :
10014       genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10015       break;
10016       
10017     case LE_OP:
10018     case GE_OP:
10019     case NE_OP:
10020       
10021     /* note these two are xlated by algebraic equivalence
10022       during parsing SDCC.y */
10023       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10024         "got '>=' or '<=' shouldn't have come here");
10025       break;  
10026       
10027     case EQ_OP:
10028       genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10029       break;      
10030       
10031     case AND_OP:
10032       genAndOp (ic);
10033       break;
10034       
10035     case OR_OP:
10036       genOrOp (ic);
10037       break;
10038       
10039     case '^' :
10040       genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10041       break;
10042       
10043     case '|' :
10044       genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10045       break;
10046       
10047     case BITWISEAND:
10048       genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10049       break;
10050       
10051     case INLINEASM:
10052       genInline (ic);
10053       break;
10054       
10055     case RRC:
10056       genRRC (ic);
10057       break;
10058       
10059     case RLC:
10060       genRLC (ic);
10061       break;
10062       
10063     case GETHBIT:
10064       genGetHbit (ic);
10065       break;
10066       
10067     case LEFT_OP:
10068       genLeftShift (ic);
10069       break;
10070       
10071     case RIGHT_OP:
10072       genRightShift (ic);
10073       break;
10074       
10075     case GET_VALUE_AT_ADDRESS:
10076       genPointerGet(ic);
10077       break;
10078       
10079     case '=' :
10080       if (POINTER_SET(ic))
10081         genPointerSet(ic);
10082       else
10083         genAssign(ic);
10084       break;
10085       
10086     case IFX:
10087       genIfx (ic,NULL);
10088       break;
10089       
10090     case ADDRESS_OF:
10091       genAddrOf (ic);
10092       break;
10093       
10094     case JUMPTABLE:
10095       genJumpTab (ic);
10096       break;
10097       
10098     case CAST:
10099       genCast (ic);
10100       break;
10101       
10102     case RECEIVE:
10103       genReceive(ic);
10104       break;
10105       
10106     case SEND:
10107       addSet(&_G.sendSet,ic);
10108       break;
10109       
10110     case DUMMY_READ_VOLATILE:
10111       genDummyRead (ic);
10112       break;
10113       
10114     default :
10115       ic = ic;
10116     }
10117   }
10118   
10119   
10120   /* now we are ready to call the
10121   peep hole optimizer */
10122   if (!options.nopeep) {
10123     peepHole (&lineHead);
10124   }
10125   /* now do the actual printing */
10126   printLine (lineHead,codeOutFile);
10127   
10128 #ifdef PCODE_DEBUG
10129   DFPRINTF((stderr,"printing pBlock\n\n"));
10130   printpBlock(stdout,pb);
10131 #endif
10132   
10133   return;
10134 }