* src/mcs51/gen.c (genCmp): fixed bug #975903
[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 /* pic14_emitDebuggerSymbol - associate the current code location  */
270 /*   with a debugger symbol                                        */
271 /*-----------------------------------------------------------------*/
272 void
273 pic14_emitDebuggerSymbol (char * debugSym)
274 {
275   _G.debugLine = 1;
276   pic14_emitcode ("", ";%s ==.", debugSym);
277   _G.debugLine = 0;
278 }
279
280
281 /*-----------------------------------------------------------------*/
282 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
283 /*-----------------------------------------------------------------*/
284 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
285 {
286   bool r0iu = FALSE , r1iu = FALSE;
287   bool r0ou = FALSE , r1ou = FALSE;
288   
289   /* the logic: if r0 & r1 used in the instruction
290   then we are in trouble otherwise */
291   
292   /* first check if r0 & r1 are used by this
293   instruction, in which case we are in trouble */
294   if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
295     (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
296   {
297     goto endOfWorld;      
298   }
299   
300   r0ou = bitVectBitValue(ic->rMask,R0_IDX);
301   r1ou = bitVectBitValue(ic->rMask,R1_IDX);
302   
303   /* if no usage of r0 then return it */
304   if (!r0iu && !r0ou) {
305     ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
306     (*aopp)->type = AOP_R0;
307     
308     return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
309   }
310   
311   /* if no usage of r1 then return it */
312   if (!r1iu && !r1ou) {
313     ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
314     (*aopp)->type = AOP_R1;
315     
316     return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
317   }    
318   
319   /* now we know they both have usage */
320   /* if r0 not used in this instruction */
321   if (!r0iu) {
322     /* push it if not already pushed */
323     if (!_G.r0Pushed) {
324       //pic14_emitcode ("push","%s",
325       //          pic14_regWithIdx(R0_IDX)->dname);
326       _G.r0Pushed++ ;
327     }
328     
329     ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
330     (*aopp)->type = AOP_R0;
331     
332     return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
333   }
334   
335   /* if r1 not used then */
336   
337   if (!r1iu) {
338     /* push it if not already pushed */
339     if (!_G.r1Pushed) {
340       //pic14_emitcode ("push","%s",
341       //          pic14_regWithIdx(R1_IDX)->dname);
342       _G.r1Pushed++ ;
343     }
344     
345     ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
346     (*aopp)->type = AOP_R1;
347     return pic14_regWithIdx(R1_IDX);
348   }
349   
350 endOfWorld :
351   /* I said end of world but not quite end of world yet */
352   /* if this is a result then we can push it on the stack*/
353   if (result) {
354     (*aopp)->type = AOP_STK;    
355     return NULL;
356   }
357   
358   /* other wise this is true end of the world */
359   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
360     "getFreePtr should never reach here");
361   exit(0);
362 }
363
364 /*-----------------------------------------------------------------*/
365 /* newAsmop - creates a new asmOp                                  */
366 /*-----------------------------------------------------------------*/
367 asmop *newAsmop (short type)
368 {
369   asmop *aop;
370   
371   aop = Safe_calloc(1,sizeof(asmop));
372   aop->type = type;
373   return aop;
374 }
375
376 static void genSetDPTR(int n)
377 {
378   if (!n)
379   {
380     pic14_emitcode(";", "Select standard DPTR");
381     pic14_emitcode("mov", "dps, #0x00");
382   }
383   else
384   {
385     pic14_emitcode(";", "Select alternate DPTR");
386     pic14_emitcode("mov", "dps, #0x01");
387   }
388 }
389
390 /*-----------------------------------------------------------------*/
391 /* resolveIfx - converts an iCode ifx into a form more useful for  */
392 /*              generating code                                    */
393 /*-----------------------------------------------------------------*/
394 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
395 {
396   if(!resIfx) 
397     return;
398   
399   //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
400   
401   resIfx->condition = 1;    /* assume that the ifx is true */
402   resIfx->generated = 0;    /* indicate that the ifx has not been used */
403   
404   if(!ifx) {
405     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
406                       /*
407                       DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
408                       __FUNCTION__,__LINE__,resIfx->lbl->key);
409     */
410   } else {
411     if(IC_TRUE(ifx)) {
412       resIfx->lbl = IC_TRUE(ifx);
413     } else {
414       resIfx->lbl = IC_FALSE(ifx);
415       resIfx->condition = 0;
416     }
417     /*
418     if(IC_TRUE(ifx)) 
419     DEBUGpic14_emitcode("; ***","ifx true is non-null");
420     if(IC_FALSE(ifx)) 
421     DEBUGpic14_emitcode("; ***","ifx false is non-null");
422     */
423   }
424   
425   //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
426   
427 }
428 /*-----------------------------------------------------------------*/
429 /* pointerCode - returns the code for a pointer type               */
430 /*-----------------------------------------------------------------*/
431 static int pointerCode (sym_link *etype)
432 {
433   
434   return PTR_TYPE(SPEC_OCLS(etype));
435   
436 }
437
438 /*-----------------------------------------------------------------*/
439 /* aopForSym - for a true symbol                                   */
440 /*-----------------------------------------------------------------*/
441 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
442 {
443   asmop *aop;
444   memmap *space= SPEC_OCLS(sym->etype);
445   
446   DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
447   /* if already has one */
448   if (sym->aop)
449     return sym->aop;
450   
451   /* assign depending on the storage class */
452   /* if it is on the stack or indirectly addressable */
453   /* space we need to assign either r0 or r1 to it   */    
454   if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
455     sym->aop = aop = newAsmop(0);
456     aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
457     aop->size = getSize(sym->type);
458     
459     /* now assign the address of the variable to 
460     the pointer register */
461     if (aop->type != AOP_STK) {
462       
463       if (sym->onStack) {
464         if ( _G.accInUse )
465           pic14_emitcode("push","acc");
466         
467         pic14_emitcode("mov","a,_bp");
468         pic14_emitcode("add","a,#0x%02x",
469           ((sym->stack < 0) ?
470           ((char)(sym->stack - _G.nRegsSaved )) :
471         ((char)sym->stack)) & 0xff);
472         pic14_emitcode("mov","%s,a",
473           aop->aopu.aop_ptr->name);
474         
475         if ( _G.accInUse )
476           pic14_emitcode("pop","acc");
477       } else
478         pic14_emitcode("mov","%s,#%s",
479         aop->aopu.aop_ptr->name,
480         sym->rname);
481       aop->paged = space->paged;
482     } else
483       aop->aopu.aop_stk = sym->stack;
484     return aop;
485   }
486   
487   if (sym->onStack && options.stack10bit)
488   {
489   /* It's on the 10 bit stack, which is located in
490   * far data space.
491     */
492     
493     //DEBUGpic14_emitcode(";","%d",__LINE__);
494     
495     if ( _G.accInUse )
496       pic14_emitcode("push","acc");
497     
498     pic14_emitcode("mov","a,_bp");
499     pic14_emitcode("add","a,#0x%02x",
500       ((sym->stack < 0) ?
501       ((char)(sym->stack - _G.nRegsSaved )) :
502     ((char)sym->stack)) & 0xff);
503     
504     genSetDPTR(1);
505     pic14_emitcode ("mov","dpx1,#0x40");
506     pic14_emitcode ("mov","dph1,#0x00");
507     pic14_emitcode ("mov","dpl1, a");
508     genSetDPTR(0);
509     
510     if ( _G.accInUse )
511       pic14_emitcode("pop","acc");
512     
513     sym->aop = aop = newAsmop(AOP_DPTR2);
514     aop->size = getSize(sym->type); 
515     return aop;
516   }
517   
518   //DEBUGpic14_emitcode(";","%d",__LINE__);
519   /* if in bit space */
520   if (IN_BITSPACE(space)) {
521     sym->aop = aop = newAsmop (AOP_CRY);
522     aop->aopu.aop_dir = sym->rname ;
523     aop->size = getSize(sym->type);
524     //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
525     return aop;
526   }
527   /* if it is in direct space */
528   if (IN_DIRSPACE(space)) {
529     sym->aop = aop = newAsmop (AOP_DIR);
530     aop->aopu.aop_dir = sym->rname ;
531     aop->size = getSize(sym->type);
532     DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
533     return aop;
534   }
535   
536   /* special case for a function */
537   if (IS_FUNC(sym->type)) {   
538     
539     sym->aop = aop = newAsmop(AOP_PCODE);
540     aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
541     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
542     PCOI(aop->aopu.pcop)->_function = 1;
543     PCOI(aop->aopu.pcop)->index = 0;
544     aop->size = FPTRSIZE; 
545     /*
546     sym->aop = aop = newAsmop(AOP_IMMD);    
547     aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
548     strcpy(aop->aopu.aop_immd,sym->rname);
549     aop->size = FPTRSIZE; 
550     */
551     DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
552     return aop;
553   }
554   
555   
556   /* only remaining is far space */
557   /* in which case DPTR gets the address */
558   sym->aop = aop = newAsmop(AOP_PCODE);
559   
560   aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
561   PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
562   PCOI(aop->aopu.pcop)->index = 0;
563   
564   DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
565     __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
566   
567   allocDirReg (IC_LEFT(ic));
568   
569   aop->size = FPTRSIZE; 
570   /*
571   DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
572   sym->aop = aop = newAsmop(AOP_DPTR);
573   pic14_emitcode ("mov","dptr,#%s", sym->rname);
574   aop->size = getSize(sym->type);
575   
576     DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
577   */
578   
579   /* if it is in code space */
580   if (IN_CODESPACE(space))
581     aop->code = 1;
582   
583   return aop;     
584 }
585
586 /*-----------------------------------------------------------------*/
587 /* aopForRemat - rematerialzes an object                           */
588 /*-----------------------------------------------------------------*/
589 static asmop *aopForRemat (operand *op) // x symbol *sym)
590 {
591   symbol *sym = OP_SYMBOL(op);
592   iCode *ic = NULL;
593   asmop *aop = newAsmop(AOP_PCODE);
594   int val = 0;
595   int offset = 0;
596   
597   ic = sym->rematiCode;
598   
599   DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
600   if(IS_OP_POINTER(op)) {
601     DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
602   }
603   for (;;) {
604     if (ic->op == '+') {
605       val += (int) operandLitValue(IC_RIGHT(ic));
606     } else if (ic->op == '-') {
607       val -= (int) operandLitValue(IC_RIGHT(ic));
608     } else
609       break;
610     
611     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
612   }
613   
614   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
615   aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
616   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
617   PCOI(aop->aopu.pcop)->index = val;
618   
619   DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
620     __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
621     val, IS_PTR_CONST(operandType(op)));
622   
623   //    DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
624   
625   allocDirReg (IC_LEFT(ic));
626   
627   return aop;        
628 }
629
630 int aopIdx (asmop *aop, int offset)
631 {
632   if(!aop)
633     return -1;
634   
635   if(aop->type !=  AOP_REG)
636     return -2;
637   
638   return aop->aopu.aop_reg[offset]->rIdx;
639   
640 }
641 /*-----------------------------------------------------------------*/
642 /* regsInCommon - two operands have some registers in common       */
643 /*-----------------------------------------------------------------*/
644 static bool regsInCommon (operand *op1, operand *op2)
645 {
646   symbol *sym1, *sym2;
647   int i;
648   
649   /* if they have registers in common */
650   if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
651     return FALSE ;
652   
653   sym1 = OP_SYMBOL(op1);
654   sym2 = OP_SYMBOL(op2);
655   
656   if (sym1->nRegs == 0 || sym2->nRegs == 0)
657     return FALSE ;
658   
659   for (i = 0 ; i < sym1->nRegs ; i++) {
660     int j;
661     if (!sym1->regs[i])
662       continue ;
663     
664     for (j = 0 ; j < sym2->nRegs ;j++ ) {
665       if (!sym2->regs[j])
666         continue ;
667       
668       if (sym2->regs[j] == sym1->regs[i])
669         return TRUE ;
670     }
671   }
672   
673   return FALSE ;
674 }
675
676 /*-----------------------------------------------------------------*/
677 /* operandsEqu - equivalent                                        */
678 /*-----------------------------------------------------------------*/
679 static bool operandsEqu ( operand *op1, operand *op2)
680 {
681   symbol *sym1, *sym2;
682   
683   /* if they not symbols */
684   if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
685     return FALSE;
686   
687   sym1 = OP_SYMBOL(op1);
688   sym2 = OP_SYMBOL(op2);
689   
690   /* if both are itemps & one is spilt
691   and the other is not then false */
692   if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
693     sym1->isspilt != sym2->isspilt )
694     return FALSE ;
695   
696   /* if they are the same */
697   if (sym1 == sym2)
698     return TRUE ;
699   
700   if (sym1->rname[0] && sym2->rname[0]
701       && strcmp (sym1->rname, sym2->rname) == 0)
702     return TRUE;
703
704   
705   /* if left is a tmp & right is not */
706   if (IS_ITEMP(op1)  && 
707     !IS_ITEMP(op2) &&
708     sym1->isspilt  &&
709     (sym1->usl.spillLoc == sym2))
710     return TRUE;
711   
712   if (IS_ITEMP(op2)  && 
713     !IS_ITEMP(op1) &&
714     sym2->isspilt  &&
715     sym1->level > 0 &&
716     (sym2->usl.spillLoc == sym1))
717     return TRUE ;
718   
719   return FALSE ;
720 }
721
722 /*-----------------------------------------------------------------*/
723 /* pic14_sameRegs - two asmops have the same registers                   */
724 /*-----------------------------------------------------------------*/
725 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
726 {
727   int i;
728   
729   if (aop1 == aop2)
730     return TRUE ;
731   
732   if (aop1->type != AOP_REG ||
733     aop2->type != AOP_REG )
734     return FALSE ;
735   
736   if (aop1->size != aop2->size )
737     return FALSE ;
738   
739   for (i = 0 ; i < aop1->size ; i++ )
740     if (aop1->aopu.aop_reg[i] !=
741       aop2->aopu.aop_reg[i] )
742       return FALSE ;
743     
744     return TRUE ;
745 }
746
747 /*-----------------------------------------------------------------*/
748 /* aopOp - allocates an asmop for an operand  :                    */
749 /*-----------------------------------------------------------------*/
750 void aopOp (operand *op, iCode *ic, bool result)
751 {
752   asmop *aop;
753   symbol *sym;
754   int i;
755   
756   if (!op)
757     return ;
758   
759   //    DEBUGpic14_emitcode(";","%d",__LINE__);
760   /* if this a literal */
761   if (IS_OP_LITERAL(op)) {
762     op->aop = aop = newAsmop(AOP_LIT);
763     aop->aopu.aop_lit = op->operand.valOperand;
764     aop->size = getSize(operandType(op));
765     return;
766   }
767   
768   {
769     sym_link *type = operandType(op);
770     if(IS_PTR_CONST(type))
771       DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
772   }
773   
774   /* if already has a asmop then continue */
775   if (op->aop)
776     return ;
777   
778   /* if the underlying symbol has a aop */
779   if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
780     DEBUGpic14_emitcode(";","%d",__LINE__);
781     op->aop = OP_SYMBOL(op)->aop;
782     return;
783   }
784   
785   /* if this is a true symbol */
786   if (IS_TRUE_SYMOP(op)) {    
787     //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
788     op->aop = aopForSym(ic,OP_SYMBOL(op),result);
789     return ;
790   }
791   
792   /* this is a temporary : this has
793   only four choices :
794   a) register
795   b) spillocation
796   c) rematerialize 
797   d) conditional   
798   e) can be a return use only */
799   
800   sym = OP_SYMBOL(op);
801   
802   
803   /* if the type is a conditional */
804   if (sym->regType == REG_CND) {
805     aop = op->aop = sym->aop = newAsmop(AOP_CRY);
806     aop->size = 0;
807     return;
808   }
809   
810   /* if it is spilt then two situations
811   a) is rematerialize 
812   b) has a spill location */
813   if (sym->isspilt || sym->nRegs == 0) {
814     
815     DEBUGpic14_emitcode(";","%d",__LINE__);
816     /* rematerialize it NOW */
817     if (sym->remat) {
818       
819       sym->aop = op->aop = aop =
820         aopForRemat (op);
821       aop->size = getSize(sym->type);
822       //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
823       return;
824     }
825     
826     if (sym->accuse) {
827       int i;
828       aop = op->aop = sym->aop = newAsmop(AOP_ACC);
829       aop->size = getSize(sym->type);
830       for ( i = 0 ; i < 2 ; i++ )
831         aop->aopu.aop_str[i] = accUse[i];
832       DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
833       return;  
834     }
835     
836     if (sym->ruonly ) {
837       if(sym->isptr) {  // && sym->uptr 
838         aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
839         aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
840         
841         //PCOI(aop->aopu.pcop)->_const = 0;
842         //PCOI(aop->aopu.pcop)->index = 0;
843         /*
844         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
845         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
846         */
847         //allocDirReg (IC_LEFT(ic));
848         
849         aop->size = getSize(sym->type);
850         DEBUGpic14_emitcode(";","%d",__LINE__);
851         return;
852         
853       } else {
854         
855         unsigned i;
856         
857         aop = op->aop = sym->aop = newAsmop(AOP_STR);
858         aop->size = getSize(sym->type);
859         for ( i = 0 ; i < fReturnSizePic ; i++ )
860           aop->aopu.aop_str[i] = fReturn[i];
861         
862         DEBUGpic14_emitcode(";","%d",__LINE__);
863         return;
864       }
865     }
866     
867     /* else spill location  */
868     if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
869       /* force a new aop if sizes differ */
870       sym->usl.spillLoc->aop = NULL;
871     }
872     DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
873       __FUNCTION__,__LINE__,
874       sym->usl.spillLoc->rname,
875       sym->rname, sym->usl.spillLoc->offset);
876     
877     sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
878     //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
879     aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
880       getSize(sym->type), 
881       sym->usl.spillLoc->offset);
882     aop->size = getSize(sym->type);
883     
884     return;
885   }
886   
887   {
888     sym_link *type = operandType(op);
889     if(IS_PTR_CONST(type)) 
890       DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
891   }
892   
893   /* must be in a register */
894   DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
895   sym->aop = op->aop = aop = newAsmop(AOP_REG);
896   aop->size = sym->nRegs;
897   for ( i = 0 ; i < sym->nRegs ;i++)
898     aop->aopu.aop_reg[i] = sym->regs[i];
899 }
900
901 /*-----------------------------------------------------------------*/
902 /* freeAsmop - free up the asmop given to an operand               */
903 /*----------------------------------------------------------------*/
904 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
905 {   
906   asmop *aop ;
907   
908   if (!op)
909     aop = aaop;
910   else 
911     aop = op->aop;
912   
913   if (!aop)
914     return ;
915   
916   if (aop->freed)
917     goto dealloc; 
918   
919   aop->freed = 1;
920   
921   /* depending on the asmop type only three cases need work AOP_RO
922   , AOP_R1 && AOP_STK */
923 #if 0
924   switch (aop->type) {
925   case AOP_R0 :
926     if (_G.r0Pushed ) {
927       if (pop) {
928         pic14_emitcode ("pop","ar0");     
929         _G.r0Pushed--;
930       }
931     }
932     bitVectUnSetBit(ic->rUsed,R0_IDX);
933     break;
934     
935   case AOP_R1 :
936     if (_G.r1Pushed ) {
937       if (pop) {
938         pic14_emitcode ("pop","ar1");
939         _G.r1Pushed--;
940       }
941     }
942     bitVectUnSetBit(ic->rUsed,R1_IDX);          
943     break;
944     
945   case AOP_STK :
946     {
947       int sz = aop->size;    
948       int stk = aop->aopu.aop_stk + aop->size;
949       bitVectUnSetBit(ic->rUsed,R0_IDX);
950       bitVectUnSetBit(ic->rUsed,R1_IDX);          
951       
952       getFreePtr(ic,&aop,FALSE);
953       
954       if (options.stack10bit)
955       {
956         /* I'm not sure what to do here yet... */
957         /* #STUB */
958         fprintf(stderr, 
959           "*** Warning: probably generating bad code for "
960           "10 bit stack mode.\n");
961       }
962       
963       if (stk) {
964         pic14_emitcode ("mov","a,_bp");
965         pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
966         pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
967       } else {
968         pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
969       }
970       
971       while (sz--) {
972         pic14_emitcode("pop","acc");
973         pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
974         if (!sz) break;
975         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
976       }
977       op->aop = aop;
978       freeAsmop(op,NULL,ic,TRUE);
979       if (_G.r0Pushed) {
980         pic14_emitcode("pop","ar0");
981         _G.r0Pushed--;
982       }
983       
984       if (_G.r1Pushed) {
985         pic14_emitcode("pop","ar1");
986         _G.r1Pushed--;
987       }       
988     }
989   }
990 #endif
991   
992 dealloc:
993   /* all other cases just dealloc */
994   if (op ) {
995     op->aop = NULL;
996     if (IS_SYMOP(op)) {
997       OP_SYMBOL(op)->aop = NULL;    
998       /* if the symbol has a spill */
999       if (SPIL_LOC(op))
1000         SPIL_LOC(op)->aop = NULL;
1001     }
1002   }
1003 }
1004
1005 /*-----------------------------------------------------------------*/
1006 /* aopGet - for fetching value of the aop                          */
1007 /*-----------------------------------------------------------------*/
1008 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1009 {
1010   char *s = buffer ;
1011   char *rs;
1012   
1013   //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1014   /* offset is greater than
1015   size then zero */
1016   if (offset > (aop->size - 1) &&
1017     aop->type != AOP_LIT)
1018     return zero;
1019   
1020   /* depending on type */
1021   switch (aop->type) {
1022     
1023   case AOP_R0:
1024   case AOP_R1:
1025     DEBUGpic14_emitcode(";","%d",__LINE__);
1026     /* if we need to increment it */       
1027     while (offset > aop->coff) {        
1028       pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1029       aop->coff++;
1030     }
1031     
1032     while (offset < aop->coff) {
1033       pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1034       aop->coff--;
1035     }
1036     
1037     aop->coff = offset ;
1038     if (aop->paged) {
1039       pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1040       return (dname ? "acc" : "a");
1041     }       
1042     sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1043     rs = Safe_calloc(1,strlen(s)+1);
1044     strcpy(rs,s);   
1045     return rs;
1046     
1047   case AOP_DPTR:
1048   case AOP_DPTR2:
1049     DEBUGpic14_emitcode(";","%d",__LINE__);
1050     if (aop->type == AOP_DPTR2)
1051     {
1052       genSetDPTR(1);
1053     }
1054     
1055     while (offset > aop->coff) {
1056       pic14_emitcode ("inc","dptr");
1057       aop->coff++;
1058     }
1059     
1060     while (offset < aop->coff) {        
1061       pic14_emitcode("lcall","__decdptr");
1062       aop->coff--;
1063     }
1064     
1065     aop->coff = offset;
1066     if (aop->code) {
1067       pic14_emitcode("clr","a");
1068       pic14_emitcode("movc","a,@a+dptr");
1069     }
1070     else {
1071       pic14_emitcode("movx","a,@dptr");
1072     }
1073     
1074     if (aop->type == AOP_DPTR2)
1075     {
1076       genSetDPTR(0);
1077     }
1078     
1079     return (dname ? "acc" : "a");
1080     
1081     
1082   case AOP_IMMD:
1083     if (bit16) 
1084       sprintf (s,"%s",aop->aopu.aop_immd);
1085     else
1086       if (offset) 
1087         sprintf(s,"(%s >> %d)",
1088         aop->aopu.aop_immd,
1089         offset*8);
1090       else
1091         sprintf(s,"%s",
1092         aop->aopu.aop_immd);
1093       DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1094       rs = Safe_calloc(1,strlen(s)+1);
1095       strcpy(rs,s);   
1096       return rs;
1097       
1098   case AOP_DIR:
1099     if (offset) {
1100       sprintf(s,"(%s + %d)",
1101         aop->aopu.aop_dir,
1102         offset);
1103       DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1104     } else
1105       sprintf(s,"%s",aop->aopu.aop_dir);
1106     rs = Safe_calloc(1,strlen(s)+1);
1107     strcpy(rs,s);   
1108     return rs;
1109     
1110   case AOP_REG:
1111     //if (dname) 
1112     //    return aop->aopu.aop_reg[offset]->dname;
1113     //else
1114     return aop->aopu.aop_reg[offset]->name;
1115     
1116   case AOP_CRY:
1117     //pic14_emitcode(";","%d",__LINE__);
1118     return aop->aopu.aop_dir;
1119     
1120   case AOP_ACC:
1121     DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1122     return "AOP_accumulator_bug";
1123     
1124   case AOP_LIT:
1125     sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1126     rs = Safe_calloc(1,strlen(s)+1);
1127     strcpy(rs,s);   
1128     return rs;
1129     
1130   case AOP_STR:
1131     aop->coff = offset ;
1132     if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1133       dname)
1134       return "acc";
1135     DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1136     
1137     return aop->aopu.aop_str[offset];
1138     
1139   case AOP_PCODE:
1140     {
1141       pCodeOp *pcop = aop->aopu.pcop;
1142       DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1143       if(pcop->name) {
1144         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1145         //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1146         sprintf(s,"%s", pcop->name);
1147       } else
1148         sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1149       
1150     }
1151     rs = Safe_calloc(1,strlen(s)+1);
1152     strcpy(rs,s);   
1153     return rs;
1154     
1155   }
1156   
1157   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1158     "aopget got unsupported aop->type");
1159   exit(0);
1160 }
1161
1162
1163 /*-----------------------------------------------------------------*/
1164 /* popGetTempReg - create a new temporary pCodeOp                  */
1165 /*-----------------------------------------------------------------*/
1166 pCodeOp *popGetTempReg(void)
1167 {
1168   
1169   pCodeOp *pcop;
1170   
1171   pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1172   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1173     PCOR(pcop)->r->wasUsed=1;
1174     PCOR(pcop)->r->isFree=0;
1175   }
1176   
1177   return pcop;
1178 }
1179
1180 /*-----------------------------------------------------------------*/
1181 /* popGetTempReg - create a new temporary pCodeOp                  */
1182 /*-----------------------------------------------------------------*/
1183 void popReleaseTempReg(pCodeOp *pcop)
1184 {
1185   
1186   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1187     PCOR(pcop)->r->isFree = 1;
1188   
1189 }
1190 /*-----------------------------------------------------------------*/
1191 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1192 /*-----------------------------------------------------------------*/
1193 pCodeOp *popGetLabel(unsigned int key)
1194 {
1195   
1196   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1197   
1198   if(key>(unsigned int)max_key)
1199     max_key = key;
1200   
1201   return newpCodeOpLabel(NULL,key+100+labelOffset);
1202 }
1203
1204 /*-------------------------------------------------------------------*/
1205 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1206 /*-------------------------------------------------------------------*/
1207 pCodeOp *popGetHighLabel(unsigned int key)
1208 {
1209   pCodeOp *pcop;
1210   pcop = popGetLabel(key);
1211   PCOLAB(pcop)->offset = 1;
1212   return pcop;
1213 }
1214
1215 /*-----------------------------------------------------------------*/
1216 /* popGet - asm operator to pcode operator conversion              */
1217 /*-----------------------------------------------------------------*/
1218 pCodeOp *popGetLit(unsigned int lit)
1219 {
1220   
1221   return newpCodeOpLit(lit);
1222 }
1223
1224 /*-----------------------------------------------------------------*/
1225 /* popGetImmd - asm operator to pcode immediate conversion         */
1226 /*-----------------------------------------------------------------*/
1227 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1228 {
1229   
1230   return newpCodeOpImmd(name, offset,index, 0, is_func);
1231 }
1232
1233
1234 /*-----------------------------------------------------------------*/
1235 /* popGet - asm operator to pcode operator conversion              */
1236 /*-----------------------------------------------------------------*/
1237 pCodeOp *popGetWithString(char *str, int isExtern)
1238 {
1239   pCodeOp *pcop;
1240   
1241   
1242   if(!str) {
1243     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1244     exit (1);
1245   }
1246   
1247   pcop = newpCodeOp(str,PO_STR);
1248   PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1249   
1250   return pcop;
1251 }
1252
1253 /*-----------------------------------------------------------------*/
1254 /* popRegFromString -                                              */
1255 /*-----------------------------------------------------------------*/
1256 pCodeOp *popRegFromString(char *str, int size, int offset)
1257 {
1258   
1259   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1260   pcop->type = PO_DIR;
1261   
1262   DEBUGpic14_emitcode(";","%d",__LINE__);
1263   
1264   if(!str)
1265     str = "BAD_STRING";
1266   
1267   pcop->name = Safe_calloc(1,strlen(str)+1);
1268   strcpy(pcop->name,str);
1269   
1270   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1271   
1272   PCOR(pcop)->r = dirregWithName(pcop->name);
1273   if(PCOR(pcop)->r == NULL) {
1274     //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1275     PCOR(pcop)->r = allocRegByName (pcop->name,size);
1276     DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1277   } else {
1278     DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1279   }
1280   PCOR(pcop)->instance = offset;
1281   
1282   return pcop;
1283 }
1284
1285 /*-----------------------------------------------------------------*/
1286 /*-----------------------------------------------------------------*/
1287 pCodeOp *popRegFromIdx(int rIdx)
1288 {
1289   pCodeOp *pcop;
1290   
1291   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1292     __FUNCTION__,__LINE__,rIdx);
1293   
1294   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1295   
1296   PCOR(pcop)->rIdx = rIdx;
1297   PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1298   PCOR(pcop)->r->isFree = 0;
1299   PCOR(pcop)->r->wasUsed = 1;
1300   
1301   pcop->type = PCOR(pcop)->r->pc_type;
1302   
1303   
1304   return pcop;
1305 }
1306
1307 /*-----------------------------------------------------------------*/
1308 /* popGet - asm operator to pcode operator conversion              */
1309 /*-----------------------------------------------------------------*/
1310 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1311 {
1312   //char *s = buffer ;
1313   //char *rs;
1314   
1315   pCodeOp *pcop;
1316   
1317   //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1318   /* offset is greater than
1319   size then zero */
1320   
1321   if (offset > (aop->size - 1) &&
1322     aop->type != AOP_LIT)
1323     return NULL;  //zero;
1324   
1325   /* depending on type */
1326   switch (aop->type) {
1327     
1328   case AOP_R0:
1329   case AOP_R1:
1330   case AOP_DPTR:
1331   case AOP_DPTR2:
1332   case AOP_ACC:
1333     DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1334     return NULL;
1335     
1336   case AOP_IMMD:
1337     DEBUGpic14_emitcode(";","%d",__LINE__);
1338     return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1339     
1340   case AOP_DIR:
1341     return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1342 #if 0
1343     pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1344     pcop->type = PO_DIR;
1345     
1346     /*
1347     if (offset)
1348     sprintf(s,"(%s + %d)",
1349     aop->aopu.aop_dir,
1350     offset);
1351     else
1352     sprintf(s,"%s",aop->aopu.aop_dir);
1353     pcop->name = Safe_calloc(1,strlen(s)+1);
1354     strcpy(pcop->name,s);   
1355     */
1356     pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1357     strcpy(pcop->name,aop->aopu.aop_dir);   
1358     PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1359     if(PCOR(pcop)->r == NULL) {
1360       //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1361       PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1362       DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1363     } else {
1364       DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1365     }
1366     PCOR(pcop)->instance = offset;
1367     
1368     return pcop;
1369 #endif
1370     
1371   case AOP_REG:
1372     {
1373       int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1374       
1375       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1376       PCOR(pcop)->rIdx = rIdx;
1377       PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1378       PCOR(pcop)->r->wasUsed=1;
1379       PCOR(pcop)->r->isFree=0;
1380       
1381       PCOR(pcop)->instance = offset;
1382       pcop->type = PCOR(pcop)->r->pc_type;
1383       //rs = aop->aopu.aop_reg[offset]->name;
1384       DEBUGpic14_emitcode(";","%d regiser idx = %d ",__LINE__,rIdx);
1385       return pcop;
1386     }
1387     
1388   case AOP_CRY:
1389     pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1390     PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1391     //if(PCOR(pcop)->r == NULL)
1392     //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1393     return pcop;
1394     
1395   case AOP_LIT:
1396     return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1397     
1398   case AOP_STR:
1399     DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1400     return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1401     /*
1402     pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1403     PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1404     PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1405     pcop->type = PCOR(pcop)->r->pc_type;
1406     pcop->name = PCOR(pcop)->r->name;
1407     
1408       return pcop;
1409     */
1410     
1411   case AOP_PCODE:
1412     DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s) %d %s",pCodeOpType(aop->aopu.pcop),
1413       __LINE__, 
1414       ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1415     pcop = pCodeOpCopy(aop->aopu.pcop);
1416     PCOI(pcop)->offset = offset;
1417     return pcop;
1418   }
1419   
1420   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1421     "popGet got unsupported aop->type");
1422   exit(0);
1423 }
1424 /*-----------------------------------------------------------------*/
1425 /* aopPut - puts a string for a aop                                */
1426 /*-----------------------------------------------------------------*/
1427 void aopPut (asmop *aop, char *s, int offset)
1428 {
1429   char *d = buffer ;
1430   symbol *lbl ;
1431   
1432   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1433   
1434   if (aop->size && offset > ( aop->size - 1)) {
1435     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1436       "aopPut got offset > aop->size");
1437     exit(0);
1438   }
1439   
1440   /* will assign value to value */
1441   /* depending on where it is ofcourse */
1442   switch (aop->type) {
1443   case AOP_DIR:
1444     if (offset) {
1445       sprintf(d,"(%s + %d)",
1446         aop->aopu.aop_dir,offset);
1447       fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1448       
1449     } else
1450       sprintf(d,"%s",aop->aopu.aop_dir);
1451     
1452     if (strcmp(d,s)) {
1453       DEBUGpic14_emitcode(";","%d",__LINE__);
1454       if(strcmp(s,"W"))
1455         pic14_emitcode("movf","%s,w",s);
1456       pic14_emitcode("movwf","%s",d);
1457       
1458       if(strcmp(s,"W")) {
1459         pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1460         if(offset >= aop->size) {
1461           emitpcode(POC_CLRF,popGet(aop,offset));
1462           break;
1463         } else
1464           emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1465       }
1466       
1467       emitpcode(POC_MOVWF,popGet(aop,offset));
1468       
1469       
1470     }
1471     break;
1472     
1473   case AOP_REG:
1474     if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1475       //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1476       /*
1477       if (*s == '@'           ||
1478       strcmp(s,"r0") == 0 ||
1479       strcmp(s,"r1") == 0 ||
1480       strcmp(s,"r2") == 0 ||
1481       strcmp(s,"r3") == 0 ||
1482       strcmp(s,"r4") == 0 ||
1483       strcmp(s,"r5") == 0 ||
1484       strcmp(s,"r6") == 0 || 
1485       strcmp(s,"r7") == 0 )
1486       pic14_emitcode("mov","%s,%s  ; %d",
1487       aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1488       else
1489       */
1490       
1491       if(strcmp(s,"W")==0 )
1492         pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1493       
1494       pic14_emitcode("movwf","%s",
1495         aop->aopu.aop_reg[offset]->name);
1496       
1497       if(strcmp(s,zero)==0) {
1498         emitpcode(POC_CLRF,popGet(aop,offset));
1499         
1500       } else if(strcmp(s,"W")==0) {
1501         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1502         pcop->type = PO_GPR_REGISTER;
1503         
1504         PCOR(pcop)->rIdx = -1;
1505         PCOR(pcop)->r = NULL;
1506         
1507         DEBUGpic14_emitcode(";","%d",__LINE__);
1508         pcop->name = Safe_strdup(s);
1509         emitpcode(POC_MOVFW,pcop);
1510         emitpcode(POC_MOVWF,popGet(aop,offset));
1511       } else if(strcmp(s,one)==0) {
1512         emitpcode(POC_CLRF,popGet(aop,offset));
1513         emitpcode(POC_INCF,popGet(aop,offset));
1514       } else {
1515         emitpcode(POC_MOVWF,popGet(aop,offset));
1516       }
1517     }
1518     break;
1519     
1520   case AOP_DPTR:
1521   case AOP_DPTR2:
1522     
1523     if (aop->type == AOP_DPTR2)
1524     {
1525       genSetDPTR(1);
1526     }
1527     
1528     if (aop->code) {
1529       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1530         "aopPut writting to code space");
1531       exit(0);
1532     }
1533     
1534     while (offset > aop->coff) {
1535       aop->coff++;
1536       pic14_emitcode ("inc","dptr");
1537     }
1538     
1539     while (offset < aop->coff) {
1540       aop->coff-- ;
1541       pic14_emitcode("lcall","__decdptr");
1542     }
1543     
1544     aop->coff = offset;
1545     
1546     /* if not in accumulater */
1547     MOVA(s);
1548     
1549     pic14_emitcode ("movx","@dptr,a");
1550     
1551     if (aop->type == AOP_DPTR2)
1552     {
1553       genSetDPTR(0);
1554     }
1555     break;
1556     
1557   case AOP_R0:
1558   case AOP_R1:
1559     while (offset > aop->coff) {
1560       aop->coff++;
1561       pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1562     }
1563     while (offset < aop->coff) {
1564       aop->coff-- ;
1565       pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1566     }
1567     aop->coff = offset;
1568     
1569     if (aop->paged) {
1570       MOVA(s);           
1571       pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1572       
1573     } else
1574       if (*s == '@') {
1575         MOVA(s);
1576         pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1577       } else
1578         if (strcmp(s,"r0") == 0 ||
1579           strcmp(s,"r1") == 0 ||
1580           strcmp(s,"r2") == 0 ||
1581           strcmp(s,"r3") == 0 ||
1582           strcmp(s,"r4") == 0 ||
1583           strcmp(s,"r5") == 0 ||
1584           strcmp(s,"r6") == 0 || 
1585           strcmp(s,"r7") == 0 ) {
1586           char buffer[10];
1587           sprintf(buffer,"a%s",s);
1588           pic14_emitcode("mov","@%s,%s",
1589             aop->aopu.aop_ptr->name,buffer);
1590         } else
1591           pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1592         
1593         break;
1594         
1595   case AOP_STK:
1596     if (strcmp(s,"a") == 0)
1597       pic14_emitcode("push","acc");
1598     else
1599       pic14_emitcode("push","%s",s);
1600     
1601     break;
1602     
1603   case AOP_CRY:
1604     /* if bit variable */
1605     if (!aop->aopu.aop_dir) {
1606       pic14_emitcode("clr","a");
1607       pic14_emitcode("rlc","a");
1608     } else {
1609       if (s == zero) 
1610         pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1611       else
1612         if (s == one)
1613           pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1614         else
1615           if (!strcmp(s,"c"))
1616             pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1617           else {
1618             lbl = newiTempLabel(NULL);
1619             
1620             if (strcmp(s,"a")) {
1621               MOVA(s);
1622             }
1623             pic14_emitcode("clr","c");
1624             pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1625             pic14_emitcode("cpl","c");
1626             pic14_emitcode("","%05d_DS_:",lbl->key+100);
1627             pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1628           }
1629     }
1630     break;
1631     
1632   case AOP_STR:
1633     aop->coff = offset;
1634     if (strcmp(aop->aopu.aop_str[offset],s))
1635       pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1636     break;
1637     
1638   case AOP_ACC:
1639     aop->coff = offset;
1640     if (!offset && (strcmp(s,"acc") == 0))
1641       break;
1642     
1643     if (strcmp(aop->aopu.aop_str[offset],s))
1644       pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1645     break;
1646     
1647   default :
1648     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1649       "aopPut got unsupported aop->type");
1650     exit(0);    
1651   }    
1652   
1653 }
1654
1655 /*-----------------------------------------------------------------*/
1656 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1657 /*-----------------------------------------------------------------*/
1658 void mov2w (asmop *aop, int offset)
1659 {
1660   
1661   if(!aop)
1662     return;
1663   
1664   DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1665   
1666   if ( aop->type == AOP_PCODE ||
1667     aop->type == AOP_LIT ||
1668     aop->type == AOP_IMMD )
1669     emitpcode(POC_MOVLW,popGet(aop,offset));
1670   else
1671     emitpcode(POC_MOVFW,popGet(aop,offset));
1672   
1673 }
1674
1675 /*-----------------------------------------------------------------*/
1676 /* reAdjustPreg - points a register back to where it should        */
1677 /*-----------------------------------------------------------------*/
1678 static void reAdjustPreg (asmop *aop)
1679 {
1680   int size ;
1681   
1682   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1683   aop->coff = 0;
1684   if ((size = aop->size) <= 1)
1685     return ;
1686   size-- ;
1687   switch (aop->type) {
1688   case AOP_R0 :
1689   case AOP_R1 :
1690     while (size--)
1691       pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1692     break;          
1693   case AOP_DPTR :
1694   case AOP_DPTR2:
1695     if (aop->type == AOP_DPTR2)
1696     {
1697       genSetDPTR(1);
1698     } 
1699     while (size--)
1700     {
1701       pic14_emitcode("lcall","__decdptr");
1702     }
1703     
1704     if (aop->type == AOP_DPTR2)
1705     {
1706       genSetDPTR(0);
1707     }
1708     break;
1709     
1710   }
1711   
1712 }
1713
1714
1715 #if 0
1716 /*-----------------------------------------------------------------*/
1717 /* opIsGptr: returns non-zero if the passed operand is       */   
1718 /* a generic pointer type.             */
1719 /*-----------------------------------------------------------------*/ 
1720 static int opIsGptr(operand *op)
1721 {
1722   sym_link *type = operandType(op);
1723   
1724   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1725   if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1726   {
1727     return 1;
1728   }
1729   return 0;        
1730 }
1731 #endif
1732
1733 /*-----------------------------------------------------------------*/
1734 /* pic14_getDataSize - get the operand data size                         */
1735 /*-----------------------------------------------------------------*/
1736 int pic14_getDataSize(operand *op)
1737 {
1738   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1739   
1740   
1741   return AOP_SIZE(op);
1742   
1743   // tsd- in the pic port, the genptr size is 1, so this code here
1744   // fails. ( in the 8051 port, the size was 4).
1745 #if 0
1746   int size;
1747   size = AOP_SIZE(op);
1748   if (size == GPTRSIZE)
1749   {
1750     sym_link *type = operandType(op);
1751     if (IS_GENPTR(type))
1752     {
1753     /* generic pointer; arithmetic operations
1754     * should ignore the high byte (pointer type).
1755       */
1756       size--;
1757       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1758     }
1759   }
1760   return size;
1761 #endif
1762 }
1763
1764 /*-----------------------------------------------------------------*/
1765 /* pic14_outAcc - output Acc                                             */
1766 /*-----------------------------------------------------------------*/
1767 void pic14_outAcc(operand *result)
1768 {
1769   int size,offset;
1770   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1771   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1772   
1773   
1774   size = pic14_getDataSize(result);
1775   if(size){
1776     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1777     size--;
1778     offset = 1;
1779     /* unsigned or positive */
1780     while(size--)
1781       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1782   }
1783   
1784 }
1785
1786 /*-----------------------------------------------------------------*/
1787 /* pic14_outBitC - output a bit C                                        */
1788 /*-----------------------------------------------------------------*/
1789 void pic14_outBitC(operand *result)
1790 {
1791   
1792   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1793   /* if the result is bit */
1794   if (AOP_TYPE(result) == AOP_CRY) 
1795     aopPut(AOP(result),"c",0);
1796   else {
1797     pic14_emitcode("clr","a  ; %d", __LINE__);
1798     pic14_emitcode("rlc","a");
1799     pic14_outAcc(result);
1800   }
1801 }
1802
1803 /*-----------------------------------------------------------------*/
1804 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1805 /*-----------------------------------------------------------------*/
1806 void pic14_toBoolean(operand *oper)
1807 {
1808   int size = AOP_SIZE(oper) - 1;
1809   int offset = 1;
1810   
1811   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1812   
1813   if ( AOP_TYPE(oper) != AOP_ACC) {
1814     emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1815   }
1816   while (size--) {
1817     emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1818   }
1819 }
1820
1821
1822 /*-----------------------------------------------------------------*/
1823 /* genNot - generate code for ! operation                          */
1824 /*-----------------------------------------------------------------*/
1825 static void genNot (iCode *ic)
1826 {
1827   symbol *tlbl;
1828   int size;
1829   
1830   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1831   /* assign asmOps to operand & result */
1832   aopOp (IC_LEFT(ic),ic,FALSE);
1833   aopOp (IC_RESULT(ic),ic,TRUE);
1834   
1835   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1836   /* if in bit space then a special case */
1837   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1838     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1839       emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1840       emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1841     } else {
1842       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1843       emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1844       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1845     }
1846     goto release;
1847   }
1848   
1849   size = AOP_SIZE(IC_LEFT(ic));
1850   if(size == 1) {
1851     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1852     emitpcode(POC_ANDLW,popGetLit(1));
1853     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1854     goto release;
1855   }
1856   pic14_toBoolean(IC_LEFT(ic));
1857   
1858   tlbl = newiTempLabel(NULL);
1859   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1860   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1861   pic14_outBitC(IC_RESULT(ic));
1862   
1863 release:    
1864   /* release the aops */
1865   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1866   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1867 }
1868
1869
1870 /*-----------------------------------------------------------------*/
1871 /* genCpl - generate code for complement                           */
1872 /*-----------------------------------------------------------------*/
1873 static void genCpl (iCode *ic)
1874 {
1875   operand *left, *result;
1876   int size, offset=0;  
1877   
1878   
1879   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1880   aopOp((left = IC_LEFT(ic)),ic,FALSE);
1881   aopOp((result=IC_RESULT(ic)),ic,TRUE);
1882   
1883   /* if both are in bit space then 
1884   a special case */
1885   if (AOP_TYPE(result) == AOP_CRY &&
1886     AOP_TYPE(left) == AOP_CRY ) { 
1887     
1888     pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
1889     pic14_emitcode("cpl","c"); 
1890     pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
1891     goto release; 
1892   } 
1893   
1894   size = AOP_SIZE(result);
1895   while (size--) {
1896     
1897     if(AOP_TYPE(left) == AOP_ACC) 
1898       emitpcode(POC_XORLW, popGetLit(0xff));
1899     else
1900       emitpcode(POC_COMFW,popGet(AOP(left),offset));
1901     
1902     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1903     offset++;
1904   }
1905   
1906   
1907 release:
1908   /* release the aops */
1909   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1910   freeAsmop(result,NULL,ic,TRUE);
1911 }
1912
1913 /*-----------------------------------------------------------------*/
1914 /* genUminusFloat - unary minus for floating points                */
1915 /*-----------------------------------------------------------------*/
1916 static void genUminusFloat(operand *op,operand *result)
1917 {
1918   int size ,offset =0 ;
1919   char *l;
1920   
1921   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1922   /* for this we just need to flip the 
1923   first it then copy the rest in place */
1924   size = AOP_SIZE(op) - 1;
1925   l = aopGet(AOP(op),3,FALSE,FALSE);
1926   
1927   MOVA(l);    
1928   
1929   pic14_emitcode("cpl","acc.7");
1930   aopPut(AOP(result),"a",3);    
1931   
1932   while(size--) {
1933     aopPut(AOP(result),
1934       aopGet(AOP(op),offset,FALSE,FALSE),
1935       offset);
1936     offset++;
1937   }          
1938 }
1939
1940 /*-----------------------------------------------------------------*/
1941 /* genUminus - unary minus code generation                         */
1942 /*-----------------------------------------------------------------*/
1943 static void genUminus (iCode *ic)
1944 {
1945   int size, i;
1946   sym_link *optype, *rtype;
1947   
1948   
1949   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1950   /* assign asmops */
1951   aopOp(IC_LEFT(ic),ic,FALSE);
1952   aopOp(IC_RESULT(ic),ic,TRUE);
1953   
1954   /* if both in bit space then special
1955   case */
1956   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1957     AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1958     
1959     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1960     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1961     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1962     
1963     goto release; 
1964   } 
1965   
1966   optype = operandType(IC_LEFT(ic));
1967   rtype = operandType(IC_RESULT(ic));
1968   
1969   /* if float then do float stuff */
1970   if (IS_FLOAT(optype)) {
1971     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1972     goto release;
1973   }
1974   
1975   /* otherwise subtract from zero by taking the 2's complement */
1976   size = AOP_SIZE(IC_LEFT(ic));
1977   
1978   for(i=0; i<size; i++) {
1979     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1980       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1981     else {
1982       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1983       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1984     }
1985   }
1986   
1987   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
1988   for(i=1; i<size; i++) {
1989     emitSKPNZ;
1990     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
1991   }
1992   
1993 release:
1994   /* release the aops */
1995   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1996   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1997 }
1998
1999 /*-----------------------------------------------------------------*/
2000 /* saveRegisters - will look for a call and save the registers     */
2001 /*-----------------------------------------------------------------*/
2002 static void saveRegisters(iCode *lic) 
2003 {
2004   int i;
2005   iCode *ic;
2006   bitVect *rsave;
2007   sym_link *dtype;
2008   
2009   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2010   /* look for call */
2011   for (ic = lic ; ic ; ic = ic->next) 
2012     if (ic->op == CALL || ic->op == PCALL)
2013       break;
2014     
2015     if (!ic) {
2016       fprintf(stderr,"found parameter push with no function call\n");
2017       return ;
2018     }
2019     
2020     /* if the registers have been saved already then
2021     do nothing */
2022     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2023       return ;
2024     
2025       /* find the registers in use at this time 
2026     and push them away to safety */
2027     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2028       ic->rUsed);
2029     
2030     ic->regsSaved = 1;
2031     if (options.useXstack) {
2032       if (bitVectBitValue(rsave,R0_IDX))
2033         pic14_emitcode("mov","b,r0");
2034       pic14_emitcode("mov","r0,%s",spname);
2035       for (i = 0 ; i < pic14_nRegs ; i++) {
2036         if (bitVectBitValue(rsave,i)) {
2037           if (i == R0_IDX)
2038             pic14_emitcode("mov","a,b");
2039           else
2040             pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2041           pic14_emitcode("movx","@r0,a");
2042           pic14_emitcode("inc","r0");
2043         }
2044       }
2045       pic14_emitcode("mov","%s,r0",spname);
2046       if (bitVectBitValue(rsave,R0_IDX))
2047         pic14_emitcode("mov","r0,b");     
2048     }// else
2049     //for (i = 0 ; i < pic14_nRegs ; i++) {
2050     //    if (bitVectBitValue(rsave,i))
2051     //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2052     //}
2053     
2054     dtype = operandType(IC_LEFT(ic));
2055     if (currFunc && dtype && 
2056       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2057       IFFUNC_ISISR(currFunc->type) &&
2058       !ic->bankSaved) 
2059       
2060       saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2061     
2062 }
2063 /*-----------------------------------------------------------------*/
2064 /* unsaveRegisters - pop the pushed registers                      */
2065 /*-----------------------------------------------------------------*/
2066 static void unsaveRegisters (iCode *ic)
2067 {
2068   int i;
2069   bitVect *rsave;
2070   
2071   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2072   /* find the registers in use at this time 
2073   and push them away to safety */
2074   rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2075     ic->rUsed);
2076   
2077   if (options.useXstack) {
2078     pic14_emitcode("mov","r0,%s",spname); 
2079     for (i =  pic14_nRegs ; i >= 0 ; i--) {
2080       if (bitVectBitValue(rsave,i)) {
2081         pic14_emitcode("dec","r0");
2082         pic14_emitcode("movx","a,@r0");
2083         if (i == R0_IDX)
2084           pic14_emitcode("mov","b,a");
2085         else
2086           pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2087       }     
2088       
2089     }
2090     pic14_emitcode("mov","%s,r0",spname);
2091     if (bitVectBitValue(rsave,R0_IDX))
2092       pic14_emitcode("mov","r0,b");
2093   } //else
2094   //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2095   //    if (bitVectBitValue(rsave,i))
2096   //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2097   //}
2098   
2099 }  
2100
2101
2102 /*-----------------------------------------------------------------*/
2103 /* pushSide -                */
2104 /*-----------------------------------------------------------------*/
2105 static void pushSide(operand * oper, int size)
2106 {
2107 #if 0
2108   int offset = 0;
2109   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2110   while (size--) {
2111     char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2112     if (AOP_TYPE(oper) != AOP_REG &&
2113       AOP_TYPE(oper) != AOP_DIR &&
2114       strcmp(l,"a") ) {
2115       pic14_emitcode("mov","a,%s",l);
2116       pic14_emitcode("push","acc");
2117     } else
2118       pic14_emitcode("push","%s",l);
2119   }
2120 #endif
2121 }
2122
2123 /*-----------------------------------------------------------------*/
2124 /* assignResultValue -               */
2125 /*-----------------------------------------------------------------*/
2126 static void assignResultValue(operand * oper)
2127 {
2128   int size = AOP_SIZE(oper);
2129   
2130   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2131   
2132   DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2133   
2134   while (size--) {
2135     if (GpsuedoStkPtr++)
2136       emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2137     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2138   }
2139 }
2140
2141
2142 /*-----------------------------------------------------------------*/
2143 /* genIpush - genrate code for pushing this gets a little complex  */
2144 /*-----------------------------------------------------------------*/
2145 static void genIpush (iCode *ic)
2146 {
2147   
2148   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2149 #if 0
2150   int size, offset = 0 ;
2151   char *l;
2152   
2153   
2154   /* if this is not a parm push : ie. it is spill push 
2155   and spill push is always done on the local stack */
2156   if (!ic->parmPush) {
2157     
2158     /* and the item is spilt then do nothing */
2159     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2160       return ;
2161     
2162     aopOp(IC_LEFT(ic),ic,FALSE);
2163     size = AOP_SIZE(IC_LEFT(ic));
2164     /* push it on the stack */
2165     while(size--) {
2166       l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2167       if (*l == '#') {
2168         MOVA(l);
2169         l = "acc";
2170       }
2171       pic14_emitcode("push","%s",l);
2172     }
2173     return ;        
2174   }
2175   
2176   /* this is a paramter push: in this case we call
2177   the routine to find the call and save those
2178   registers that need to be saved */   
2179   saveRegisters(ic);
2180   
2181   /* then do the push */
2182   aopOp(IC_LEFT(ic),ic,FALSE);
2183   
2184   
2185   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2186   size = AOP_SIZE(IC_LEFT(ic));
2187   
2188   while (size--) {
2189     l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2190     if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2191       AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2192       strcmp(l,"a") ) {
2193       pic14_emitcode("mov","a,%s",l);
2194       pic14_emitcode("push","acc");
2195     } else
2196       pic14_emitcode("push","%s",l);
2197   }       
2198   
2199   freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2200 #endif
2201 }
2202
2203 /*-----------------------------------------------------------------*/
2204 /* genIpop - recover the registers: can happen only for spilling   */
2205 /*-----------------------------------------------------------------*/
2206 static void genIpop (iCode *ic)
2207 {
2208   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2209 #if 0
2210   int size,offset ;
2211   
2212   
2213   /* if the temp was not pushed then */
2214   if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2215     return ;
2216   
2217   aopOp(IC_LEFT(ic),ic,FALSE);
2218   size = AOP_SIZE(IC_LEFT(ic));
2219   offset = (size-1);
2220   while (size--) 
2221     pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2222     FALSE,TRUE));
2223   
2224   freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2225 #endif
2226 }
2227
2228 /*-----------------------------------------------------------------*/
2229 /* unsaverbank - restores the resgister bank from stack            */
2230 /*-----------------------------------------------------------------*/
2231 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2232 {
2233   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2234 #if 0
2235   int i;
2236   asmop *aop ;
2237   regs *r = NULL;
2238   
2239   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2240   if (popPsw) {
2241     if (options.useXstack) {
2242       aop = newAsmop(0);
2243       r = getFreePtr(ic,&aop,FALSE);
2244       
2245       
2246       pic14_emitcode("mov","%s,_spx",r->name);
2247       pic14_emitcode("movx","a,@%s",r->name);
2248       pic14_emitcode("mov","psw,a");
2249       pic14_emitcode("dec","%s",r->name);
2250       
2251     }else
2252       pic14_emitcode ("pop","psw");
2253   }
2254   
2255   for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2256     if (options.useXstack) {       
2257       pic14_emitcode("movx","a,@%s",r->name);
2258       //pic14_emitcode("mov","(%s+%d),a",
2259       //       regspic14[i].base,8*bank+regspic14[i].offset);
2260       pic14_emitcode("dec","%s",r->name);
2261       
2262     } else 
2263       pic14_emitcode("pop",""); //"(%s+%d)",
2264     //regspic14[i].base,8*bank); //+regspic14[i].offset);
2265   }
2266   
2267   if (options.useXstack) {
2268     
2269     pic14_emitcode("mov","_spx,%s",r->name);
2270     freeAsmop(NULL,aop,ic,TRUE);
2271     
2272   }
2273 #endif 
2274 }
2275
2276 /*-----------------------------------------------------------------*/
2277 /* saverbank - saves an entire register bank on the stack          */
2278 /*-----------------------------------------------------------------*/
2279 static void saverbank (int bank, iCode *ic, bool pushPsw)
2280 {
2281   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2282 #if 0
2283   int i;
2284   asmop *aop ;
2285   regs *r = NULL;
2286   
2287   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2288   if (options.useXstack) {
2289     
2290     aop = newAsmop(0);
2291     r = getFreePtr(ic,&aop,FALSE);  
2292     pic14_emitcode("mov","%s,_spx",r->name);
2293     
2294   }
2295   
2296   for (i = 0 ; i < pic14_nRegs ;i++) {
2297     if (options.useXstack) {
2298       pic14_emitcode("inc","%s",r->name);
2299       //pic14_emitcode("mov","a,(%s+%d)",
2300       //         regspic14[i].base,8*bank+regspic14[i].offset);
2301       pic14_emitcode("movx","@%s,a",r->name);           
2302     } else 
2303       pic14_emitcode("push","");// "(%s+%d)",
2304     //regspic14[i].base,8*bank+regspic14[i].offset);
2305   }
2306   
2307   if (pushPsw) {
2308     if (options.useXstack) {
2309       pic14_emitcode("mov","a,psw");
2310       pic14_emitcode("movx","@%s,a",r->name); 
2311       pic14_emitcode("inc","%s",r->name);
2312       pic14_emitcode("mov","_spx,%s",r->name);       
2313       freeAsmop (NULL,aop,ic,TRUE);
2314       
2315     } else
2316       pic14_emitcode("push","psw");
2317     
2318     pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2319   }
2320   ic->bankSaved = 1;
2321 #endif
2322 }
2323
2324 /*-----------------------------------------------------------------*/
2325 /* genCall - generates a call statement                            */
2326 /*-----------------------------------------------------------------*/
2327 static void genCall (iCode *ic)
2328 {
2329   sym_link *dtype;   
2330   symbol *sym;
2331   unsigned char *name;
2332   int isExtern;
2333   
2334   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2335   
2336   /* if caller saves & we have not saved then */
2337   if (!ic->regsSaved)
2338     saveRegisters(ic);
2339   
2340     /* if we are calling a function that is not using
2341     the same register bank then we need to save the
2342   destination registers on the stack */
2343   dtype = operandType(IC_LEFT(ic));
2344   if (currFunc && dtype && 
2345     (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2346     IFFUNC_ISISR(currFunc->type) &&
2347     !ic->bankSaved) 
2348     
2349     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2350   
2351   /* if send set is not empty the assign */
2352   if (_G.sendSet) {
2353     iCode *sic;
2354     /* For the Pic port, there is no data stack.
2355     * So parameters passed to functions are stored
2356     * in registers. (The pCode optimizer will get
2357     * rid of most of these :).
2358     */
2359     int psuedoStkPtr=-1;
2360     int firstTimeThruLoop = 1;
2361     
2362     _G.sendSet = reverseSet(_G.sendSet);
2363     
2364     /* First figure how many parameters are getting passed */
2365     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2366     sic = setNextItem(_G.sendSet)) {
2367       
2368       aopOp(IC_LEFT(sic),sic,FALSE);
2369       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2370       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2371     }
2372     
2373     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2374     sic = setNextItem(_G.sendSet)) {
2375       int size, offset = 0;
2376       
2377       aopOp(IC_LEFT(sic),sic,FALSE);
2378       size = AOP_SIZE(IC_LEFT(sic));
2379       
2380       while (size--) {
2381         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2382           AopType(AOP_TYPE(IC_LEFT(sic))));
2383         
2384         if(!firstTimeThruLoop) {
2385         /* If this is not the first time we've been through the loop
2386         * then we need to save the parameter in a temporary
2387         * register. The last byte of the last parameter is
2388           * passed in W. */
2389           emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2390           
2391         }
2392         firstTimeThruLoop=0;
2393         
2394         mov2w (AOP(IC_LEFT(sic)),  offset);
2395         offset++;
2396       }
2397       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2398     }
2399     _G.sendSet = NULL;
2400   }
2401   /* make the call */
2402   sym = OP_SYMBOL(IC_LEFT(ic));
2403   name = sym->rname[0] ? sym->rname : sym->name;
2404   isExtern = IS_EXTERN(sym->etype);
2405   if (isExtern) {
2406     emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2407   }
2408   emitpcode(POC_CALL,popGetWithString(name,isExtern));
2409   if (isExtern) {
2410     emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel */
2411   }
2412   GpsuedoStkPtr=0;
2413   /* if we need assign a result value */
2414   if ((IS_ITEMP(IC_RESULT(ic)) && 
2415     (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2416     OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2417     IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2418     
2419     _G.accInUse++;
2420     aopOp(IC_RESULT(ic),ic,FALSE);
2421     _G.accInUse--;
2422     
2423     assignResultValue(IC_RESULT(ic));
2424     
2425     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2426       AopType(AOP_TYPE(IC_RESULT(ic))));
2427     
2428     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2429   }
2430   
2431   /* adjust the stack for parameters if 
2432   required */
2433   if (ic->parmBytes) {
2434     int i;
2435     if (ic->parmBytes > 3) {
2436       pic14_emitcode("mov","a,%s",spname);
2437       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2438       pic14_emitcode("mov","%s,a",spname);
2439     } else 
2440       for ( i = 0 ; i <  ic->parmBytes ;i++)
2441         pic14_emitcode("dec","%s",spname);
2442       
2443   }
2444   
2445   /* if register bank was saved then pop them */
2446   if (ic->bankSaved)
2447     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2448   
2449   /* if we hade saved some registers then unsave them */
2450   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2451     unsaveRegisters (ic);
2452   
2453   
2454 }
2455
2456 /*-----------------------------------------------------------------*/
2457 /* genPcall - generates a call by pointer statement                */
2458 /*-----------------------------------------------------------------*/
2459 static void genPcall (iCode *ic)
2460 {
2461   sym_link *dtype;
2462   symbol *albl = newiTempLabel(NULL);
2463   symbol *blbl = newiTempLabel(NULL);
2464   PIC_OPCODE poc;
2465   pCodeOp *pcop;
2466   operand *left;
2467   
2468   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2469   /* if caller saves & we have not saved then */
2470   if (!ic->regsSaved)
2471     saveRegisters(ic);
2472   
2473     /* if we are calling a function that is not using
2474     the same register bank then we need to save the
2475   destination registers on the stack */
2476   dtype = operandType(IC_LEFT(ic));
2477   if (currFunc && dtype && 
2478     IFFUNC_ISISR(currFunc->type) &&
2479     (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2480     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2481   
2482   left = IC_LEFT(ic);
2483   aopOp(left,ic,FALSE);
2484   DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2485   
2486   pushSide(IC_LEFT(ic), FPTRSIZE);
2487   
2488   /* if send set is not empty, assign parameters */
2489   if (_G.sendSet) {
2490     
2491     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2492     /* no way to pass args - W always gets used to make the call */
2493   }
2494   /* first idea - factor out a common helper function and call it.
2495   But don't know how to get it generated only once in its own block
2496   
2497     if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2498     char *rname;
2499     char *buffer;
2500     rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2501     DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2502     buffer = Safe_calloc(1,strlen(rname)+16);
2503     sprintf(buffer, "%s_goto_helper", rname);
2504     addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2505     free(buffer);
2506     }
2507   */
2508   emitpcode(POC_CALL,popGetLabel(albl->key));
2509   pcop = popGetLabel(blbl->key);
2510   emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2511   emitpcode(POC_GOTO,pcop);
2512   emitpLabel(albl->key);
2513   
2514   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
2515   
2516   emitpcode(poc,popGet(AOP(left),1));
2517   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2518   emitpcode(poc,popGet(AOP(left),0));
2519   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2520   
2521   emitpLabel(blbl->key);
2522   
2523   freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2524   
2525   /* if we need to assign a result value */
2526   if ((IS_ITEMP(IC_RESULT(ic)) &&
2527     (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2528     OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2529     IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2530     
2531     _G.accInUse++;
2532     aopOp(IC_RESULT(ic),ic,FALSE);
2533     _G.accInUse--;
2534     
2535     assignResultValue(IC_RESULT(ic));
2536     
2537     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2538   }
2539   
2540   /* if register bank was saved then unsave them */
2541   if (currFunc && dtype && 
2542     (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2543     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2544   
2545     /* if we hade saved some registers then
2546   unsave them */
2547   if (ic->regsSaved)
2548     unsaveRegisters (ic);
2549   
2550 }
2551
2552 /*-----------------------------------------------------------------*/
2553 /* resultRemat - result  is rematerializable                       */
2554 /*-----------------------------------------------------------------*/
2555 static int resultRemat (iCode *ic)
2556 {
2557   //    DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2558   if (SKIP_IC(ic) || ic->op == IFX)
2559     return 0;
2560   
2561   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2562     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2563     if (sym->remat && !POINTER_SET(ic)) 
2564       return 1;
2565   }
2566   
2567   return 0;
2568 }
2569
2570 #if defined(__BORLANDC__) || defined(_MSC_VER)
2571 #define STRCASECMP stricmp
2572 #else
2573 #define STRCASECMP strcasecmp
2574 #endif
2575
2576 #if 0
2577 /*-----------------------------------------------------------------*/
2578 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2579 /*-----------------------------------------------------------------*/
2580 static bool inExcludeList(char *s)
2581 {
2582   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2583   int i =0;
2584   
2585   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2586   if (options.excludeRegs[i] &&
2587     STRCASECMP(options.excludeRegs[i],"none") == 0)
2588     return FALSE ;
2589   
2590   for ( i = 0 ; options.excludeRegs[i]; i++) {
2591     if (options.excludeRegs[i] &&
2592       STRCASECMP(s,options.excludeRegs[i]) == 0)
2593       return TRUE;
2594   }
2595   return FALSE ;
2596 }
2597 #endif
2598
2599 /*-----------------------------------------------------------------*/
2600 /* genFunction - generated code for function entry                 */
2601 /*-----------------------------------------------------------------*/
2602 static void genFunction (iCode *ic)
2603 {
2604   symbol *sym;
2605   sym_link *ftype;
2606   
2607   DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2608   
2609   labelOffset += (max_key+4);
2610   max_key=0;
2611   GpsuedoStkPtr=0;
2612   _G.nRegsSaved = 0;
2613   /* create the function header */
2614   pic14_emitcode(";","-----------------------------------------");
2615   pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2616   pic14_emitcode(";","-----------------------------------------");
2617   
2618   pic14_emitcode("","%s:",sym->rname);
2619   addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2620   
2621   ftype = operandType(IC_LEFT(ic));
2622   
2623   /* if critical function then turn interrupts off */
2624   if (IFFUNC_ISCRITICAL(ftype))
2625     pic14_emitcode("clr","ea");
2626   
2627     /* here we need to generate the equates for the
2628   register bank if required */
2629 #if 0
2630   if (FUNC_REGBANK(ftype) != rbank) {
2631     int i ;
2632     
2633     rbank = FUNC_REGBANK(ftype);
2634     for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2635       if (strcmp(regspic14[i].base,"0") == 0)
2636         pic14_emitcode("","%s = 0x%02x",
2637         regspic14[i].dname,
2638         8*rbank+regspic14[i].offset);
2639       else
2640         pic14_emitcode ("","%s = %s + 0x%02x",
2641         regspic14[i].dname,
2642         regspic14[i].base,
2643         8*rbank+regspic14[i].offset);
2644     }
2645   }
2646 #endif
2647   
2648   /* if this is an interrupt service routine */
2649   if (IFFUNC_ISISR(sym->type)) {
2650   /*  already done in pic14createInterruptVect() - delete me
2651   addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2652   emitpcodeNULLop(POC_NOP);
2653   emitpcodeNULLop(POC_NOP);
2654   emitpcodeNULLop(POC_NOP);
2655     */
2656     emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2657     emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2658     emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2659     emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2660     emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2661     emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2662     emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2663     
2664     pBlockConvert2ISR(pb);
2665 #if 0  
2666     if (!inExcludeList("acc"))      
2667       pic14_emitcode ("push","acc");  
2668     if (!inExcludeList("b"))
2669       pic14_emitcode ("push","b");
2670     if (!inExcludeList("dpl"))
2671       pic14_emitcode ("push","dpl");
2672     if (!inExcludeList("dph"))
2673       pic14_emitcode ("push","dph");
2674     if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2675     {
2676       pic14_emitcode ("push", "dpx");
2677       /* Make sure we're using standard DPTR */
2678       pic14_emitcode ("push", "dps");
2679       pic14_emitcode ("mov", "dps, #0x00");
2680       if (options.stack10bit)
2681       { 
2682         /* This ISR could conceivably use DPTR2. Better save it. */
2683         pic14_emitcode ("push", "dpl1");
2684         pic14_emitcode ("push", "dph1");
2685         pic14_emitcode ("push", "dpx1");
2686       }
2687     }
2688     /* if this isr has no bank i.e. is going to
2689     run with bank 0 , then we need to save more
2690 registers :-) */
2691     if (!FUNC_REGBANK(sym->type)) {
2692       
2693     /* if this function does not call any other
2694     function then we can be economical and
2695       save only those registers that are used */
2696       if (! IFFUNC_HASFCALL(sym->type)) {
2697         int i;
2698         
2699         /* if any registers used */
2700         if (sym->regsUsed) {
2701           /* save the registers used */
2702           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2703             if (bitVectBitValue(sym->regsUsed,i) ||
2704               (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2705               pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);         
2706           }
2707         }
2708         
2709       } else {
2710       /* this function has  a function call cannot
2711       determines register usage so we will have the
2712         entire bank */
2713         saverbank(0,ic,FALSE);
2714       }     
2715     }
2716 #endif
2717   } else {
2718   /* if callee-save to be used for this function
2719     then save the registers being used in this function */
2720     if (IFFUNC_CALLEESAVES(sym->type)) {
2721       int i;
2722       
2723       /* if any registers used */
2724       if (sym->regsUsed) {
2725         /* save the registers used */
2726         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2727           if (bitVectBitValue(sym->regsUsed,i) ||
2728             (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2729             //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2730             _G.nRegsSaved++;
2731           }
2732         }
2733       }
2734     }
2735   }
2736   
2737   /* set the register bank to the desired value */
2738   if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2739     pic14_emitcode("push","psw");
2740     pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2741   }
2742   
2743   if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2744     
2745     if (options.useXstack) {
2746       pic14_emitcode("mov","r0,%s",spname);
2747       pic14_emitcode("mov","a,_bp");
2748       pic14_emitcode("movx","@r0,a");
2749       pic14_emitcode("inc","%s",spname);
2750     }
2751     else
2752     {
2753       /* set up the stack */
2754       pic14_emitcode ("push","_bp");     /* save the callers stack  */
2755     }
2756     pic14_emitcode ("mov","_bp,%s",spname);
2757   }
2758   
2759   /* adjust the stack for the function */
2760   if (sym->stack) {
2761     
2762     int i = sym->stack;
2763     if (i > 256 ) 
2764       werror(W_STACK_OVERFLOW,sym->name);
2765     
2766     if (i > 3 && sym->recvSize < 4) {        
2767       
2768       pic14_emitcode ("mov","a,sp");
2769       pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2770       pic14_emitcode ("mov","sp,a");
2771       
2772     }
2773     else
2774       while(i--)
2775         pic14_emitcode("inc","sp");
2776   }
2777   
2778   if (sym->xstack) {
2779     
2780     pic14_emitcode ("mov","a,_spx");
2781     pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2782     pic14_emitcode ("mov","_spx,a");
2783   }    
2784   
2785 }
2786
2787 /*-----------------------------------------------------------------*/
2788 /* genEndFunction - generates epilogue for functions               */
2789 /*-----------------------------------------------------------------*/
2790 static void genEndFunction (iCode *ic)
2791 {
2792   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2793   
2794   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2795   
2796   if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2797   {
2798     pic14_emitcode ("mov","%s,_bp",spname);
2799   }
2800   
2801   /* if use external stack but some variables were
2802   added to the local stack then decrement the
2803   local stack */
2804   if (options.useXstack && sym->stack) {      
2805     pic14_emitcode("mov","a,sp");
2806     pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2807     pic14_emitcode("mov","sp,a");
2808   }
2809   
2810   
2811   if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2812     if (options.useXstack) {
2813       pic14_emitcode("mov","r0,%s",spname);
2814       pic14_emitcode("movx","a,@r0");
2815       pic14_emitcode("mov","_bp,a");
2816       pic14_emitcode("dec","%s",spname);
2817     }
2818     else
2819     {
2820       pic14_emitcode ("pop","_bp");
2821     }
2822   }
2823   
2824   /* restore the register bank  */    
2825   if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2826     pic14_emitcode ("pop","psw");
2827   
2828   if (IFFUNC_ISISR(sym->type)) {
2829     
2830     /* now we need to restore the registers */
2831     /* if this isr has no bank i.e. is going to
2832     run with bank 0 , then we need to save more
2833 registers :-) */
2834     if (!FUNC_REGBANK(sym->type)) {
2835       
2836     /* if this function does not call any other
2837     function then we can be economical and
2838       save only those registers that are used */
2839       if (! IFFUNC_HASFCALL(sym->type)) {
2840         int i;
2841         
2842         /* if any registers used */
2843         if (sym->regsUsed) {
2844           /* save the registers used */
2845           for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2846             if (bitVectBitValue(sym->regsUsed,i) ||
2847               (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2848               pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2849           }
2850         }
2851         
2852       } else {
2853       /* this function has  a function call cannot
2854       determines register usage so we will have the
2855         entire bank */
2856         unsaverbank(0,ic,FALSE);
2857       }     
2858     }
2859 #if 0
2860     if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2861     {
2862       if (options.stack10bit)
2863       {
2864         pic14_emitcode ("pop", "dpx1");
2865         pic14_emitcode ("pop", "dph1");
2866         pic14_emitcode ("pop", "dpl1");
2867       } 
2868       pic14_emitcode ("pop", "dps");
2869       pic14_emitcode ("pop", "dpx");
2870     }
2871     if (!inExcludeList("dph"))
2872       pic14_emitcode ("pop","dph");
2873     if (!inExcludeList("dpl"))
2874       pic14_emitcode ("pop","dpl");
2875     if (!inExcludeList("b"))
2876       pic14_emitcode ("pop","b");
2877     if (!inExcludeList("acc"))
2878       pic14_emitcode ("pop","acc");
2879     
2880     if (IFFUNC_ISCRITICAL(sym->type))
2881       pic14_emitcode("setb","ea");
2882 #endif
2883     
2884     /* if debug then send end of function */
2885     /*  if (options.debug && currFunc) { */
2886     if (currFunc) {
2887       debugFile->writeEndFunction (currFunc, ic, 1);
2888     }
2889     
2890     pic14_emitcode ("reti","");
2891     emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
2892     emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
2893     emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2894     emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2895     emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2896     emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2897     emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2898     addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2899     emitpcodeNULLop(POC_RETFIE);
2900   }
2901   else {
2902     if (IFFUNC_ISCRITICAL(sym->type))
2903       pic14_emitcode("setb","ea");
2904     
2905     if (IFFUNC_CALLEESAVES(sym->type)) {
2906       int i;
2907       
2908       /* if any registers used */
2909       if (sym->regsUsed) {
2910         /* save the registers used */
2911         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2912           if (bitVectBitValue(sym->regsUsed,i) ||
2913             (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2914             pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2915         }
2916       }
2917       
2918     }
2919     
2920     /* if debug then send end of function */
2921     if (currFunc) {
2922       debugFile->writeEndFunction (currFunc, ic, 1);
2923     }
2924     
2925     pic14_emitcode ("return","");
2926     emitpcodeNULLop(POC_RETURN);
2927     
2928     /* Mark the end of a function */
2929     addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2930   }
2931   
2932 }
2933
2934 /*-----------------------------------------------------------------*/
2935 /* genRet - generate code for return statement                     */
2936 /*-----------------------------------------------------------------*/
2937 static void genRet (iCode *ic)
2938 {
2939   int size,offset = 0 , pushed = 0;
2940   
2941   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2942   /* if we have no return value then
2943   just generate the "ret" */
2944   if (!IC_LEFT(ic)) 
2945     goto jumpret;       
2946   
2947     /* we have something to return then
2948   move the return value into place */
2949   aopOp(IC_LEFT(ic),ic,FALSE);
2950   size = AOP_SIZE(IC_LEFT(ic));
2951   
2952   while (size--) {
2953     char *l ;
2954     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2955       /* #NOCHANGE */
2956       l = aopGet(AOP(IC_LEFT(ic)),offset++,
2957         FALSE,TRUE);
2958       pic14_emitcode("push","%s",l);
2959       pushed++;
2960     } else {
2961       l = aopGet(AOP(IC_LEFT(ic)),offset,
2962         FALSE,FALSE);
2963       if (strcmp(fReturn[offset],l)) {
2964         if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
2965           AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
2966           ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2967           ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
2968           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
2969         }else {
2970           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
2971         }
2972         if(size) {
2973           emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
2974         }
2975         offset++;
2976       }
2977     }
2978   }    
2979   
2980   if (pushed) {
2981     while(pushed) {
2982       pushed--;
2983       if (strcmp(fReturn[pushed],"a"))
2984         pic14_emitcode("pop",fReturn[pushed]);
2985       else
2986         pic14_emitcode("pop","acc");
2987     }
2988   }
2989   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2990   
2991 jumpret:
2992 /* generate a jump to the return label
2993   if the next is not the return statement */
2994   if (!(ic->next && ic->next->op == LABEL &&
2995     IC_LABEL(ic->next) == returnLabel)) {
2996     
2997     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2998     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2999   }
3000   
3001 }
3002
3003 /*-----------------------------------------------------------------*/
3004 /* genLabel - generates a label                                    */
3005 /*-----------------------------------------------------------------*/
3006 static void genLabel (iCode *ic)
3007 {
3008   /* special case never generate */
3009   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3010   if (IC_LABEL(ic) == entryLabel)
3011     return ;
3012   
3013   emitpLabel(IC_LABEL(ic)->key);
3014   pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3015 }
3016
3017 /*-----------------------------------------------------------------*/
3018 /* genGoto - generates a goto                                      */
3019 /*-----------------------------------------------------------------*/
3020 //tsd
3021 static void genGoto (iCode *ic)
3022 {
3023   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3024   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3025 }
3026
3027
3028 /*-----------------------------------------------------------------*/
3029 /* genMultbits :- multiplication of bits                           */
3030 /*-----------------------------------------------------------------*/
3031 static void genMultbits (operand *left, 
3032              operand *right, 
3033              operand *result)
3034 {
3035   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3036   
3037   if(!pic14_sameRegs(AOP(result),AOP(right)))
3038     emitpcode(POC_BSF,  popGet(AOP(result),0));
3039   
3040   emitpcode(POC_BTFSC,popGet(AOP(right),0));
3041   emitpcode(POC_BTFSS,popGet(AOP(left),0));
3042   emitpcode(POC_BCF,  popGet(AOP(result),0));
3043   
3044 }
3045
3046
3047 /*-----------------------------------------------------------------*/
3048 /* genMultOneByte : 8 bit multiplication & division                */
3049 /*-----------------------------------------------------------------*/
3050 static void genMultOneByte (operand *left,
3051               operand *right,
3052               operand *result)
3053 {
3054   sym_link *opetype = operandType(result);
3055   
3056   // symbol *lbl ;
3057   int size,offset;
3058   
3059   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3060   DEBUGpic14_AopType(__LINE__,left,right,result);
3061   DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3062   
3063   /* (if two literals, the value is computed before) */
3064   /* if one literal, literal on the right */
3065   if (AOP_TYPE(left) == AOP_LIT){
3066     operand *t = right;
3067     right = left;
3068     left = t;
3069   }
3070   
3071   size = AOP_SIZE(result);
3072   if(size == 1) {
3073     
3074     if (AOP_TYPE(right) == AOP_LIT){
3075       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3076         aopGet(AOP(right),0,FALSE,FALSE), 
3077         aopGet(AOP(left),0,FALSE,FALSE), 
3078         aopGet(AOP(result),0,FALSE,FALSE));
3079       pic14_emitcode("call","genMultLit");
3080     } else {
3081       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3082         aopGet(AOP(right),0,FALSE,FALSE), 
3083         aopGet(AOP(left),0,FALSE,FALSE), 
3084         aopGet(AOP(result),0,FALSE,FALSE));
3085       pic14_emitcode("call","genMult8X8_8");
3086       
3087     }
3088     genMult8X8_8 (left, right,result);
3089     
3090     
3091     /* signed or unsigned */
3092     //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3093     //l = aopGet(AOP(left),0,FALSE,FALSE);
3094     //MOVA(l);       
3095     //pic14_emitcode("mul","ab");
3096     /* if result size = 1, mul signed = mul unsigned */
3097     //aopPut(AOP(result),"a",0);
3098     
3099   } else {  // (size > 1)
3100     
3101     pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3102       aopGet(AOP(right),0,FALSE,FALSE), 
3103       aopGet(AOP(left),0,FALSE,FALSE), 
3104       aopGet(AOP(result),0,FALSE,FALSE));
3105     
3106     if (SPEC_USIGN(opetype)){
3107       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3108       genUMult8X8_16 (left, right, result, NULL);
3109       
3110       if (size > 2) {
3111         /* for filling the MSBs */
3112         emitpcode(POC_CLRF,  popGet(AOP(result),2));
3113         emitpcode(POC_CLRF,  popGet(AOP(result),3));
3114       }
3115     }
3116     else{
3117       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3118       
3119       pic14_emitcode("mov","a,b");
3120       
3121       /* adjust the MSB if left or right neg */
3122       
3123       /* if one literal */
3124       if (AOP_TYPE(right) == AOP_LIT){
3125         pic14_emitcode("multiply ","right is a lit");
3126         /* AND literal negative */
3127         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3128           /* adjust MSB (c==0 after mul) */
3129           pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3130         }
3131       }
3132       else{
3133         genSMult8X8_16 (left, right, result, NULL);
3134       }
3135       
3136       if(size > 2){
3137         pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3138         /* get the sign */
3139         pic14_emitcode("rlc","a");
3140         pic14_emitcode("subb","a,acc");
3141       }
3142     }
3143     
3144     size -= 2;   
3145     offset = 2;
3146     if (size > 0)
3147       while (size--)
3148         pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3149       //aopPut(AOP(result),"a",offset++);
3150   }
3151 }
3152
3153 /*-----------------------------------------------------------------*/
3154 /* genMult - generates code for multiplication                     */
3155 /*-----------------------------------------------------------------*/
3156 static void genMult (iCode *ic)
3157 {
3158   operand *left = IC_LEFT(ic);
3159   operand *right = IC_RIGHT(ic);
3160   operand *result= IC_RESULT(ic);   
3161   
3162   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3163   /* assign the amsops */
3164   aopOp (left,ic,FALSE);
3165   aopOp (right,ic,FALSE);
3166   aopOp (result,ic,TRUE);
3167   
3168   DEBUGpic14_AopType(__LINE__,left,right,result);
3169   
3170   /* special cases first */
3171   /* both are bits */
3172   if (AOP_TYPE(left) == AOP_CRY &&
3173     AOP_TYPE(right)== AOP_CRY) {
3174     genMultbits(left,right,result);
3175     goto release ;
3176   }
3177   
3178   /* if both are of size == 1 */
3179   if (AOP_SIZE(left) == 1 &&
3180     AOP_SIZE(right) == 1 ) {
3181     genMultOneByte(left,right,result);
3182     goto release ;
3183   }
3184   
3185   pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3186   
3187   /* should have been converted to function call */
3188   //assert(0) ;
3189   
3190 release :
3191   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3192   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3193   freeAsmop(result,NULL,ic,TRUE); 
3194 }
3195
3196 /*-----------------------------------------------------------------*/
3197 /* genDivbits :- division of bits                                  */
3198 /*-----------------------------------------------------------------*/
3199 static void genDivbits (operand *left, 
3200             operand *right, 
3201             operand *result)
3202 {
3203   
3204   char *l;
3205   
3206   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3207   /* the result must be bit */    
3208   pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3209   l = aopGet(AOP(left),0,FALSE,FALSE);
3210   
3211   MOVA(l);    
3212   
3213   pic14_emitcode("div","ab");
3214   pic14_emitcode("rrc","a");
3215   aopPut(AOP(result),"c",0);
3216 }
3217
3218 /*-----------------------------------------------------------------*/
3219 /* genDivOneByte : 8 bit division                                  */
3220 /*-----------------------------------------------------------------*/
3221 static void genDivOneByte (operand *left,
3222                operand *right,
3223                operand *result)
3224 {
3225   sym_link *opetype = operandType(result);
3226   char *l ;
3227   symbol *lbl ;
3228   int size,offset;
3229   
3230   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3231   size = AOP_SIZE(result) - 1;
3232   offset = 1;
3233   /* signed or unsigned */
3234   if (SPEC_USIGN(opetype)) {
3235     /* unsigned is easy */
3236     pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3237     l = aopGet(AOP(left),0,FALSE,FALSE);
3238     MOVA(l);        
3239     pic14_emitcode("div","ab");
3240     aopPut(AOP(result),"a",0);
3241     while (size--)
3242       aopPut(AOP(result),zero,offset++);
3243     return ;
3244   }
3245   
3246   /* signed is a little bit more difficult */
3247   
3248   /* save the signs of the operands */
3249   l = aopGet(AOP(left),0,FALSE,FALSE);    
3250   MOVA(l);    
3251   pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3252   pic14_emitcode("push","acc"); /* save it on the stack */
3253   
3254   /* now sign adjust for both left & right */
3255   l =  aopGet(AOP(right),0,FALSE,FALSE);    
3256   MOVA(l);       
3257   lbl = newiTempLabel(NULL);
3258   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3259   pic14_emitcode("cpl","a");   
3260   pic14_emitcode("inc","a");
3261   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3262   pic14_emitcode("mov","b,a");
3263   
3264   /* sign adjust left side */
3265   l =  aopGet(AOP(left),0,FALSE,FALSE);    
3266   MOVA(l);
3267   
3268   lbl = newiTempLabel(NULL);
3269   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3270   pic14_emitcode("cpl","a");
3271   pic14_emitcode("inc","a");
3272   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3273   
3274   /* now the division */
3275   pic14_emitcode("div","ab");
3276   /* we are interested in the lower order
3277   only */
3278   pic14_emitcode("mov","b,a");
3279   lbl = newiTempLabel(NULL);
3280   pic14_emitcode("pop","acc");   
3281   /* if there was an over flow we don't 
3282   adjust the sign of the result */
3283   pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3284   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3285   CLRC;
3286   pic14_emitcode("clr","a");
3287   pic14_emitcode("subb","a,b");
3288   pic14_emitcode("mov","b,a");
3289   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3290   
3291   /* now we are done */
3292   aopPut(AOP(result),"b",0);
3293   if(size > 0){
3294     pic14_emitcode("mov","c,b.7");
3295     pic14_emitcode("subb","a,acc");   
3296   }
3297   while (size--)
3298     aopPut(AOP(result),"a",offset++);
3299   
3300 }
3301
3302 /*-----------------------------------------------------------------*/
3303 /* genDiv - generates code for division                            */
3304 /*-----------------------------------------------------------------*/
3305 static void genDiv (iCode *ic)
3306 {
3307   operand *left = IC_LEFT(ic);
3308   operand *right = IC_RIGHT(ic);
3309   operand *result= IC_RESULT(ic);   
3310   
3311   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3312   /* assign the amsops */
3313   aopOp (left,ic,FALSE);
3314   aopOp (right,ic,FALSE);
3315   aopOp (result,ic,TRUE);
3316   
3317   /* special cases first */
3318   /* both are bits */
3319   if (AOP_TYPE(left) == AOP_CRY &&
3320     AOP_TYPE(right)== AOP_CRY) {
3321     genDivbits(left,right,result);
3322     goto release ;
3323   }
3324   
3325   /* if both are of size == 1 */
3326   if (AOP_SIZE(left) == 1 &&
3327     AOP_SIZE(right) == 1 ) {
3328     genDivOneByte(left,right,result);
3329     goto release ;
3330   }
3331   
3332   /* should have been converted to function call */
3333   assert(0);
3334 release :
3335   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3336   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3337   freeAsmop(result,NULL,ic,TRUE); 
3338 }
3339
3340 /*-----------------------------------------------------------------*/
3341 /* genModbits :- modulus of bits                                   */
3342 /*-----------------------------------------------------------------*/
3343 static void genModbits (operand *left, 
3344             operand *right, 
3345             operand *result)
3346 {
3347   
3348   char *l;
3349   
3350   /* the result must be bit */    
3351   pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3352   l = aopGet(AOP(left),0,FALSE,FALSE);
3353   
3354   MOVA(l);       
3355   
3356   pic14_emitcode("div","ab");
3357   pic14_emitcode("mov","a,b");
3358   pic14_emitcode("rrc","a");
3359   aopPut(AOP(result),"c",0);
3360 }
3361
3362 /*-----------------------------------------------------------------*/
3363 /* genModOneByte : 8 bit modulus                                   */
3364 /*-----------------------------------------------------------------*/
3365 static void genModOneByte (operand *left,
3366                operand *right,
3367                operand *result)
3368 {
3369   sym_link *opetype = operandType(result);
3370   char *l ;
3371   symbol *lbl ;
3372   
3373   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3374   /* signed or unsigned */
3375   if (SPEC_USIGN(opetype)) {
3376     /* unsigned is easy */
3377     pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3378     l = aopGet(AOP(left),0,FALSE,FALSE);
3379     MOVA(l);    
3380     pic14_emitcode("div","ab");
3381     aopPut(AOP(result),"b",0);
3382     return ;
3383   }
3384   
3385   /* signed is a little bit more difficult */
3386   
3387   /* save the signs of the operands */
3388   l = aopGet(AOP(left),0,FALSE,FALSE);    
3389   MOVA(l);
3390   
3391   pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3392   pic14_emitcode("push","acc"); /* save it on the stack */
3393   
3394   /* now sign adjust for both left & right */
3395   l =  aopGet(AOP(right),0,FALSE,FALSE);    
3396   MOVA(l);
3397   
3398   lbl = newiTempLabel(NULL);
3399   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3400   pic14_emitcode("cpl","a");   
3401   pic14_emitcode("inc","a");
3402   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3403   pic14_emitcode("mov","b,a"); 
3404   
3405   /* sign adjust left side */
3406   l =  aopGet(AOP(left),0,FALSE,FALSE);    
3407   MOVA(l);
3408   
3409   lbl = newiTempLabel(NULL);
3410   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3411   pic14_emitcode("cpl","a");   
3412   pic14_emitcode("inc","a");
3413   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3414   
3415   /* now the multiplication */
3416   pic14_emitcode("div","ab");
3417   /* we are interested in the lower order
3418   only */
3419   lbl = newiTempLabel(NULL);
3420   pic14_emitcode("pop","acc");   
3421   /* if there was an over flow we don't 
3422   adjust the sign of the result */
3423   pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3424   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3425   CLRC ;
3426   pic14_emitcode("clr","a");
3427   pic14_emitcode("subb","a,b");
3428   pic14_emitcode("mov","b,a");
3429   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3430   
3431   /* now we are done */
3432   aopPut(AOP(result),"b",0);
3433   
3434 }
3435
3436 /*-----------------------------------------------------------------*/
3437 /* genMod - generates code for division                            */
3438 /*-----------------------------------------------------------------*/
3439 static void genMod (iCode *ic)
3440 {
3441   operand *left = IC_LEFT(ic);
3442   operand *right = IC_RIGHT(ic);
3443   operand *result= IC_RESULT(ic);  
3444   
3445   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3446   /* assign the amsops */
3447   aopOp (left,ic,FALSE);
3448   aopOp (right,ic,FALSE);
3449   aopOp (result,ic,TRUE);
3450   
3451   /* special cases first */
3452   /* both are bits */
3453   if (AOP_TYPE(left) == AOP_CRY &&
3454     AOP_TYPE(right)== AOP_CRY) {
3455     genModbits(left,right,result);
3456     goto release ;
3457   }
3458   
3459   /* if both are of size == 1 */
3460   if (AOP_SIZE(left) == 1 &&
3461     AOP_SIZE(right) == 1 ) {
3462     genModOneByte(left,right,result);
3463     goto release ;
3464   }
3465   
3466   /* should have been converted to function call */
3467   assert(0);
3468   
3469 release :
3470   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3471   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3472   freeAsmop(result,NULL,ic,TRUE); 
3473 }
3474
3475 /*-----------------------------------------------------------------*/
3476 /* genIfxJump :- will create a jump depending on the ifx           */
3477 /*-----------------------------------------------------------------*/
3478 /*
3479 note: May need to add parameter to indicate when a variable is in bit space.
3480 */
3481 static void genIfxJump (iCode *ic, char *jval)
3482 {
3483   
3484   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3485   /* if true label then we jump if condition
3486   supplied is true */
3487   if ( IC_TRUE(ic) ) {
3488     
3489     if(strcmp(jval,"a") == 0)
3490       emitSKPZ;
3491     else if (strcmp(jval,"c") == 0)
3492       emitSKPC;
3493     else {
3494       DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);   
3495       emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3496     }
3497     
3498     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3499     pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3500     
3501   }
3502   else {
3503     /* false label is present */
3504     if(strcmp(jval,"a") == 0)
3505       emitSKPNZ;
3506     else if (strcmp(jval,"c") == 0)
3507       emitSKPNC;
3508     else {
3509       DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);   
3510       emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3511     }
3512     
3513     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3514     pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3515     
3516   }
3517   
3518   
3519   /* mark the icode as generated */
3520   ic->generated = 1;
3521 }
3522
3523 /*-----------------------------------------------------------------*/
3524 /* genSkip                                                         */
3525 /*-----------------------------------------------------------------*/
3526 static void genSkip(iCode *ifx,int status_bit)
3527 {
3528   if(!ifx)
3529     return;
3530   
3531   if ( IC_TRUE(ifx) ) {
3532     switch(status_bit) {
3533     case 'z':
3534       emitSKPNZ;
3535       break;
3536       
3537     case 'c':
3538       emitSKPNC;
3539       break;
3540       
3541     case 'd':
3542       emitSKPDC;
3543       break;
3544       
3545     }
3546     
3547     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3548     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3549     
3550   } else {
3551     
3552     switch(status_bit) {
3553       
3554     case 'z':
3555       emitSKPZ;
3556       break;
3557       
3558     case 'c':
3559       emitSKPC;
3560       break;
3561       
3562     case 'd':
3563       emitSKPDC;
3564       break;
3565     }
3566     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3567     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3568     
3569   }
3570   
3571 }
3572
3573 /*-----------------------------------------------------------------*/
3574 /* genSkipc                                                        */
3575 /*-----------------------------------------------------------------*/
3576 static void genSkipc(resolvedIfx *rifx)
3577 {
3578   if(!rifx)
3579     return;
3580   
3581   if(rifx->condition)
3582     emitSKPC;
3583   else
3584     emitSKPNC;
3585   
3586   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3587   rifx->generated = 1;
3588 }
3589
3590 /*-----------------------------------------------------------------*/
3591 /* genSkipz2                                                       */
3592 /*-----------------------------------------------------------------*/
3593 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3594 {
3595   if(!rifx)
3596     return;
3597   
3598   if( (rifx->condition ^ invert_condition) & 1)
3599     emitSKPZ;
3600   else
3601     emitSKPNZ;
3602   
3603   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3604   rifx->generated = 1;
3605 }
3606
3607 /*-----------------------------------------------------------------*/
3608 /* genSkipz                                                        */
3609 /*-----------------------------------------------------------------*/
3610 static void genSkipz(iCode *ifx, int condition)
3611 {
3612   if(!ifx)
3613     return;
3614   
3615   if(condition)
3616     emitSKPNZ;
3617   else
3618     emitSKPZ;
3619   
3620   if ( IC_TRUE(ifx) )
3621     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3622   else
3623     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3624   
3625   if ( IC_TRUE(ifx) )
3626     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3627   else
3628     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3629   
3630 }
3631 /*-----------------------------------------------------------------*/
3632 /* genSkipCond                                                     */
3633 /*-----------------------------------------------------------------*/
3634 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3635 {
3636   if(!rifx)
3637     return;
3638   
3639   if(rifx->condition)
3640     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3641   else
3642     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3643   
3644   
3645   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3646   rifx->generated = 1;
3647 }
3648
3649 #if 0
3650 /*-----------------------------------------------------------------*/
3651 /* genChkZeroes :- greater or less than comparison                 */
3652 /*     For each byte in a literal that is zero, inclusive or the   */
3653 /*     the corresponding byte in the operand with W                */
3654 /*     returns true if any of the bytes are zero                   */
3655 /*-----------------------------------------------------------------*/
3656 static int genChkZeroes(operand *op, int lit,  int size)
3657 {
3658   
3659   int i;
3660   int flag =1;
3661   
3662   while(size--) {
3663     i = (lit >> (size*8)) & 0xff;
3664     
3665     if(i==0) {
3666       if(flag) 
3667         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3668       else
3669         emitpcode(POC_IORFW, popGet(AOP(op),size));
3670       flag = 0;
3671     }
3672   }
3673   
3674   return (flag==0);
3675 }
3676 #endif
3677
3678 /*-----------------------------------------------------------------*/
3679 /* genCmp :- greater or less than comparison                       */
3680 /*-----------------------------------------------------------------*/
3681 static void genCmp (operand *left,operand *right,
3682           operand *result, iCode *ifx, int sign)
3683 {
3684   int size; //, offset = 0 ;
3685   unsigned long lit = 0L,i = 0;
3686   resolvedIfx rFalseIfx;
3687   //  resolvedIfx rTrueIfx;
3688   symbol *truelbl;
3689   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3690   /*
3691   if(ifx) {
3692   DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3693   DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3694   }
3695   */
3696   
3697   resolveIfx(&rFalseIfx,ifx);
3698   truelbl  = newiTempLabel(NULL);
3699   size = max(AOP_SIZE(left),AOP_SIZE(right));
3700   
3701   DEBUGpic14_AopType(__LINE__,left,right,result);
3702   
3703 #define _swapp
3704   
3705   /* if literal is on the right then swap with left */
3706   if ((AOP_TYPE(right) == AOP_LIT)) {
3707     operand *tmp = right ;
3708     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3709     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3710 #ifdef _swapp
3711     
3712     lit = (lit - 1) & mask;
3713     right = left;
3714     left = tmp;
3715     rFalseIfx.condition ^= 1;
3716 #endif
3717     
3718   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3719     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3720   }
3721   
3722   
3723   //if(IC_TRUE(ifx) == NULL)
3724   /* if left & right are bit variables */
3725   if (AOP_TYPE(left) == AOP_CRY &&
3726     AOP_TYPE(right) == AOP_CRY ) {
3727     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3728     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3729   } else {
3730   /* subtract right from left if at the
3731   end the carry flag is set then we know that
3732     left is greater than right */
3733     
3734     //    {
3735     
3736     symbol *lbl  = newiTempLabel(NULL);
3737     
3738 #ifndef _swapp
3739     if(AOP_TYPE(right) == AOP_LIT) {
3740       
3741       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3742       
3743       DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3744       
3745       /* special cases */
3746       
3747       if(lit == 0) {
3748         
3749         if(sign != 0) 
3750           genSkipCond(&rFalseIfx,left,size-1,7);
3751         else 
3752           /* no need to compare to 0...*/
3753           /* NOTE: this is a de-generate compare that most certainly 
3754           *       creates some dead code. */
3755           emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3756         
3757         if(ifx) ifx->generated = 1;
3758         return;
3759         
3760       }
3761       size--;
3762       
3763       if(size == 0) {
3764         //i = (lit >> (size*8)) & 0xff;
3765         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3766         
3767         emitpcode(POC_MOVFW, popGet(AOP(left),size));
3768         
3769         i = ((0-lit) & 0xff);
3770         if(sign) {
3771           if( i == 0x81) { 
3772           /* lit is 0x7f, all signed chars are less than
3773             * this except for 0x7f itself */
3774             emitpcode(POC_XORLW, popGetLit(0x7f));
3775             genSkipz2(&rFalseIfx,0);
3776           } else {
3777             emitpcode(POC_ADDLW, popGetLit(0x80));
3778             emitpcode(POC_ADDLW, popGetLit(i^0x80));
3779             genSkipc(&rFalseIfx);
3780           }
3781           
3782         } else {
3783           if(lit == 1) {
3784             genSkipz2(&rFalseIfx,1);
3785           } else {
3786             emitpcode(POC_ADDLW, popGetLit(i));
3787             genSkipc(&rFalseIfx);
3788           }
3789         }
3790         
3791         if(ifx) ifx->generated = 1;
3792         return;
3793       }
3794       
3795       /* chars are out of the way. now do ints and longs */
3796       
3797       
3798       DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3799       
3800       /* special cases */
3801       
3802       if(sign) {
3803         
3804         if(lit == 0) {
3805           genSkipCond(&rFalseIfx,left,size,7);
3806           if(ifx) ifx->generated = 1;
3807           return;
3808         }
3809         
3810         if(lit <0x100) {
3811           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3812           
3813           //rFalseIfx.condition ^= 1;
3814           //genSkipCond(&rFalseIfx,left,size,7);
3815           //rFalseIfx.condition ^= 1;
3816           
3817           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3818           if(rFalseIfx.condition)
3819             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3820           else
3821             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3822           
3823           emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3824           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3825           emitpcode(POC_MOVFW, popGet(AOP(left),1));
3826           
3827           while(size > 1)
3828             emitpcode(POC_IORFW, popGet(AOP(left),size--));
3829           
3830           if(rFalseIfx.condition) {
3831             emitSKPZ;
3832             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3833             
3834           } else {
3835             emitSKPNZ;
3836           }
3837           
3838           genSkipc(&rFalseIfx);
3839           emitpLabel(truelbl->key);
3840           if(ifx) ifx->generated = 1;
3841           return;
3842           
3843         }
3844         
3845         if(size == 1) {
3846           
3847           if( (lit & 0xff) == 0) {
3848             /* lower byte is zero */
3849             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3850             i = ((lit >> 8) & 0xff) ^0x80;
3851             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3852             emitpcode(POC_ADDLW, popGetLit( 0x80));
3853             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3854             genSkipc(&rFalseIfx);
3855             
3856             
3857             if(ifx) ifx->generated = 1;
3858             return;
3859             
3860           }
3861         } else {
3862           /* Special cases for signed longs */
3863           if( (lit & 0xffffff) == 0) {
3864             /* lower byte is zero */
3865             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3866             i = ((lit >> 8*3) & 0xff) ^0x80;
3867             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3868             emitpcode(POC_ADDLW, popGetLit( 0x80));
3869             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3870             genSkipc(&rFalseIfx);
3871             
3872             
3873             if(ifx) ifx->generated = 1;
3874             return;
3875             
3876           }
3877           
3878         }
3879         
3880         
3881         if(lit & (0x80 << (size*8))) {
3882           /* lit is negative */
3883           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3884           
3885           //genSkipCond(&rFalseIfx,left,size,7);
3886           
3887           emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3888           
3889           if(rFalseIfx.condition)
3890             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3891           else
3892             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3893           
3894           
3895         } else {
3896           /* lit is positive */
3897           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3898           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3899           if(rFalseIfx.condition)
3900             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3901           else
3902             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3903           
3904         }
3905         
3906         /* There are no more special cases, so perform a general compare */
3907         
3908         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3909         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3910         
3911         while(size--) {
3912           
3913           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3914           emitSKPNZ;
3915           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3916         }
3917         //rFalseIfx.condition ^= 1;
3918         genSkipc(&rFalseIfx);
3919         
3920         emitpLabel(truelbl->key);
3921         
3922         if(ifx) ifx->generated = 1;
3923         return;
3924         
3925         
3926     }
3927     
3928     
3929     /* sign is out of the way. So now do an unsigned compare */
3930     DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3931     
3932     
3933     /* General case - compare to an unsigned literal on the right.*/
3934     
3935     i = (lit >> (size*8)) & 0xff;
3936     emitpcode(POC_MOVLW, popGetLit(i));
3937     emitpcode(POC_SUBFW, popGet(AOP(left),size));
3938     while(size--) {
3939       i = (lit >> (size*8)) & 0xff;
3940       
3941       if(i) {
3942         emitpcode(POC_MOVLW, popGetLit(i));
3943         emitSKPNZ;
3944         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3945       } else {
3946       /* this byte of the lit is zero, 
3947         *if it's not the last then OR in the variable */
3948         if(size)
3949           emitpcode(POC_IORFW, popGet(AOP(left),size));
3950       }
3951     }
3952     
3953     
3954     emitpLabel(lbl->key);
3955     //if(emitFinalCheck)
3956     genSkipc(&rFalseIfx);
3957     if(sign)
3958       emitpLabel(truelbl->key);
3959     
3960     if(ifx) ifx->generated = 1;
3961     return;
3962     
3963     
3964   }
3965 #endif  // _swapp
3966   
3967   if(AOP_TYPE(left) == AOP_LIT) {
3968     //symbol *lbl = newiTempLabel(NULL);
3969     
3970     //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3971     
3972     
3973     DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
3974     
3975     /* Special cases */
3976     if((lit == 0) && (sign == 0)){
3977       
3978       size--;
3979       emitpcode(POC_MOVFW, popGet(AOP(right),size));
3980       while(size) 
3981         emitpcode(POC_IORFW, popGet(AOP(right),--size));
3982       
3983       genSkipz2(&rFalseIfx,0);
3984       if(ifx) ifx->generated = 1;
3985       return;
3986     }
3987     
3988     if(size==1) {
3989       /* Special cases */
3990       lit &= 0xff;
3991       if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3992         /* degenerate compare can never be true */
3993         if(rFalseIfx.condition == 0)
3994           emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3995         
3996         if(ifx) ifx->generated = 1;
3997         return;
3998       }
3999       
4000       if(sign) {
4001         /* signed comparisons to a literal byte */
4002         
4003         int lp1 = (lit+1) & 0xff;
4004         
4005         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4006         switch (lp1) {
4007         case 0:
4008           rFalseIfx.condition ^= 1;
4009           genSkipCond(&rFalseIfx,right,0,7);
4010           break;
4011         case 0x7f:
4012           emitpcode(POC_MOVFW, popGet(AOP(right),0));
4013           emitpcode(POC_XORLW, popGetLit(0x7f));
4014           genSkipz2(&rFalseIfx,1);
4015           break;
4016         default:
4017           emitpcode(POC_MOVFW, popGet(AOP(right),0));
4018           emitpcode(POC_ADDLW, popGetLit(0x80));
4019           emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4020           rFalseIfx.condition ^= 1;
4021           genSkipc(&rFalseIfx);
4022           break;
4023         }
4024         if(ifx) ifx->generated = 1;
4025       } else {
4026         /* unsigned comparisons to a literal byte */
4027         
4028         switch(lit & 0xff ) {
4029         case 0:
4030           emitpcode(POC_MOVFW, popGet(AOP(right),0));
4031           genSkipz2(&rFalseIfx,0);
4032           if(ifx) ifx->generated = 1;
4033           break;
4034         case 0x7f:
4035           genSkipCond(&rFalseIfx,right,0,7);
4036           if(ifx) ifx->generated = 1;
4037           break;
4038           
4039         default:
4040           emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4041           emitpcode(POC_SUBFW, popGet(AOP(right),0));
4042           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4043           rFalseIfx.condition ^= 1;
4044           if (AOP_TYPE(result) == AOP_CRY) {
4045             genSkipc(&rFalseIfx);
4046             if(ifx) ifx->generated = 1;
4047           } else {
4048             DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4049             emitpcode(POC_CLRF, popGet(AOP(result),0));
4050             emitpcode(POC_RLF, popGet(AOP(result),0));
4051             emitpcode(POC_MOVLW, popGetLit(0x01));
4052             emitpcode(POC_XORWF, popGet(AOP(result),0));
4053           }       
4054           break;
4055         }
4056       }
4057       
4058       //goto check_carry;
4059       return;
4060       
4061     } else {
4062       
4063       /* Size is greater than 1 */
4064       
4065       if(sign) {
4066         int lp1 = lit+1;
4067         
4068         size--;
4069         
4070         if(lp1 == 0) {
4071           /* this means lit = 0xffffffff, or -1 */
4072           
4073           
4074           DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4075           rFalseIfx.condition ^= 1;
4076           genSkipCond(&rFalseIfx,right,size,7);
4077           if(ifx) ifx->generated = 1;
4078           return;
4079         }
4080         
4081         if(lit == 0) {
4082           int s = size;
4083           
4084           if(rFalseIfx.condition) {
4085             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4086             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4087           }
4088           
4089           emitpcode(POC_MOVFW, popGet(AOP(right),size));
4090           while(size--)
4091             emitpcode(POC_IORFW, popGet(AOP(right),size));
4092           
4093           
4094           emitSKPZ;
4095           if(rFalseIfx.condition) {
4096             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4097             emitpLabel(truelbl->key);
4098           }else {
4099             rFalseIfx.condition ^= 1;
4100             genSkipCond(&rFalseIfx,right,s,7);
4101           }
4102           
4103           if(ifx) ifx->generated = 1;
4104           return;
4105         }
4106         
4107         if((size == 1) &&  (0 == (lp1&0xff))) {
4108           /* lower byte of signed word is zero */
4109           DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4110           i = ((lp1 >> 8) & 0xff) ^0x80;
4111           emitpcode(POC_MOVFW, popGet(AOP(right),size));
4112           emitpcode(POC_ADDLW, popGetLit( 0x80));
4113           emitpcode(POC_ADDLW, popGetLit(0x100-i));
4114           rFalseIfx.condition ^= 1;
4115           genSkipc(&rFalseIfx);
4116           
4117           
4118           if(ifx) ifx->generated = 1;
4119           return;
4120         }
4121         
4122         if(lit & (0x80 << (size*8))) {
4123           /* Lit is less than zero */
4124           DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4125           //rFalseIfx.condition ^= 1;
4126           //genSkipCond(&rFalseIfx,left,size,7);
4127           //rFalseIfx.condition ^= 1;
4128           emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4129           //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4130           
4131           if(rFalseIfx.condition)
4132             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4133           else
4134             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4135           
4136           
4137         } else {
4138           /* Lit is greater than or equal to zero */
4139           DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4140           //rFalseIfx.condition ^= 1;
4141           //genSkipCond(&rFalseIfx,right,size,7);
4142           //rFalseIfx.condition ^= 1;
4143           
4144           //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4145           //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4146           
4147           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4148           if(rFalseIfx.condition)
4149             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4150           else
4151             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4152           
4153         }
4154         
4155         
4156         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4157         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4158         
4159         while(size--) {
4160           
4161           emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4162           emitSKPNZ;
4163           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4164         }
4165         rFalseIfx.condition ^= 1;
4166         //rFalseIfx.condition = 1;
4167         genSkipc(&rFalseIfx);
4168         
4169         emitpLabel(truelbl->key);
4170         
4171         if(ifx) ifx->generated = 1;
4172         return;
4173         // end of if (sign)
4174   } else {
4175     
4176     /* compare word or long to an unsigned literal on the right.*/
4177     
4178     
4179     size--;
4180     if(lit < 0xff) {
4181       DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4182       switch (lit) {
4183       case 0:
4184         break; /* handled above */
4185       /*
4186       case 0xff:
4187       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4188       while(size--)
4189       emitpcode(POC_IORFW, popGet(AOP(right),size));
4190       genSkipz2(&rFalseIfx,0);
4191       break;
4192       */
4193       default:
4194         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4195         while(--size)
4196           emitpcode(POC_IORFW, popGet(AOP(right),size));
4197         
4198         emitSKPZ;
4199         if(rFalseIfx.condition)
4200           emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4201         else
4202           emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4203         
4204         
4205         emitpcode(POC_MOVLW, popGetLit(lit+1));
4206         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4207         
4208         rFalseIfx.condition ^= 1;
4209         genSkipc(&rFalseIfx);
4210       }
4211       
4212       emitpLabel(truelbl->key);
4213       
4214       if(ifx) ifx->generated = 1;
4215       return;
4216     }
4217     
4218     
4219     lit++;
4220     DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4221     i = (lit >> (size*8)) & 0xff;
4222     
4223     emitpcode(POC_MOVLW, popGetLit(i));
4224     emitpcode(POC_SUBFW, popGet(AOP(right),size));
4225     
4226     while(size--) {
4227       i = (lit >> (size*8)) & 0xff;
4228       
4229       if(i) {
4230         emitpcode(POC_MOVLW, popGetLit(i));
4231         emitSKPNZ;
4232         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4233       } else {
4234       /* this byte of the lit is zero, 
4235         *if it's not the last then OR in the variable */
4236         if(size)
4237           emitpcode(POC_IORFW, popGet(AOP(right),size));
4238       }
4239     }
4240     
4241     
4242     emitpLabel(lbl->key);
4243     
4244     rFalseIfx.condition ^= 1;
4245     genSkipc(&rFalseIfx);
4246   }
4247   
4248   if(sign)
4249     emitpLabel(truelbl->key);
4250   if(ifx) ifx->generated = 1;
4251   return;
4252     }
4253   }
4254   /* Compare two variables */
4255   
4256   DEBUGpic14_emitcode(";sign","%d",sign);
4257   
4258   size--;
4259   if(sign) {
4260     /* Sigh. thus sucks... */
4261     if(size) {
4262       emitpcode(POC_MOVFW, popGet(AOP(left),size));
4263       emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4264       emitpcode(POC_MOVLW, popGetLit(0x80));
4265       emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4266       emitpcode(POC_XORFW, popGet(AOP(right),size));
4267       emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4268     } else {
4269       /* Signed char comparison */
4270       /* Special thanks to Nikolai Golovchenko for this snippet */
4271       emitpcode(POC_MOVFW, popGet(AOP(right),0));
4272       emitpcode(POC_SUBFW, popGet(AOP(left),0));
4273       emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4274       emitpcode(POC_XORFW, popGet(AOP(left),0));
4275       emitpcode(POC_XORFW, popGet(AOP(right),0));
4276       emitpcode(POC_ADDLW, popGetLit(0x80));
4277       
4278       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4279       genSkipc(&rFalseIfx);
4280       
4281       if(ifx) ifx->generated = 1;
4282       return;
4283     }
4284     
4285   } else {
4286     
4287     emitpcode(POC_MOVFW, popGet(AOP(right),size));
4288     emitpcode(POC_SUBFW, popGet(AOP(left),size));
4289   }
4290   
4291   
4292   /* The rest of the bytes of a multi-byte compare */
4293   while (size) {
4294     
4295     emitSKPZ;
4296     emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4297     size--;
4298     
4299     emitpcode(POC_MOVFW, popGet(AOP(right),size));
4300     emitpcode(POC_SUBFW, popGet(AOP(left),size));
4301     
4302     
4303   }
4304   
4305   emitpLabel(lbl->key);
4306   
4307   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4308   if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4309     (AOP_TYPE(result) == AOP_REG)) {
4310     emitpcode(POC_CLRF, popGet(AOP(result),0));
4311     emitpcode(POC_RLF, popGet(AOP(result),0));
4312   } else {
4313     genSkipc(&rFalseIfx);
4314   }       
4315   //genSkipc(&rFalseIfx);
4316   if(ifx) ifx->generated = 1;
4317   
4318   return;
4319   
4320   }
4321   
4322   // check_carry:
4323   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4324     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4325     pic14_outBitC(result);
4326   } else {
4327     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4328     /* if the result is used in the next
4329     ifx conditional branch then generate
4330     code a little differently */
4331     if (ifx )
4332       genIfxJump (ifx,"c");
4333     else
4334       pic14_outBitC(result);
4335     /* leave the result in acc */
4336   }
4337   
4338 }
4339
4340 /*-----------------------------------------------------------------*/
4341 /* genCmpGt :- greater than comparison                             */
4342 /*-----------------------------------------------------------------*/
4343 static void genCmpGt (iCode *ic, iCode *ifx)
4344 {
4345   operand *left, *right, *result;
4346   sym_link *letype , *retype;
4347   int sign ;
4348   
4349   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4350   left = IC_LEFT(ic);
4351   right= IC_RIGHT(ic);
4352   result = IC_RESULT(ic);
4353   
4354   letype = getSpec(operandType(left));
4355   retype =getSpec(operandType(right));
4356   sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4357   /* assign the amsops */
4358   aopOp (left,ic,FALSE);
4359   aopOp (right,ic,FALSE);
4360   aopOp (result,ic,TRUE);
4361   
4362   genCmp(right, left, result, ifx, sign);
4363   
4364   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4365   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4366   freeAsmop(result,NULL,ic,TRUE); 
4367 }
4368
4369 /*-----------------------------------------------------------------*/
4370 /* genCmpLt - less than comparisons                                */
4371 /*-----------------------------------------------------------------*/
4372 static void genCmpLt (iCode *ic, iCode *ifx)
4373 {
4374   operand *left, *right, *result;
4375   sym_link *letype , *retype;
4376   int sign ;
4377   
4378   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4379   left = IC_LEFT(ic);
4380   right= IC_RIGHT(ic);
4381   result = IC_RESULT(ic);
4382   
4383   letype = getSpec(operandType(left));
4384   retype =getSpec(operandType(right));
4385   sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4386   
4387   /* assign the amsops */
4388   aopOp (left,ic,FALSE);
4389   aopOp (right,ic,FALSE);
4390   aopOp (result,ic,TRUE);
4391   
4392   genCmp(left, right, result, ifx, sign);
4393   
4394   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4395   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4396   freeAsmop(result,NULL,ic,TRUE); 
4397 }
4398
4399 /*-----------------------------------------------------------------*/
4400 /* genc16bit2lit - compare a 16 bit value to a literal             */
4401 /*-----------------------------------------------------------------*/
4402 static void genc16bit2lit(operand *op, int lit, int offset)
4403 {
4404   int i;
4405   
4406   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4407   if( (lit&0xff) == 0) 
4408     i=1;
4409   else
4410     i=0;
4411   
4412   switch( BYTEofLONG(lit,i)) { 
4413   case 0:
4414     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4415     break;
4416   case 1:
4417     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4418     break;
4419   case 0xff:
4420     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4421     break;
4422   default:
4423     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4424     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4425   }
4426   
4427   i ^= 1;
4428   
4429   switch( BYTEofLONG(lit,i)) { 
4430   case 0:
4431     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4432     break;
4433   case 1:
4434     emitSKPNZ;
4435     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4436     break;
4437   case 0xff:
4438     emitSKPNZ;
4439     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4440     break;
4441   default:
4442     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4443     emitSKPNZ;
4444     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4445     
4446   }
4447   
4448 }
4449
4450 /*-----------------------------------------------------------------*/
4451 /* gencjneshort - compare and jump if not equal                    */
4452 /*-----------------------------------------------------------------*/
4453 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4454 {
4455   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4456   int offset = 0;
4457   int res_offset = 0;  /* the result may be a different size then left or right */
4458   int res_size = AOP_SIZE(result);
4459   resolvedIfx rIfx;
4460   symbol *lbl;
4461   
4462   unsigned long lit = 0L;
4463   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4464   DEBUGpic14_AopType(__LINE__,left,right,result);
4465   if(result)
4466     DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4467   resolveIfx(&rIfx,ifx);
4468   lbl =  newiTempLabel(NULL);
4469   
4470   
4471   /* if the left side is a literal or 
4472   if the right is in a pointer register and left 
4473   is not */
4474   if ((AOP_TYPE(left) == AOP_LIT) || 
4475     (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4476     operand *t = right;
4477     right = left;
4478     left = t;
4479   }
4480   if(AOP_TYPE(right) == AOP_LIT)
4481     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4482   
4483   /* if the right side is a literal then anything goes */
4484   if (AOP_TYPE(right) == AOP_LIT &&
4485     AOP_TYPE(left) != AOP_DIR ) {
4486     switch(size) {
4487     case 2:
4488       genc16bit2lit(left, lit, 0);
4489       emitSKPNZ;
4490       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4491       break;
4492     default:
4493       while (size--) {
4494         if(lit & 0xff) {
4495           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4496           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4497         } else {
4498           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4499         }
4500         
4501         emitSKPNZ;
4502         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4503         offset++;
4504         if(res_offset < res_size-1)
4505           res_offset++;
4506         lit >>= 8;
4507       }
4508       break;
4509     }
4510   }
4511   
4512   /* if the right side is in a register or in direct space or
4513   if the left is a pointer register & right is not */    
4514   else if (AOP_TYPE(right) == AOP_REG ||
4515     AOP_TYPE(right) == AOP_DIR || 
4516     (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4517     (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4518     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4519     int lbl_key = lbl->key;
4520     
4521     if(result) {
4522       emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4523       //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4524     }else {
4525       DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4526       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4527         __FUNCTION__,__LINE__);
4528       return;
4529     }
4530     
4531     /*     switch(size) { */
4532     /*     case 2: */
4533     /*       genc16bit2lit(left, lit, 0); */
4534     /*       emitSKPNZ; */
4535     /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4536     /*       break; */
4537     /*     default: */
4538     while (size--) {
4539       int emit_skip=1;
4540       if((AOP_TYPE(left) == AOP_DIR) && 
4541         ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4542         
4543         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4544         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4545         
4546       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4547         
4548         switch (lit & 0xff) {
4549         case 0:
4550           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4551           break;
4552         case 1:
4553           emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4554           emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4555           //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4556           emit_skip=0;
4557           break;
4558         case 0xff:
4559           emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4560           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4561           //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4562           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4563           emit_skip=0;
4564           break;
4565         default:
4566           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4567           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4568         }
4569         lit >>= 8;
4570         
4571       } else {
4572         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4573       }
4574       if(emit_skip) {
4575         if(AOP_TYPE(result) == AOP_CRY) {
4576           pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4577           if(rIfx.condition)
4578             emitSKPNZ;
4579           else
4580             emitSKPZ;
4581           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4582         } else {
4583           /* fix me. probably need to check result size too */
4584           //emitpcode(POC_CLRF,popGet(AOP(result),0));
4585           if(rIfx.condition)
4586             emitSKPZ;
4587           else
4588             emitSKPNZ;
4589           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4590           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4591         }
4592         if(ifx)
4593           ifx->generated=1;
4594       }
4595       emit_skip++;
4596       offset++;
4597       if(res_offset < res_size-1)
4598         res_offset++;
4599     }
4600     /*       break; */
4601     /*     } */
4602   } else if(AOP_TYPE(right) == AOP_REG &&
4603     AOP_TYPE(left) != AOP_DIR){
4604     
4605     while(size--) {
4606       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4607       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4608       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4609       if(rIfx.condition)
4610         emitSKPNZ;
4611       else
4612         emitSKPZ;
4613       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4614       offset++;
4615       if(res_offset < res_size-1)
4616         res_offset++;
4617     }
4618     
4619   }else{
4620     /* right is a pointer reg need both a & b */
4621     while(size--) {
4622       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4623       if(strcmp(l,"b"))
4624         pic14_emitcode("mov","b,%s",l);
4625       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4626       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4627       offset++;
4628     }
4629   }
4630   
4631   emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4632   if(!rIfx.condition)
4633     emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4634   
4635   emitpLabel(lbl->key);
4636   
4637   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4638   
4639   if(ifx)
4640     ifx->generated = 1;
4641 }
4642
4643 #if 0
4644 /*-----------------------------------------------------------------*/
4645 /* gencjne - compare and jump if not equal                         */
4646 /*-----------------------------------------------------------------*/
4647 static void gencjne(operand *left, operand *right, iCode *ifx)
4648 {
4649   symbol *tlbl  = newiTempLabel(NULL);
4650   
4651   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4652   gencjneshort(left, right, lbl);
4653   
4654   pic14_emitcode("mov","a,%s",one);
4655   pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4656   pic14_emitcode("","%05d_DS_:",lbl->key+100);
4657   pic14_emitcode("clr","a");
4658   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4659   
4660   emitpLabel(lbl->key);
4661   emitpLabel(tlbl->key);
4662   
4663 }
4664 #endif
4665
4666 /*-----------------------------------------------------------------*/
4667 /* genCmpEq - generates code for equal to                          */
4668 /*-----------------------------------------------------------------*/
4669 static void genCmpEq (iCode *ic, iCode *ifx)
4670 {
4671   operand *left, *right, *result;
4672   unsigned long lit = 0L;
4673   int size,offset=0;
4674   
4675   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4676   
4677   if(ifx)
4678     DEBUGpic14_emitcode ("; ifx is non-null","");
4679   else
4680     DEBUGpic14_emitcode ("; ifx is null","");
4681   
4682   aopOp((left=IC_LEFT(ic)),ic,FALSE);
4683   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4684   aopOp((result=IC_RESULT(ic)),ic,TRUE);
4685   
4686   size = max(AOP_SIZE(left),AOP_SIZE(right));
4687   
4688   DEBUGpic14_AopType(__LINE__,left,right,result);
4689   
4690   /* if literal, literal on the right or 
4691   if the right is in a pointer register and left 
4692   is not */
4693   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4694     (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4695     operand *tmp = right ;
4696     right = left;
4697     left = tmp;
4698   }
4699   
4700   
4701   if(ifx && !AOP_SIZE(result)){
4702     symbol *tlbl;
4703     /* if they are both bit variables */
4704     if (AOP_TYPE(left) == AOP_CRY &&
4705       ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4706       if(AOP_TYPE(right) == AOP_LIT){
4707         unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4708         if(lit == 0L){
4709           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4710           pic14_emitcode("cpl","c");
4711         } else if(lit == 1L) {
4712           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4713         } else {
4714           pic14_emitcode("clr","c");
4715         }
4716         /* AOP_TYPE(right) == AOP_CRY */
4717       } else {
4718         symbol *lbl = newiTempLabel(NULL);
4719         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4720         pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4721         pic14_emitcode("cpl","c");
4722         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4723       }
4724       /* if true label then we jump if condition
4725       supplied is true */
4726       tlbl = newiTempLabel(NULL);
4727       if ( IC_TRUE(ifx) ) {
4728         pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4729         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4730       } else {
4731         pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4732         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4733       }
4734       pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4735       
4736       {
4737         /* left and right are both bit variables, result is carry */
4738         resolvedIfx rIfx;
4739         
4740         resolveIfx(&rIfx,ifx);
4741         
4742         emitpcode(POC_MOVLW,popGet(AOP(left),0));
4743         emitpcode(POC_ANDFW,popGet(AOP(left),0));
4744         emitpcode(POC_BTFSC,popGet(AOP(right),0));
4745         emitpcode(POC_ANDLW,popGet(AOP(left),0));
4746         genSkipz2(&rIfx,0);
4747       }
4748     } else {
4749       
4750       /* They're not both bit variables. Is the right a literal? */
4751       if(AOP_TYPE(right) == AOP_LIT) {
4752         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4753         
4754         switch(size) {
4755           
4756         case 1:
4757           switch(lit & 0xff) {
4758           case 1:
4759             if ( IC_TRUE(ifx) ) {
4760               emitpcode(POC_DECFW,popGet(AOP(left),offset));
4761               emitSKPNZ;
4762               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4763             } else {
4764               emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4765               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4766             }
4767             break;
4768           case 0xff:
4769             if ( IC_TRUE(ifx) ) {
4770               emitpcode(POC_INCFW,popGet(AOP(left),offset));
4771               emitSKPNZ;
4772               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4773             } else {
4774               emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4775               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4776             }
4777             break;
4778           default:
4779             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4780             if(lit)
4781               emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4782             genSkip(ifx,'z');
4783           }
4784           
4785           
4786           /* end of size == 1 */
4787           break;
4788           
4789           case 2:
4790             genc16bit2lit(left,lit,offset);
4791             genSkip(ifx,'z');
4792             break;
4793             /* end of size == 2 */
4794             
4795           default:
4796             /* size is 4 */
4797             if(lit==0) {
4798               emitpcode(POC_MOVFW,popGet(AOP(left),0));
4799               emitpcode(POC_IORFW,popGet(AOP(left),1));
4800               emitpcode(POC_IORFW,popGet(AOP(left),2));
4801               emitpcode(POC_IORFW,popGet(AOP(left),3));
4802               
4803             } else {
4804               
4805               /* search for patterns that can be optimized */
4806               
4807               genc16bit2lit(left,lit,0);
4808               lit >>= 16;
4809               if(lit) {
4810                 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4811                 //genSkip(ifx,'z');
4812                 genc16bit2lit(left,lit,2);
4813               } else {
4814                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4815                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4816                 
4817               }
4818               
4819             }
4820             
4821             genSkip(ifx,'z');
4822         }
4823         
4824         ifx->generated = 1;
4825         goto release ;
4826         
4827         
4828       } else if(AOP_TYPE(right) == AOP_CRY ) {
4829         /* we know the left is not a bit, but that the right is */
4830         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4831         emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4832           popGet(AOP(right),offset));
4833         emitpcode(POC_XORLW,popGetLit(1));
4834         
4835         /* if the two are equal, then W will be 0 and the Z bit is set
4836         * we could test Z now, or go ahead and check the high order bytes if
4837         * the variable we're comparing is larger than a byte. */
4838         
4839         while(--size)
4840           emitpcode(POC_IORFW,popGet(AOP(left),offset));
4841         
4842         if ( IC_TRUE(ifx) ) {
4843           emitSKPNZ;
4844           emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4845           pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4846         } else {
4847           emitSKPZ;
4848           emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4849           pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4850         }
4851         
4852       } else {
4853         /* They're both variables that are larger than bits */
4854         int s = size;
4855         
4856         tlbl = newiTempLabel(NULL);
4857         
4858         while(size--) {
4859           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4860           emitpcode(POC_XORFW,popGet(AOP(right),offset));
4861           
4862           if ( IC_TRUE(ifx) ) {
4863             if(size) {
4864               emitSKPZ;
4865               emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4866               pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4867             } else {
4868               emitSKPNZ;
4869               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4870               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4871             }
4872           } else {
4873             emitSKPZ;
4874             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4875             pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4876           }
4877           offset++;
4878         }
4879         if(s>1 && IC_TRUE(ifx)) {
4880           emitpLabel(tlbl->key);
4881           pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4882         }
4883       }
4884     }
4885     /* mark the icode as generated */
4886     ifx->generated = 1;
4887     goto release ;
4888   }
4889   
4890   /* if they are both bit variables */
4891   if (AOP_TYPE(left) == AOP_CRY &&
4892     ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4893     if(AOP_TYPE(right) == AOP_LIT){
4894       unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4895       if(lit == 0L){
4896         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4897         pic14_emitcode("cpl","c");
4898       } else if(lit == 1L) {
4899         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4900       } else {
4901         pic14_emitcode("clr","c");
4902       }
4903       /* AOP_TYPE(right) == AOP_CRY */
4904     } else {
4905       symbol *lbl = newiTempLabel(NULL);
4906       pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4907       pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4908       pic14_emitcode("cpl","c");
4909       pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4910     }
4911     /* c = 1 if egal */
4912     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4913       pic14_outBitC(result);
4914       goto release ;
4915     }
4916     if (ifx) {
4917       genIfxJump (ifx,"c");
4918       goto release ;
4919     }
4920     /* if the result is used in an arithmetic operation
4921     then put the result in place */
4922     pic14_outBitC(result);
4923   } else {
4924     
4925     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4926     gencjne(left,right,result,ifx);
4927     /*
4928     if(ifx) 
4929     gencjne(left,right,newiTempLabel(NULL));
4930     else {
4931     if(IC_TRUE(ifx)->key)
4932     gencjne(left,right,IC_TRUE(ifx)->key);
4933     else
4934     gencjne(left,right,IC_FALSE(ifx)->key);
4935     ifx->generated = 1;
4936     goto release ;
4937     }
4938     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4939     aopPut(AOP(result),"a",0);
4940     goto release ;
4941     }
4942     
4943       if (ifx) {
4944       genIfxJump (ifx,"a");
4945       goto release ;
4946       }
4947     */
4948     /* if the result is used in an arithmetic operation
4949     then put the result in place */
4950     /*
4951     if (AOP_TYPE(result) != AOP_CRY) 
4952     pic14_outAcc(result);
4953     */
4954     /* leave the result in acc */
4955   }
4956   
4957 release:
4958   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4959   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4960   freeAsmop(result,NULL,ic,TRUE);
4961 }
4962
4963 /*-----------------------------------------------------------------*/
4964 /* ifxForOp - returns the icode containing the ifx for operand     */
4965 /*-----------------------------------------------------------------*/
4966 static iCode *ifxForOp ( operand *op, iCode *ic )
4967 {
4968   /* if true symbol then needs to be assigned */
4969   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4970   if (IS_TRUE_SYMOP(op))
4971     return NULL ;
4972   
4973     /* if this has register type condition and
4974     the next instruction is ifx with the same operand
4975   and live to of the operand is upto the ifx only then */
4976   if (ic->next &&
4977     ic->next->op == IFX &&
4978     IC_COND(ic->next)->key == op->key &&
4979     OP_SYMBOL(op)->liveTo <= ic->next->seq )
4980     return ic->next;
4981   
4982   if (ic->next &&
4983     ic->next->op == IFX &&
4984     IC_COND(ic->next)->key == op->key) {
4985     DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4986     return ic->next;
4987   }
4988   
4989   DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4990   if (ic->next &&
4991     ic->next->op == IFX)
4992     DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4993   
4994   if (ic->next &&
4995     ic->next->op == IFX &&
4996     IC_COND(ic->next)->key == op->key) {
4997     DEBUGpic14_emitcode ("; "," key is okay");
4998     DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4999       OP_SYMBOL(op)->liveTo,
5000       ic->next->seq);
5001   }
5002   
5003   
5004   return NULL;
5005 }
5006 /*-----------------------------------------------------------------*/
5007 /* genAndOp - for && operation                                     */
5008 /*-----------------------------------------------------------------*/
5009 static void genAndOp (iCode *ic)
5010 {
5011   operand *left,*right, *result;
5012   /*     symbol *tlbl; */
5013   
5014   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5015   /* note here that && operations that are in an
5016   if statement are taken away by backPatchLabels
5017   only those used in arthmetic operations remain */
5018   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5019   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5020   aopOp((result=IC_RESULT(ic)),ic,FALSE);
5021   
5022   DEBUGpic14_AopType(__LINE__,left,right,result);
5023   
5024   emitpcode(POC_MOVFW,popGet(AOP(left),0));
5025   emitpcode(POC_ANDFW,popGet(AOP(right),0));
5026   emitpcode(POC_MOVWF,popGet(AOP(result),0));
5027   
5028   /* if both are bit variables */
5029   /*     if (AOP_TYPE(left) == AOP_CRY && */
5030   /*         AOP_TYPE(right) == AOP_CRY ) { */
5031   /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5032   /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5033   /*         pic14_outBitC(result); */
5034   /*     } else { */
5035   /*         tlbl = newiTempLabel(NULL); */
5036   /*         pic14_toBoolean(left);     */
5037   /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5038   /*         pic14_toBoolean(right); */
5039   /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5040   /*         pic14_outBitAcc(result); */
5041   /*     } */
5042   
5043   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5044   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5045   freeAsmop(result,NULL,ic,TRUE);
5046 }
5047
5048
5049 /*-----------------------------------------------------------------*/
5050 /* genOrOp - for || operation                                      */
5051 /*-----------------------------------------------------------------*/
5052 /*
5053 tsd pic port -
5054 modified this code, but it doesn't appear to ever get called
5055 */
5056
5057 static void genOrOp (iCode *ic)
5058 {
5059   operand *left,*right, *result;
5060   symbol *tlbl;
5061   
5062   /* note here that || operations that are in an
5063   if statement are taken away by backPatchLabels
5064   only those used in arthmetic operations remain */
5065   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5066   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5067   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5068   aopOp((result=IC_RESULT(ic)),ic,FALSE);
5069   
5070   DEBUGpic14_AopType(__LINE__,left,right,result);
5071   
5072   /* if both are bit variables */
5073   if (AOP_TYPE(left) == AOP_CRY &&
5074     AOP_TYPE(right) == AOP_CRY ) {
5075     pic14_emitcode("clrc","");
5076     pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5077       AOP(left)->aopu.aop_dir,
5078       AOP(left)->aopu.aop_dir);
5079     pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5080       AOP(right)->aopu.aop_dir,
5081       AOP(right)->aopu.aop_dir);
5082     pic14_emitcode("setc","");
5083     
5084   } else {
5085     tlbl = newiTempLabel(NULL);
5086     pic14_toBoolean(left);
5087     emitSKPZ;
5088     pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5089     pic14_toBoolean(right);
5090     pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5091     
5092     pic14_outBitAcc(result);
5093   }
5094   
5095   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5096   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5097   freeAsmop(result,NULL,ic,TRUE);            
5098 }
5099
5100 /*-----------------------------------------------------------------*/
5101 /* isLiteralBit - test if lit == 2^n                               */
5102 /*-----------------------------------------------------------------*/
5103 static int isLiteralBit(unsigned long lit)
5104 {
5105   unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5106     0x100L,0x200L,0x400L,0x800L,
5107     0x1000L,0x2000L,0x4000L,0x8000L,
5108     0x10000L,0x20000L,0x40000L,0x80000L,
5109     0x100000L,0x200000L,0x400000L,0x800000L,
5110     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5111     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5112   int idx;
5113   
5114   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5115   for(idx = 0; idx < 32; idx++)
5116     if(lit == pw[idx])
5117       return idx+1;
5118     return 0;
5119 }
5120
5121 /*-----------------------------------------------------------------*/
5122 /* continueIfTrue -                                                */
5123 /*-----------------------------------------------------------------*/
5124 static void continueIfTrue (iCode *ic)
5125 {
5126   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5127   if(IC_TRUE(ic))
5128     pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5129   ic->generated = 1;
5130 }
5131
5132 /*-----------------------------------------------------------------*/
5133 /* jmpIfTrue -                                                     */
5134 /*-----------------------------------------------------------------*/
5135 static void jumpIfTrue (iCode *ic)
5136 {
5137   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5138   if(!IC_TRUE(ic))
5139     pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5140   ic->generated = 1;
5141 }
5142
5143 /*-----------------------------------------------------------------*/
5144 /* jmpTrueOrFalse -                                                */
5145 /*-----------------------------------------------------------------*/
5146 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5147 {
5148   // ugly but optimized by peephole
5149   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5150   if(IC_TRUE(ic)){
5151     symbol *nlbl = newiTempLabel(NULL);
5152     pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5153     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5154     pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5155     pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5156   }
5157   else{
5158     pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5159     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5160   }
5161   ic->generated = 1;
5162 }
5163
5164 /*-----------------------------------------------------------------*/
5165 /* genAnd  - code for and                                          */
5166 /*-----------------------------------------------------------------*/
5167 static void genAnd (iCode *ic, iCode *ifx)
5168 {
5169   operand *left, *right, *result;
5170   int size, offset=0;  
5171   unsigned long lit = 0L;
5172   int bytelit = 0;
5173   resolvedIfx rIfx;
5174   
5175   
5176   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5177   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5178   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5179   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5180   
5181   resolveIfx(&rIfx,ifx);
5182   
5183   /* if left is a literal & right is not then exchange them */
5184   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5185     AOP_NEEDSACC(left)) {
5186     operand *tmp = right ;
5187     right = left;
5188     left = tmp;
5189   }
5190   
5191   /* if result = right then exchange them */
5192   if(pic14_sameRegs(AOP(result),AOP(right))){
5193     operand *tmp = right ;
5194     right = left;
5195     left = tmp;
5196   }
5197   
5198   /* if right is bit then exchange them */
5199   if (AOP_TYPE(right) == AOP_CRY &&
5200     AOP_TYPE(left) != AOP_CRY){
5201     operand *tmp = right ;
5202     right = left;
5203     left = tmp;
5204   }
5205   if(AOP_TYPE(right) == AOP_LIT)
5206     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5207   
5208   size = AOP_SIZE(result);
5209   
5210   DEBUGpic14_AopType(__LINE__,left,right,result);
5211   
5212   // if(bit & yy)
5213   // result = bit & yy;
5214   if (AOP_TYPE(left) == AOP_CRY){
5215     // c = bit & literal;
5216     if(AOP_TYPE(right) == AOP_LIT){
5217       if(lit & 1) {
5218         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5219           // no change
5220           goto release;
5221         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5222       } else {
5223         // bit(result) = 0;
5224         if(size && (AOP_TYPE(result) == AOP_CRY)){
5225           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5226           goto release;
5227         }
5228         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5229           jumpIfTrue(ifx);
5230           goto release;
5231         }
5232         pic14_emitcode("clr","c");
5233       }
5234     } else {
5235       if (AOP_TYPE(right) == AOP_CRY){
5236         // c = bit & bit;
5237         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5238         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5239       } else {
5240         // c = bit & val;
5241         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5242         // c = lsb
5243         pic14_emitcode("rrc","a");
5244         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5245       }
5246     }
5247     // bit = c
5248     // val = c
5249     if(size)
5250       pic14_outBitC(result);
5251     // if(bit & ...)
5252     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5253       genIfxJump(ifx, "c");           
5254     goto release ;
5255   }
5256   
5257   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5258   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5259   if((AOP_TYPE(right) == AOP_LIT) &&
5260     (AOP_TYPE(result) == AOP_CRY) &&
5261     (AOP_TYPE(left) != AOP_CRY)){
5262     int posbit = isLiteralBit(lit);
5263     /* left &  2^n */
5264     if(posbit){
5265       posbit--;
5266       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5267       // bit = left & 2^n
5268       if(size)
5269         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5270       // if(left &  2^n)
5271       else{
5272         if(ifx){
5273           int offset = 0;
5274           while (posbit > 7) {
5275             posbit -= 8;
5276             offset++;
5277           }
5278           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5279             newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5280           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5281           
5282           ifx->generated = 1;
5283         }
5284         goto release;
5285       }
5286     } else {
5287       symbol *tlbl = newiTempLabel(NULL);
5288       int sizel = AOP_SIZE(left);
5289       if(size)
5290         pic14_emitcode("setb","c");
5291       while(sizel--){
5292         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5293           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5294           // byte ==  2^n ?
5295           if((posbit = isLiteralBit(bytelit)) != 0)
5296             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5297           else{
5298             if(bytelit != 0x0FFL)
5299               pic14_emitcode("anl","a,%s",
5300               aopGet(AOP(right),offset,FALSE,TRUE));
5301             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5302           }
5303         }
5304         offset++;
5305       }
5306       // bit = left & literal
5307       if(size){
5308         pic14_emitcode("clr","c");
5309         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5310       }
5311       // if(left & literal)
5312       else{
5313         if(ifx)
5314           jmpTrueOrFalse(ifx, tlbl);
5315         goto release ;
5316       }
5317     }
5318     pic14_outBitC(result);
5319     goto release ;
5320   }
5321   
5322   /* if left is same as result */
5323   if(pic14_sameRegs(AOP(result),AOP(left))){
5324     int know_W = -1;
5325     for(;size--; offset++,lit>>=8) {
5326       if(AOP_TYPE(right) == AOP_LIT){
5327         switch(lit & 0xff) {
5328         case 0x00:
5329           /*  and'ing with 0 has clears the result */
5330           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5331           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5332           break;
5333         case 0xff:
5334           /* and'ing with 0xff is a nop when the result and left are the same */
5335           break;
5336           
5337         default:
5338           {
5339             int p = my_powof2( (~lit) & 0xff );
5340             if(p>=0) {
5341               /* only one bit is set in the literal, so use a bcf instruction */
5342               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5343               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5344               
5345             } else {
5346               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5347               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5348               if(know_W != (int)(lit&0xff))
5349                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5350               know_W = lit &0xff;
5351               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5352             }
5353           }    
5354         }
5355       } else {
5356         if (AOP_TYPE(left) == AOP_ACC) {
5357           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5358         } else {        
5359           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5360           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5361           
5362         }
5363       }
5364     }
5365     
5366   } else {
5367     // left & result in different registers
5368     if(AOP_TYPE(result) == AOP_CRY){
5369       // result = bit
5370       // if(size), result in bit
5371       // if(!size && ifx), conditional oper: if(left & right)
5372       symbol *tlbl = newiTempLabel(NULL);
5373       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5374       if(size)
5375         pic14_emitcode("setb","c");
5376       while(sizer--){
5377         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5378         pic14_emitcode("anl","a,%s",
5379           aopGet(AOP(left),offset,FALSE,FALSE));
5380         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5381         offset++;
5382       }
5383       if(size){
5384         CLRC;
5385         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5386         pic14_outBitC(result);
5387       } else if(ifx)
5388         jmpTrueOrFalse(ifx, tlbl);
5389     } else {
5390       for(;(size--);offset++) {
5391         // normal case
5392         // result = left & right
5393         if(AOP_TYPE(right) == AOP_LIT){
5394           int t = (lit >> (offset*8)) & 0x0FFL;
5395           switch(t) { 
5396           case 0x00:
5397             pic14_emitcode("clrf","%s",
5398               aopGet(AOP(result),offset,FALSE,FALSE));
5399             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5400             break;
5401           case 0xff:
5402             if(AOP_TYPE(left) != AOP_ACC) {
5403               pic14_emitcode("movf","%s,w",
5404                 aopGet(AOP(left),offset,FALSE,FALSE));
5405               pic14_emitcode("movwf","%s",
5406                 aopGet(AOP(result),offset,FALSE,FALSE));
5407               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5408             }
5409             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5410             break;
5411           default:
5412             if(AOP_TYPE(left) == AOP_ACC) {
5413               emitpcode(POC_ANDLW, popGetLit(t));
5414             } else {
5415               pic14_emitcode("movlw","0x%x",t);
5416               pic14_emitcode("andwf","%s,w",
5417                 aopGet(AOP(left),offset,FALSE,FALSE));
5418               pic14_emitcode("movwf","%s",
5419                 aopGet(AOP(result),offset,FALSE,FALSE));
5420               
5421               emitpcode(POC_MOVLW, popGetLit(t));
5422               emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5423             }
5424             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5425           }
5426           continue;
5427         }
5428         
5429         if (AOP_TYPE(left) == AOP_ACC) {
5430           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5431           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5432         } else {
5433           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5434           pic14_emitcode("andwf","%s,w",
5435             aopGet(AOP(left),offset,FALSE,FALSE));
5436           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5437           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5438         }
5439         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5440         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5441       }
5442     }
5443   }
5444   
5445 release :
5446   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5447   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5448   freeAsmop(result,NULL,ic,TRUE);     
5449 }
5450
5451 /*-----------------------------------------------------------------*/
5452 /* genOr  - code for or                                            */
5453 /*-----------------------------------------------------------------*/
5454 static void genOr (iCode *ic, iCode *ifx)
5455 {
5456   operand *left, *right, *result;
5457   int size, offset=0;
5458   unsigned long lit = 0L;
5459   
5460   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5461   
5462   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5463   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5464   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5465   
5466   DEBUGpic14_AopType(__LINE__,left,right,result);
5467   
5468   /* if left is a literal & right is not then exchange them */
5469   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5470     AOP_NEEDSACC(left)) {
5471     operand *tmp = right ;
5472     right = left;
5473     left = tmp;
5474   }
5475   
5476   /* if result = right then exchange them */
5477   if(pic14_sameRegs(AOP(result),AOP(right))){
5478     operand *tmp = right ;
5479     right = left;
5480     left = tmp;
5481   }
5482   
5483   /* if right is bit then exchange them */
5484   if (AOP_TYPE(right) == AOP_CRY &&
5485     AOP_TYPE(left) != AOP_CRY){
5486     operand *tmp = right ;
5487     right = left;
5488     left = tmp;
5489   }
5490   
5491   DEBUGpic14_AopType(__LINE__,left,right,result);
5492   
5493   if(AOP_TYPE(right) == AOP_LIT)
5494     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5495   
5496   size = AOP_SIZE(result);
5497   
5498   // if(bit | yy)
5499   // xx = bit | yy;
5500   if (AOP_TYPE(left) == AOP_CRY){
5501     if(AOP_TYPE(right) == AOP_LIT){
5502       // c = bit & literal;
5503       if(lit){
5504         // lit != 0 => result = 1
5505         if(AOP_TYPE(result) == AOP_CRY){
5506           if(size)
5507             emitpcode(POC_BSF, popGet(AOP(result),0));
5508           //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5509           //   AOP(result)->aopu.aop_dir,
5510           //   AOP(result)->aopu.aop_dir);
5511           else if(ifx)
5512             continueIfTrue(ifx);
5513           goto release;
5514         }
5515       } else {
5516         // lit == 0 => result = left
5517         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5518           goto release;
5519         pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5520       }
5521     } else {
5522       if (AOP_TYPE(right) == AOP_CRY){
5523         if(pic14_sameRegs(AOP(result),AOP(left))){
5524           // c = bit | bit;
5525           emitpcode(POC_BCF,   popGet(AOP(result),0));
5526           emitpcode(POC_BTFSC, popGet(AOP(right),0));
5527           emitpcode(POC_BSF,   popGet(AOP(result),0));
5528           
5529           pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5530             AOP(result)->aopu.aop_dir,
5531             AOP(result)->aopu.aop_dir);
5532           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5533             AOP(right)->aopu.aop_dir,
5534             AOP(right)->aopu.aop_dir);
5535           pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5536             AOP(result)->aopu.aop_dir,
5537             AOP(result)->aopu.aop_dir);
5538         } else {
5539           if( AOP_TYPE(result) == AOP_ACC) {
5540             emitpcode(POC_MOVLW, popGetLit(0));
5541             emitpcode(POC_BTFSS, popGet(AOP(right),0));
5542             emitpcode(POC_BTFSC, popGet(AOP(left),0));
5543             emitpcode(POC_MOVLW, popGetLit(1));
5544             
5545           } else {
5546             
5547             emitpcode(POC_BCF,   popGet(AOP(result),0));
5548             emitpcode(POC_BTFSS, popGet(AOP(right),0));
5549             emitpcode(POC_BTFSC, popGet(AOP(left),0));
5550             emitpcode(POC_BSF,   popGet(AOP(result),0));
5551             
5552             pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5553               AOP(result)->aopu.aop_dir,
5554               AOP(result)->aopu.aop_dir);
5555             pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5556               AOP(right)->aopu.aop_dir,
5557               AOP(right)->aopu.aop_dir);
5558             pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5559               AOP(left)->aopu.aop_dir,
5560               AOP(left)->aopu.aop_dir);
5561             pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5562               AOP(result)->aopu.aop_dir,
5563               AOP(result)->aopu.aop_dir);
5564           }
5565         }
5566       } else {
5567         // c = bit | val;
5568         symbol *tlbl = newiTempLabel(NULL);
5569         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5570         
5571         
5572         emitpcode(POC_BCF,   popGet(AOP(result),0));
5573         if( AOP_TYPE(right) == AOP_ACC) {
5574           emitpcode(POC_IORLW, popGetLit(0));
5575           emitSKPNZ;
5576           emitpcode(POC_BTFSC, popGet(AOP(left),0));
5577           emitpcode(POC_BSF,   popGet(AOP(result),0));
5578         }
5579         
5580         
5581         
5582         if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5583           pic14_emitcode(";XXX setb","c");
5584         pic14_emitcode(";XXX jb","%s,%05d_DS_",
5585           AOP(left)->aopu.aop_dir,tlbl->key+100);
5586         pic14_toBoolean(right);
5587         pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5588         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5589           jmpTrueOrFalse(ifx, tlbl);
5590           goto release;
5591         } else {
5592           CLRC;
5593           pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5594         }
5595       }
5596     }
5597     // bit = c
5598     // val = c
5599     if(size)
5600       pic14_outBitC(result);
5601     // if(bit | ...)
5602     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5603       genIfxJump(ifx, "c");           
5604     goto release ;
5605   }
5606   
5607   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5608   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5609   if((AOP_TYPE(right) == AOP_LIT) &&
5610     (AOP_TYPE(result) == AOP_CRY) &&
5611     (AOP_TYPE(left) != AOP_CRY)){
5612     if(lit){
5613       pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5614       // result = 1
5615       if(size)
5616         pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5617       else 
5618         continueIfTrue(ifx);
5619       goto release;
5620     } else {
5621       pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5622       // lit = 0, result = boolean(left)
5623       if(size)
5624         pic14_emitcode(";XXX setb","c");
5625       pic14_toBoolean(right);
5626       if(size){
5627         symbol *tlbl = newiTempLabel(NULL);
5628         pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5629         CLRC;
5630         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5631       } else {
5632         genIfxJump (ifx,"a");
5633         goto release;
5634       }
5635     }
5636     pic14_outBitC(result);
5637     goto release ;
5638   }
5639   
5640   /* if left is same as result */
5641   if(pic14_sameRegs(AOP(result),AOP(left))){
5642     int know_W = -1;
5643     for(;size--; offset++,lit>>=8) {
5644       if(AOP_TYPE(right) == AOP_LIT){
5645         if((lit & 0xff) == 0)
5646           /*  or'ing with 0 has no effect */
5647           continue;
5648         else {
5649           int p = my_powof2(lit & 0xff);
5650           if(p>=0) {
5651             /* only one bit is set in the literal, so use a bsf instruction */
5652             emitpcode(POC_BSF,
5653               newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5654           } else {
5655             if(know_W != (int)(lit & 0xff))
5656               emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5657             know_W = lit & 0xff;
5658             emitpcode(POC_IORWF, popGet(AOP(left),offset));
5659           }
5660           
5661         }
5662       } else {
5663         if (AOP_TYPE(left) == AOP_ACC) {
5664           emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5665           pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5666         } else {        
5667           emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5668           emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5669           
5670           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5671           pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5672           
5673         }
5674       }
5675     }
5676   } else {
5677     // left & result in different registers
5678     if(AOP_TYPE(result) == AOP_CRY){
5679       // result = bit
5680       // if(size), result in bit
5681       // if(!size && ifx), conditional oper: if(left | right)
5682       symbol *tlbl = newiTempLabel(NULL);
5683       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5684       pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5685       
5686       
5687       if(size)
5688         pic14_emitcode(";XXX setb","c");
5689       while(sizer--){
5690         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5691         pic14_emitcode(";XXX orl","a,%s",
5692           aopGet(AOP(left),offset,FALSE,FALSE));
5693         pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5694         offset++;
5695       }
5696       if(size){
5697         CLRC;
5698         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5699         pic14_outBitC(result);
5700       } else if(ifx)
5701         jmpTrueOrFalse(ifx, tlbl);
5702     } else for(;(size--);offset++){
5703       // normal case
5704       // result = left & right
5705       if(AOP_TYPE(right) == AOP_LIT){
5706         int t = (lit >> (offset*8)) & 0x0FFL;
5707         switch(t) { 
5708         case 0x00:
5709           if (AOP_TYPE(left) != AOP_ACC) {
5710             emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5711           }
5712           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5713           
5714           break;
5715         default:
5716           if (AOP_TYPE(left) == AOP_ACC) {
5717             emitpcode(POC_IORLW,  popGetLit(t));
5718           } else {
5719             emitpcode(POC_MOVLW,  popGetLit(t));
5720             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5721           }
5722           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
5723         }
5724         continue;
5725       }
5726       
5727       // faster than result <- left, anl result,right
5728       // and better if result is SFR
5729       if (AOP_TYPE(left) == AOP_ACC) {
5730         emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5731         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5732       } else {
5733         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5734         emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5735         
5736         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5737         pic14_emitcode("iorwf","%s,w",
5738           aopGet(AOP(left),offset,FALSE,FALSE));
5739       }
5740       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5741       pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5742     }
5743   }
5744   
5745 release :
5746   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5747   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5748   freeAsmop(result,NULL,ic,TRUE);     
5749 }
5750
5751 /*-----------------------------------------------------------------*/
5752 /* genXor - code for xclusive or                                   */
5753 /*-----------------------------------------------------------------*/
5754 static void genXor (iCode *ic, iCode *ifx)
5755 {
5756   operand *left, *right, *result;
5757   int size, offset=0;
5758   unsigned long lit = 0L;
5759   
5760   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5761   
5762   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5763   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5764   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5765   
5766   /* if left is a literal & right is not ||
5767   if left needs acc & right does not */
5768   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5769     (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5770     operand *tmp = right ;
5771     right = left;
5772     left = tmp;
5773   }
5774   
5775   /* if result = right then exchange them */
5776   if(pic14_sameRegs(AOP(result),AOP(right))){
5777     operand *tmp = right ;
5778     right = left;
5779     left = tmp;
5780   }
5781   
5782   /* if right is bit then exchange them */
5783   if (AOP_TYPE(right) == AOP_CRY &&
5784     AOP_TYPE(left) != AOP_CRY){
5785     operand *tmp = right ;
5786     right = left;
5787     left = tmp;
5788   }
5789   if(AOP_TYPE(right) == AOP_LIT)
5790     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5791   
5792   size = AOP_SIZE(result);
5793   
5794   // if(bit ^ yy)
5795   // xx = bit ^ yy;
5796   if (AOP_TYPE(left) == AOP_CRY){
5797     if(AOP_TYPE(right) == AOP_LIT){
5798       // c = bit & literal;
5799       if(lit>>1){
5800         // lit>>1  != 0 => result = 1
5801         if(AOP_TYPE(result) == AOP_CRY){
5802           if(size)
5803           {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5804           pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5805           else if(ifx)
5806             continueIfTrue(ifx);
5807           goto release;
5808         }
5809         pic14_emitcode("setb","c");
5810       } else{
5811         // lit == (0 or 1)
5812         if(lit == 0){
5813           // lit == 0, result = left
5814           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5815             goto release;
5816           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5817         } else{
5818           // lit == 1, result = not(left)
5819           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5820             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5821             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5822             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5823             goto release;
5824           } else {
5825             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5826             pic14_emitcode("cpl","c");
5827           }
5828         }
5829       }
5830       
5831     } else {
5832       // right != literal
5833       symbol *tlbl = newiTempLabel(NULL);
5834       if (AOP_TYPE(right) == AOP_CRY){
5835         // c = bit ^ bit;
5836         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5837       }
5838       else{
5839         int sizer = AOP_SIZE(right);
5840         // c = bit ^ val
5841         // if val>>1 != 0, result = 1
5842         pic14_emitcode("setb","c");
5843         while(sizer){
5844           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5845           if(sizer == 1)
5846             // test the msb of the lsb
5847             pic14_emitcode("anl","a,#0xfe");
5848           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5849           sizer--;
5850         }
5851         // val = (0,1)
5852         pic14_emitcode("rrc","a");
5853       }
5854       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5855       pic14_emitcode("cpl","c");
5856       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5857     }
5858     // bit = c
5859     // val = c
5860     if(size)
5861       pic14_outBitC(result);
5862     // if(bit | ...)
5863     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5864       genIfxJump(ifx, "c");           
5865     goto release ;
5866   }
5867   
5868   if(pic14_sameRegs(AOP(result),AOP(left))){
5869     /* if left is same as result */
5870     for(;size--; offset++) {
5871       if(AOP_TYPE(right) == AOP_LIT){
5872         int t  = (lit >> (offset*8)) & 0x0FFL;
5873         if(t == 0x00L)
5874           continue;
5875         else
5876           if (IS_AOP_PREG(left)) {
5877             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5878             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5879             aopPut(AOP(result),"a",offset);
5880           } else {
5881             emitpcode(POC_MOVLW, popGetLit(t));
5882             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5883             pic14_emitcode("xrl","%s,%s",
5884               aopGet(AOP(left),offset,FALSE,TRUE),
5885               aopGet(AOP(right),offset,FALSE,FALSE));
5886           }
5887       } else {
5888         if (AOP_TYPE(left) == AOP_ACC)
5889           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5890         else {
5891           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5892           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5893           /*
5894           if (IS_AOP_PREG(left)) {
5895           pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5896           aopPut(AOP(result),"a",offset);
5897           } else
5898           pic14_emitcode("xrl","%s,a",
5899           aopGet(AOP(left),offset,FALSE,TRUE));
5900           */
5901         }
5902       }
5903     }
5904   } else {
5905     // left & result in different registers
5906     if(AOP_TYPE(result) == AOP_CRY){
5907       // result = bit
5908       // if(size), result in bit
5909       // if(!size && ifx), conditional oper: if(left ^ right)
5910       symbol *tlbl = newiTempLabel(NULL);
5911       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5912       if(size)
5913         pic14_emitcode("setb","c");
5914       while(sizer--){
5915         if((AOP_TYPE(right) == AOP_LIT) &&
5916           (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5917           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5918         } else {
5919           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5920           pic14_emitcode("xrl","a,%s",
5921             aopGet(AOP(left),offset,FALSE,FALSE));
5922         }
5923         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5924         offset++;
5925       }
5926       if(size){
5927         CLRC;
5928         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5929         pic14_outBitC(result);
5930       } else if(ifx)
5931         jmpTrueOrFalse(ifx, tlbl);
5932     } else for(;(size--);offset++){
5933       // normal case
5934       // result = left & right
5935       if(AOP_TYPE(right) == AOP_LIT){
5936         int t = (lit >> (offset*8)) & 0x0FFL;
5937         switch(t) { 
5938         case 0x00:
5939           if (AOP_TYPE(left) != AOP_ACC) {
5940             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5941           }
5942           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5943           pic14_emitcode("movf","%s,w",
5944             aopGet(AOP(left),offset,FALSE,FALSE));
5945           pic14_emitcode("movwf","%s",
5946             aopGet(AOP(result),offset,FALSE,FALSE));
5947           break;
5948         case 0xff:
5949           if (AOP_TYPE(left) == AOP_ACC) {
5950             emitpcode(POC_XORLW, popGetLit(t));
5951           } else {
5952             emitpcode(POC_COMFW,popGet(AOP(left),offset));
5953           }
5954           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5955           break;
5956         default:
5957           if (AOP_TYPE(left) == AOP_ACC) {
5958             emitpcode(POC_XORLW, popGetLit(t));
5959           } else {
5960             emitpcode(POC_MOVLW, popGetLit(t));
5961             emitpcode(POC_XORFW,popGet(AOP(left),offset));
5962           }
5963           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5964           pic14_emitcode("movlw","0x%x",t);
5965           pic14_emitcode("xorwf","%s,w",
5966             aopGet(AOP(left),offset,FALSE,FALSE));
5967           pic14_emitcode("movwf","%s",
5968             aopGet(AOP(result),offset,FALSE,FALSE));
5969           
5970         }
5971         continue;
5972       }
5973       
5974       // faster than result <- left, anl result,right
5975       // and better if result is SFR
5976       if (AOP_TYPE(left) == AOP_ACC) {
5977         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5978         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5979       } else {
5980         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5981         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5982         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5983         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5984       }
5985       if ( AOP_TYPE(result) != AOP_ACC){
5986         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5987         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5988       }
5989     }
5990   }
5991   
5992 release :
5993   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5994   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5995   freeAsmop(result,NULL,ic,TRUE);     
5996 }
5997
5998 /*-----------------------------------------------------------------*/
5999 /* genInline - write the inline code out                           */
6000 /*-----------------------------------------------------------------*/
6001 static void genInline (iCode *ic)
6002 {
6003   char *buffer, *bp, *bp1;
6004   
6005   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6006   
6007   _G.inLine += (!options.asmpeep);
6008   
6009   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6010   strcpy(buffer,IC_INLINE(ic));
6011   
6012   /* emit each line as a code */
6013   while (*bp) {
6014     if (*bp == '\n') {
6015       *bp++ = '\0';
6016       
6017       if(*bp1)
6018         addpCode2pBlock(pb,AssembleLine(bp1));
6019       bp1 = bp;
6020     } else {
6021       if (*bp == ':') {
6022         bp++;
6023         *bp = '\0';
6024         bp++;
6025         pic14_emitcode(bp1,"");
6026         bp1 = bp;
6027       } else
6028         bp++;
6029     }
6030   }
6031   if ((bp1 != bp) && *bp1)
6032     addpCode2pBlock(pb,AssembleLine(bp1));
6033   
6034   Safe_free(buffer);
6035   
6036   _G.inLine -= (!options.asmpeep);
6037 }
6038
6039 /*-----------------------------------------------------------------*/
6040 /* genRRC - rotate right with carry                                */
6041 /*-----------------------------------------------------------------*/
6042 static void genRRC (iCode *ic)
6043 {
6044   operand *left , *result ;
6045   int size, offset = 0, same;
6046   
6047   /* rotate right with carry */
6048   left = IC_LEFT(ic);
6049   result=IC_RESULT(ic);
6050   aopOp (left,ic,FALSE);
6051   aopOp (result,ic,FALSE);
6052   
6053   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6054   
6055   same = pic14_sameRegs(AOP(result),AOP(left));
6056   
6057   size = AOP_SIZE(result);    
6058   
6059   /* get the lsb and put it into the carry */
6060   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6061   
6062   offset = 0 ;
6063   
6064   while(size--) {
6065     
6066     if(same) {
6067       emitpcode(POC_RRF, popGet(AOP(left),offset));
6068     } else {
6069       emitpcode(POC_RRFW, popGet(AOP(left),offset));
6070       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6071     }
6072     
6073     offset++;
6074   }
6075   
6076   freeAsmop(left,NULL,ic,TRUE);
6077   freeAsmop(result,NULL,ic,TRUE);
6078 }
6079
6080 /*-----------------------------------------------------------------*/
6081 /* genRLC - generate code for rotate left with carry               */
6082 /*-----------------------------------------------------------------*/
6083 static void genRLC (iCode *ic)
6084 {    
6085   operand *left , *result ;
6086   int size, offset = 0;
6087   int same;
6088   
6089   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6090   /* rotate right with carry */
6091   left = IC_LEFT(ic);
6092   result=IC_RESULT(ic);
6093   aopOp (left,ic,FALSE);
6094   aopOp (result,ic,FALSE);
6095   
6096   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6097   
6098   same = pic14_sameRegs(AOP(result),AOP(left));
6099   
6100   /* move it to the result */
6101   size = AOP_SIZE(result);    
6102   
6103   /* get the msb and put it into the carry */
6104   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6105   
6106   offset = 0 ;
6107   
6108   while(size--) {
6109     
6110     if(same) {
6111       emitpcode(POC_RLF, popGet(AOP(left),offset));
6112     } else {
6113       emitpcode(POC_RLFW, popGet(AOP(left),offset));
6114       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6115     }
6116     
6117     offset++;
6118   }
6119   
6120   
6121   freeAsmop(left,NULL,ic,TRUE);
6122   freeAsmop(result,NULL,ic,TRUE);
6123 }
6124
6125 /*-----------------------------------------------------------------*/
6126 /* genGetHbit - generates code get highest order bit               */
6127 /*-----------------------------------------------------------------*/
6128 static void genGetHbit (iCode *ic)
6129 {
6130   operand *left, *result;
6131   left = IC_LEFT(ic);
6132   result=IC_RESULT(ic);
6133   aopOp (left,ic,FALSE);
6134   aopOp (result,ic,FALSE);
6135   
6136   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6137   /* get the highest order byte into a */
6138   MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6139   if(AOP_TYPE(result) == AOP_CRY){
6140     pic14_emitcode("rlc","a");
6141     pic14_outBitC(result);
6142   }
6143   else{
6144     pic14_emitcode("rl","a");
6145     pic14_emitcode("anl","a,#0x01");
6146     pic14_outAcc(result);
6147   }
6148   
6149   
6150   freeAsmop(left,NULL,ic,TRUE);
6151   freeAsmop(result,NULL,ic,TRUE);
6152 }
6153
6154 /*-----------------------------------------------------------------*/
6155 /* AccRol - rotate left accumulator by known count                 */
6156 /*-----------------------------------------------------------------*/
6157 static void AccRol (int shCount)
6158 {
6159   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6160   shCount &= 0x0007;              // shCount : 0..7
6161   switch(shCount){
6162   case 0 :
6163     break;
6164   case 1 :
6165     pic14_emitcode("rl","a");
6166     break;
6167   case 2 :
6168     pic14_emitcode("rl","a");
6169     pic14_emitcode("rl","a");
6170     break;
6171   case 3 :
6172     pic14_emitcode("swap","a");
6173     pic14_emitcode("rr","a");
6174     break;
6175   case 4 :
6176     pic14_emitcode("swap","a");
6177     break;
6178   case 5 :
6179     pic14_emitcode("swap","a");
6180     pic14_emitcode("rl","a");
6181     break;
6182   case 6 :
6183     pic14_emitcode("rr","a");
6184     pic14_emitcode("rr","a");
6185     break;
6186   case 7 :
6187     pic14_emitcode("rr","a");
6188     break;
6189   }
6190 }
6191
6192 /*-----------------------------------------------------------------*/
6193 /* AccLsh - left shift accumulator by known count                  */
6194 /*-----------------------------------------------------------------*/
6195 static void AccLsh (int shCount)
6196 {
6197   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6198   if(shCount != 0){
6199     if(shCount == 1)
6200       pic14_emitcode("add","a,acc");
6201     else 
6202       if(shCount == 2) {
6203         pic14_emitcode("add","a,acc");
6204         pic14_emitcode("add","a,acc");
6205       } else {
6206         /* rotate left accumulator */
6207         AccRol(shCount);
6208         /* and kill the lower order bits */
6209         pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6210       }
6211   }
6212 }
6213
6214 /*-----------------------------------------------------------------*/
6215 /* AccRsh - right shift accumulator by known count                 */
6216 /*-----------------------------------------------------------------*/
6217 static void AccRsh (int shCount)
6218 {
6219   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6220   if(shCount != 0){
6221     if(shCount == 1){
6222       CLRC;
6223       pic14_emitcode("rrc","a");
6224     } else {
6225       /* rotate right accumulator */
6226       AccRol(8 - shCount);
6227       /* and kill the higher order bits */
6228       pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6229     }
6230   }
6231 }
6232
6233 #if 0
6234 /*-----------------------------------------------------------------*/
6235 /* AccSRsh - signed right shift accumulator by known count                 */
6236 /*-----------------------------------------------------------------*/
6237 static void AccSRsh (int shCount)
6238 {
6239   symbol *tlbl ;
6240   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6241   if(shCount != 0){
6242     if(shCount == 1){
6243       pic14_emitcode("mov","c,acc.7");
6244       pic14_emitcode("rrc","a");
6245     } else if(shCount == 2){
6246       pic14_emitcode("mov","c,acc.7");
6247       pic14_emitcode("rrc","a");
6248       pic14_emitcode("mov","c,acc.7");
6249       pic14_emitcode("rrc","a");
6250     } else {
6251       tlbl = newiTempLabel(NULL);
6252       /* rotate right accumulator */
6253       AccRol(8 - shCount);
6254       /* and kill the higher order bits */
6255       pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6256       pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6257       pic14_emitcode("orl","a,#0x%02x",
6258         (unsigned char)~SRMask[shCount]);
6259       pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6260     }
6261   }
6262 }
6263 #endif
6264 /*-----------------------------------------------------------------*/
6265 /* shiftR1Left2Result - shift right one byte from left to result   */
6266 /*-----------------------------------------------------------------*/
6267 static void shiftR1Left2ResultSigned (operand *left, int offl,
6268                     operand *result, int offr,
6269                     int shCount)
6270 {
6271   int same;
6272   
6273   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6274   
6275   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6276   
6277   switch(shCount) {
6278   case 1:
6279     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6280     if(same) 
6281       emitpcode(POC_RRF, popGet(AOP(result),offr));
6282     else {
6283       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6284       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6285     }
6286     
6287     break;
6288   case 2:
6289     
6290     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6291     if(same) 
6292       emitpcode(POC_RRF, popGet(AOP(result),offr));
6293     else {
6294       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6295       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6296     }
6297     emitpcode(POC_RLFW, popGet(AOP(result),offr));
6298     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6299     
6300     break;
6301     
6302   case 3:
6303     if(same)
6304       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6305     else {
6306       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6307       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6308     }
6309     
6310     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6311     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6312     emitpcode(POC_ANDLW, popGetLit(0x1f));
6313     
6314     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6315     emitpcode(POC_IORLW, popGetLit(0xe0));
6316     
6317     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6318     break;
6319     
6320   case 4:
6321     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6322     emitpcode(POC_ANDLW,  popGetLit(0x0f));
6323     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6324     emitpcode(POC_IORLW,  popGetLit(0xf0));
6325     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6326     break;
6327   case 5:
6328     if(same) {
6329       emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6330     } else {
6331       emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6332       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6333     }
6334     emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6335     emitpcode(POC_ANDLW,  popGetLit(0x07));
6336     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6337     emitpcode(POC_IORLW,  popGetLit(0xf8));
6338     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6339     break;
6340     
6341   case 6:
6342     if(same) {
6343       emitpcode(POC_MOVLW, popGetLit(0x00));
6344       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6345       emitpcode(POC_MOVLW, popGetLit(0xfe));
6346       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6347       emitpcode(POC_IORLW, popGetLit(0x01));
6348       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6349     } else {
6350       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6351       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6352       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6353       emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6354       emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6355     }
6356     break;
6357     
6358   case 7:
6359     if(same) {
6360       emitpcode(POC_MOVLW, popGetLit(0x00));
6361       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6362       emitpcode(POC_MOVLW, popGetLit(0xff));
6363       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6364     } else {
6365       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6366       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6367       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6368     }
6369     
6370   default:
6371     break;
6372   }
6373 }
6374
6375 /*-----------------------------------------------------------------*/
6376 /* shiftR1Left2Result - shift right one byte from left to result   */
6377 /*-----------------------------------------------------------------*/
6378 static void shiftR1Left2Result (operand *left, int offl,
6379                 operand *result, int offr,
6380                 int shCount, int sign)
6381 {
6382   int same;
6383   
6384   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6385   
6386   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6387   
6388   /* Copy the msb into the carry if signed. */
6389   if(sign) {
6390     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6391     return;
6392   }
6393   
6394   
6395   
6396   switch(shCount) {
6397   case 1:
6398     emitCLRC;
6399     if(same) 
6400       emitpcode(POC_RRF, popGet(AOP(result),offr));
6401     else {
6402       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6403       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6404     }
6405     break;
6406   case 2:
6407     emitCLRC;
6408     if(same) {
6409       emitpcode(POC_RRF, popGet(AOP(result),offr));
6410     } else {
6411       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6412       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6413     }
6414     emitCLRC;
6415     emitpcode(POC_RRF, popGet(AOP(result),offr));
6416     
6417     break;
6418   case 3:
6419     if(same)
6420       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6421     else {
6422       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6423       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6424     }
6425     
6426     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6427     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6428     emitpcode(POC_ANDLW, popGetLit(0x1f));
6429     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6430     break;
6431     
6432   case 4:
6433     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6434     emitpcode(POC_ANDLW, popGetLit(0x0f));
6435     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6436     break;
6437     
6438   case 5:
6439     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6440     emitpcode(POC_ANDLW, popGetLit(0x0f));
6441     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6442     emitCLRC;
6443     emitpcode(POC_RRF, popGet(AOP(result),offr));
6444     
6445     break;
6446   case 6:
6447     
6448     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6449     emitpcode(POC_ANDLW, popGetLit(0x80));
6450     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6451     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6452     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6453     break;
6454     
6455   case 7:
6456     
6457     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6458     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6459     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6460     
6461     break;
6462     
6463   default:
6464     break;
6465   }
6466 }
6467
6468 /*-----------------------------------------------------------------*/
6469 /* shiftL1Left2Result - shift left one byte from left to result    */
6470 /*-----------------------------------------------------------------*/
6471 static void shiftL1Left2Result (operand *left, int offl,
6472                 operand *result, int offr, int shCount)
6473 {
6474   int same;
6475   
6476   //    char *l;
6477   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6478   
6479   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6480   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6481   //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6482   //    MOVA(l);
6483   /* shift left accumulator */
6484   //AccLsh(shCount); // don't comment out just yet...
6485   //    aopPut(AOP(result),"a",offr);
6486   
6487   switch(shCount) {
6488   case 1:
6489     /* Shift left 1 bit position */
6490     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6491     if(same) {
6492       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6493     } else {
6494       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6495       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6496     }
6497     break;
6498   case 2:
6499     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6500     emitpcode(POC_ANDLW,popGetLit(0x7e));
6501     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6502     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6503     break;
6504   case 3:
6505     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6506     emitpcode(POC_ANDLW,popGetLit(0x3e));
6507     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6508     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6509     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6510     break;
6511   case 4:
6512     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6513     emitpcode(POC_ANDLW, popGetLit(0xf0));
6514     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6515     break;
6516   case 5:
6517     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6518     emitpcode(POC_ANDLW, popGetLit(0xf0));
6519     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6520     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6521     break;
6522   case 6:
6523     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6524     emitpcode(POC_ANDLW, popGetLit(0x30));
6525     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6526     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6527     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6528     break;
6529   case 7:
6530     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6531     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6532     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6533     break;
6534     
6535   default:
6536     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6537   }
6538   
6539 }
6540
6541 /*-----------------------------------------------------------------*/
6542 /* movLeft2Result - move byte from left to result                  */
6543 /*-----------------------------------------------------------------*/
6544 static void movLeft2Result (operand *left, int offl,
6545               operand *result, int offr)
6546 {
6547   char *l;
6548   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6549   if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6550     l = aopGet(AOP(left),offl,FALSE,FALSE);
6551     
6552     if (*l == '@' && (IS_AOP_PREG(result))) {
6553       pic14_emitcode("mov","a,%s",l);
6554       aopPut(AOP(result),"a",offr);
6555     } else {
6556       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6557       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6558     }
6559   }
6560 }
6561
6562 /*-----------------------------------------------------------------*/
6563 /* shiftL2Left2Result - shift left two bytes from left to result   */
6564 /*-----------------------------------------------------------------*/
6565 static void shiftL2Left2Result (operand *left, int offl,
6566                 operand *result, int offr, int shCount)
6567 {
6568   
6569   
6570   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6571   
6572   if(pic14_sameRegs(AOP(result), AOP(left))) {
6573     switch(shCount) {
6574     case 0:
6575       break;
6576     case 1:
6577     case 2:
6578     case 3:
6579       
6580       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6581       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6582       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6583       
6584       while(--shCount) {
6585         emitCLRC;
6586         emitpcode(POC_RLF, popGet(AOP(result),offr));
6587         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6588       }
6589       
6590       break;
6591     case 4:
6592     case 5:
6593       emitpcode(POC_MOVLW, popGetLit(0x0f));
6594       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6595       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6596       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6597       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6598       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6599       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6600       if(shCount >=5) {
6601         emitpcode(POC_RLF, popGet(AOP(result),offr));
6602         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6603       }
6604       break;
6605     case 6:
6606       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6607       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6608       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6609       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6610       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6611       emitpcode(POC_ANDLW,popGetLit(0xc0));
6612       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6613       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6614       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6615       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6616       break;
6617     case 7:
6618       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6619       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6620       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6621       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6622       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6623     }
6624     
6625   } else {
6626     switch(shCount) {
6627     case 0:
6628       break;
6629     case 1:
6630     case 2:
6631     case 3:
6632     /* note, use a mov/add for the shift since the mov has a
6633       chance of getting optimized out */
6634       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6635       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6636       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6637       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6638       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6639       
6640       while(--shCount) {
6641         emitCLRC;
6642         emitpcode(POC_RLF, popGet(AOP(result),offr));
6643         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6644       }
6645       break;
6646       
6647     case 4:
6648     case 5:
6649       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6650       emitpcode(POC_ANDLW, popGetLit(0xF0));
6651       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6652       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6653       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6654       emitpcode(POC_ANDLW, popGetLit(0xF0));
6655       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6656       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6657       
6658       
6659       if(shCount == 5) {
6660         emitpcode(POC_RLF, popGet(AOP(result),offr));
6661         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6662       }
6663       break;
6664     case 6:
6665       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6666       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6667       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6668       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6669       
6670       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6671       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6672       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6673       emitpcode(POC_ANDLW,popGetLit(0xc0));
6674       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6675       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6676       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6677       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6678       break;
6679     case 7:
6680       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6681       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6682       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6683       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6684       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6685     }
6686   }
6687   
6688 }
6689 /*-----------------------------------------------------------------*/
6690 /* shiftR2Left2Result - shift right two bytes from left to result  */
6691 /*-----------------------------------------------------------------*/
6692 static void shiftR2Left2Result (operand *left, int offl,
6693                 operand *result, int offr,
6694                 int shCount, int sign)
6695 {
6696   int same=0;
6697   
6698   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6699   same = pic14_sameRegs(AOP(result), AOP(left));
6700   
6701   if(same && ((offl + MSB16) == offr)){
6702     same=1;
6703     /* don't crash result[offr] */
6704     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6705     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6706   }
6707   /* else {
6708   movLeft2Result(left,offl, result, offr);
6709   MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6710   }
6711   */
6712   /* a:x >> shCount (x = lsb(result))*/
6713   /*
6714   if(sign)
6715   AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6716   else {
6717   AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6718   */
6719   switch(shCount) {
6720   case 0:
6721     break;
6722   case 1:
6723   case 2:
6724   case 3:
6725     if(sign)
6726       emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6727     else
6728       emitCLRC;
6729     
6730     if(same) {
6731       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6732       emitpcode(POC_RRF,popGet(AOP(result),offr));
6733     } else {
6734       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6735       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6736       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6737       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6738     }
6739     
6740     while(--shCount) {
6741       if(sign)
6742         emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6743       else
6744         emitCLRC;
6745       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6746       emitpcode(POC_RRF,popGet(AOP(result),offr));
6747     }
6748     break;
6749   case 4:
6750   case 5:
6751     if(same) {
6752       
6753       emitpcode(POC_MOVLW, popGetLit(0xf0));
6754       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6755       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6756       
6757       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6758       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6759       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6760       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6761     } else {
6762       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6763       emitpcode(POC_ANDLW, popGetLit(0x0f));
6764       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6765       
6766       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6767       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6768       emitpcode(POC_ANDLW, popGetLit(0xf0));
6769       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6770       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6771     }
6772     
6773     if(shCount >=5) {
6774       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6775       emitpcode(POC_RRF, popGet(AOP(result),offr));
6776     }
6777     
6778     if(sign) {
6779       emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6780       emitpcode(POC_BTFSC, 
6781         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6782       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6783     }
6784     
6785     break;
6786     
6787   case 6:
6788     if(same) {
6789       
6790       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6791       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6792       
6793       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6794       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6795       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6796       emitpcode(POC_ANDLW,popGetLit(0x03));
6797       if(sign) {
6798         emitpcode(POC_BTFSC, 
6799           newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6800         emitpcode(POC_IORLW,popGetLit(0xfc));
6801       }
6802       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6803       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6804       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6805       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6806     } else {
6807       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6808       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6809       emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6810       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6811       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6812       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6813       emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6814       emitpcode(POC_ANDLW,popGetLit(0x03));
6815       if(sign) {
6816         emitpcode(POC_BTFSC, 
6817           newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6818         emitpcode(POC_IORLW,popGetLit(0xfc));
6819       }
6820       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6821       //emitpcode(POC_RLF,  popGet(AOP(result),offr));
6822       
6823       
6824     }
6825     
6826     break;
6827   case 7:
6828     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6829     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6830     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6831     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6832     if(sign) {
6833       emitSKPNC;
6834       emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6835     } else 
6836       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6837   }
6838 }
6839
6840
6841 /*-----------------------------------------------------------------*/
6842 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6843 /*-----------------------------------------------------------------*/
6844 static void shiftLLeftOrResult (operand *left, int offl,
6845                 operand *result, int offr, int shCount)
6846 {
6847   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6848   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6849   /* shift left accumulator */
6850   AccLsh(shCount);
6851   /* or with result */
6852   pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6853   /* back to result */
6854   aopPut(AOP(result),"a",offr);
6855 }
6856
6857 /*-----------------------------------------------------------------*/
6858 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6859 /*-----------------------------------------------------------------*/
6860 static void shiftRLeftOrResult (operand *left, int offl,
6861                 operand *result, int offr, int shCount)
6862 {
6863   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6864   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6865   /* shift right accumulator */
6866   AccRsh(shCount);
6867   /* or with result */
6868   pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6869   /* back to result */
6870   aopPut(AOP(result),"a",offr);
6871 }
6872
6873 /*-----------------------------------------------------------------*/
6874 /* genlshOne - left shift a one byte quantity by known count       */
6875 /*-----------------------------------------------------------------*/
6876 static void genlshOne (operand *result, operand *left, int shCount)
6877 {       
6878   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6879   shiftL1Left2Result(left, LSB, result, LSB, shCount);
6880 }
6881
6882 /*-----------------------------------------------------------------*/
6883 /* genlshTwo - left shift two bytes by known amount != 0           */
6884 /*-----------------------------------------------------------------*/
6885 static void genlshTwo (operand *result,operand *left, int shCount)
6886 {
6887   int size;
6888   
6889   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6890   size = pic14_getDataSize(result);
6891   
6892   /* if shCount >= 8 */
6893   if (shCount >= 8) {
6894     shCount -= 8 ;
6895     
6896     if (size > 1){
6897       if (shCount)
6898         shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6899       else 
6900         movLeft2Result(left, LSB, result, MSB16);
6901     }
6902     emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6903   }
6904   
6905   /*  1 <= shCount <= 7 */
6906   else {  
6907     if(size == 1)
6908       shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6909     else 
6910       shiftL2Left2Result(left, LSB, result, LSB, shCount);
6911   }
6912 }
6913
6914 /*-----------------------------------------------------------------*/
6915 /* shiftLLong - shift left one long from left to result            */
6916 /* offl = LSB or MSB16                                             */
6917 /*-----------------------------------------------------------------*/
6918 static void shiftLLong (operand *left, operand *result, int offr )
6919 {
6920   char *l;
6921   int size = AOP_SIZE(result);
6922   
6923   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6924   if(size >= LSB+offr){
6925     l = aopGet(AOP(left),LSB,FALSE,FALSE);
6926     MOVA(l);
6927     pic14_emitcode("add","a,acc");
6928     if (pic14_sameRegs(AOP(left),AOP(result)) && 
6929       size >= MSB16+offr && offr != LSB )
6930       pic14_emitcode("xch","a,%s",
6931       aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6932     else      
6933       aopPut(AOP(result),"a",LSB+offr);
6934   }
6935   
6936   if(size >= MSB16+offr){
6937     if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6938       l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6939       MOVA(l);
6940     }
6941     pic14_emitcode("rlc","a");
6942     if (pic14_sameRegs(AOP(left),AOP(result)) && 
6943       size >= MSB24+offr && offr != LSB)
6944       pic14_emitcode("xch","a,%s",
6945       aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6946     else      
6947       aopPut(AOP(result),"a",MSB16+offr);
6948   }
6949   
6950   if(size >= MSB24+offr){
6951     if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6952       l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6953       MOVA(l);
6954     }
6955     pic14_emitcode("rlc","a");
6956     if (pic14_sameRegs(AOP(left),AOP(result)) && 
6957       size >= MSB32+offr && offr != LSB )
6958       pic14_emitcode("xch","a,%s",
6959       aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6960     else      
6961       aopPut(AOP(result),"a",MSB24+offr);
6962   }
6963   
6964   if(size > MSB32+offr){
6965     if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6966       l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6967       MOVA(l);  
6968     }
6969     pic14_emitcode("rlc","a");
6970     aopPut(AOP(result),"a",MSB32+offr);
6971   }
6972   if(offr != LSB)
6973     aopPut(AOP(result),zero,LSB);       
6974 }
6975
6976 /*-----------------------------------------------------------------*/
6977 /* genlshFour - shift four byte by a known amount != 0             */
6978 /*-----------------------------------------------------------------*/
6979 static void genlshFour (operand *result, operand *left, int shCount)
6980 {
6981   int size;
6982   
6983   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6984   size = AOP_SIZE(result);
6985   
6986   /* if shifting more that 3 bytes */
6987   if (shCount >= 24 ) {
6988     shCount -= 24;
6989     if (shCount)
6990     /* lowest order of left goes to the highest
6991     order of the destination */
6992     shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6993     else
6994       movLeft2Result(left, LSB, result, MSB32);
6995     aopPut(AOP(result),zero,LSB);
6996     aopPut(AOP(result),zero,MSB16);
6997     aopPut(AOP(result),zero,MSB32);
6998     return;
6999   }
7000   
7001   /* more than two bytes */
7002   else if ( shCount >= 16 ) {
7003     /* lower order two bytes goes to higher order two bytes */
7004     shCount -= 16;
7005     /* if some more remaining */
7006     if (shCount)
7007       shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7008     else {
7009       movLeft2Result(left, MSB16, result, MSB32);
7010       movLeft2Result(left, LSB, result, MSB24);
7011     }
7012     aopPut(AOP(result),zero,MSB16);
7013     aopPut(AOP(result),zero,LSB);
7014     return;
7015   }    
7016   
7017   /* if more than 1 byte */
7018   else if ( shCount >= 8 ) {
7019     /* lower order three bytes goes to higher order  three bytes */
7020     shCount -= 8;
7021     if(size == 2){
7022       if(shCount)
7023         shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7024       else
7025         movLeft2Result(left, LSB, result, MSB16);
7026     }
7027     else{   /* size = 4 */
7028       if(shCount == 0){
7029         movLeft2Result(left, MSB24, result, MSB32);
7030         movLeft2Result(left, MSB16, result, MSB24);
7031         movLeft2Result(left, LSB, result, MSB16);
7032         aopPut(AOP(result),zero,LSB);
7033       }
7034       else if(shCount == 1)
7035         shiftLLong(left, result, MSB16);
7036       else{
7037         shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7038         shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7039         shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7040         aopPut(AOP(result),zero,LSB);
7041       }
7042     }
7043   }
7044   
7045   /* 1 <= shCount <= 7 */
7046   else if(shCount <= 2){
7047     shiftLLong(left, result, LSB);
7048     if(shCount == 2)
7049       shiftLLong(result, result, LSB);
7050   }
7051   /* 3 <= shCount <= 7, optimize */
7052   else{
7053     shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7054     shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7055     shiftL2Left2Result(left, LSB, result, LSB, shCount);
7056   }
7057 }
7058
7059 /*-----------------------------------------------------------------*/
7060 /* genLeftShiftLiteral - left shifting by known count              */
7061 /*-----------------------------------------------------------------*/
7062 static void genLeftShiftLiteral (operand *left,
7063                  operand *right,
7064                  operand *result,
7065                  iCode *ic)
7066 {    
7067   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7068   int size;
7069   
7070   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7071   freeAsmop(right,NULL,ic,TRUE);
7072   
7073   aopOp(left,ic,FALSE);
7074   aopOp(result,ic,FALSE);
7075   
7076   size = getSize(operandType(result));
7077   
7078 #if VIEW_SIZE
7079   pic14_emitcode("; shift left ","result %d, left %d",size,
7080     AOP_SIZE(left));
7081 #endif
7082   
7083   /* I suppose that the left size >= result size */
7084   if(shCount == 0){
7085     while(size--){
7086       movLeft2Result(left, size, result, size);
7087     }
7088   }
7089   
7090   else if(shCount >= (size * 8))
7091     while(size--)
7092       aopPut(AOP(result),zero,size);
7093     else{
7094       switch (size) {
7095       case 1:
7096         genlshOne (result,left,shCount);
7097         break;
7098         
7099       case 2:
7100       case 3:
7101         genlshTwo (result,left,shCount);
7102         break;
7103         
7104       case 4:
7105         genlshFour (result,left,shCount);
7106         break;
7107       }
7108     }
7109     freeAsmop(left,NULL,ic,TRUE);
7110     freeAsmop(result,NULL,ic,TRUE);
7111 }
7112
7113 /*-----------------------------------------------------------------*
7114 * genMultiAsm - repeat assembly instruction for size of register.
7115 * if endian == 1, then the high byte (i.e base address + size of 
7116 * register) is used first else the low byte is used first;
7117 *-----------------------------------------------------------------*/
7118 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7119 {
7120   
7121   int offset = 0;
7122   
7123   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7124   
7125   if(!reg)
7126     return;
7127   
7128   if(!endian) {
7129     endian = 1;
7130   } else {
7131     endian = -1;
7132     offset = size-1;
7133   }
7134   
7135   while(size--) {
7136     emitpcode(poc,    popGet(AOP(reg),offset));
7137     offset += endian;
7138   }
7139   
7140 }
7141 /*-----------------------------------------------------------------*/
7142 /* genLeftShift - generates code for left shifting                 */
7143 /*-----------------------------------------------------------------*/
7144 static void genLeftShift (iCode *ic)
7145 {
7146   operand *left,*right, *result;
7147   int size, offset;
7148   char *l;
7149   symbol *tlbl , *tlbl1;
7150   pCodeOp *pctemp;
7151   
7152   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7153   
7154   right = IC_RIGHT(ic);
7155   left  = IC_LEFT(ic);
7156   result = IC_RESULT(ic);
7157   
7158   aopOp(right,ic,FALSE);
7159   
7160   /* if the shift count is known then do it 
7161   as efficiently as possible */
7162   if (AOP_TYPE(right) == AOP_LIT) {
7163     genLeftShiftLiteral (left,right,result,ic);
7164     return ;
7165   }
7166   
7167   /* shift count is unknown then we have to form 
7168   a loop get the loop count in B : Note: we take
7169   only the lower order byte since shifting
7170   more that 32 bits make no sense anyway, ( the
7171   largest size of an object can be only 32 bits ) */  
7172   
7173   
7174   aopOp(left,ic,FALSE);
7175   aopOp(result,ic,FALSE);
7176   
7177   /* now move the left to the result if they are not the
7178   same */
7179   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7180     AOP_SIZE(result) > 1) {
7181     
7182     size = AOP_SIZE(result);
7183     offset=0;
7184     while (size--) {
7185       l = aopGet(AOP(left),offset,FALSE,TRUE);
7186       if (*l == '@' && (IS_AOP_PREG(result))) {
7187         
7188         pic14_emitcode("mov","a,%s",l);
7189         aopPut(AOP(result),"a",offset);
7190       } else {
7191         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7192         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7193         //aopPut(AOP(result),l,offset);
7194       }
7195       offset++;
7196     }
7197   }
7198   
7199   size = AOP_SIZE(result);
7200   
7201   /* if it is only one byte then */
7202   if (size == 1) {
7203     if(optimized_for_speed) {
7204       emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7205       emitpcode(POC_ANDLW,  popGetLit(0xf0));
7206       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7207       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7208       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7209       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7210       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7211       emitpcode(POC_RLFW,   popGet(AOP(result),0));
7212       emitpcode(POC_ANDLW,  popGetLit(0xfe));
7213       emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7214       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7215       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7216     } else {
7217       
7218       tlbl = newiTempLabel(NULL);
7219       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7220         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7221         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7222       }
7223       
7224       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7225       emitpcode(POC_RRF,    popGet(AOP(result),0));
7226       emitpLabel(tlbl->key);
7227       emitpcode(POC_RLF,    popGet(AOP(result),0));
7228       emitpcode(POC_ADDLW,  popGetLit(1));
7229       emitSKPC;
7230       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7231     }
7232     goto release ;
7233   }
7234   
7235   if (pic14_sameRegs(AOP(left),AOP(result))) {
7236     
7237     tlbl = newiTempLabel(NULL);
7238     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7239     genMultiAsm(POC_RRF, result, size,1);
7240     emitpLabel(tlbl->key);
7241     genMultiAsm(POC_RLF, result, size,0);
7242     emitpcode(POC_ADDLW,  popGetLit(1));
7243     emitSKPC;
7244     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7245     goto release;
7246   }
7247   
7248   //tlbl = newiTempLabel(NULL);
7249   //offset = 0 ;   
7250   //tlbl1 = newiTempLabel(NULL);
7251   
7252   //reAdjustPreg(AOP(result));    
7253   
7254   //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7255   //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7256   //l = aopGet(AOP(result),offset,FALSE,FALSE);
7257   //MOVA(l);
7258   //pic14_emitcode("add","a,acc");         
7259   //aopPut(AOP(result),"a",offset++);
7260   //while (--size) {
7261   //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7262   //  MOVA(l);
7263   //  pic14_emitcode("rlc","a");         
7264   //  aopPut(AOP(result),"a",offset++);
7265   //}
7266   //reAdjustPreg(AOP(result));
7267   
7268   //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7269   //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7270   
7271   
7272   tlbl = newiTempLabel(NULL);
7273   tlbl1= newiTempLabel(NULL);
7274   
7275   size = AOP_SIZE(result);
7276   offset = 1;
7277   
7278   pctemp = popGetTempReg();  /* grab a temporary working register. */
7279   
7280   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7281   
7282   /* offset should be 0, 1 or 3 */
7283   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7284   emitSKPNZ;
7285   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7286   
7287   emitpcode(POC_MOVWF, pctemp);
7288   
7289   
7290   emitpLabel(tlbl->key);
7291   
7292   emitCLRC;
7293   emitpcode(POC_RLF,  popGet(AOP(result),0));
7294   while(--size)
7295     emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7296   
7297   emitpcode(POC_DECFSZ,  pctemp);
7298   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7299   emitpLabel(tlbl1->key);
7300   
7301   popReleaseTempReg(pctemp);
7302   
7303   
7304 release:
7305   freeAsmop (right,NULL,ic,TRUE);
7306   freeAsmop(left,NULL,ic,TRUE);
7307   freeAsmop(result,NULL,ic,TRUE);
7308 }
7309
7310 /*-----------------------------------------------------------------*/
7311 /* genrshOne - right shift a one byte quantity by known count      */
7312 /*-----------------------------------------------------------------*/
7313 static void genrshOne (operand *result, operand *left,
7314              int shCount, int sign)
7315 {
7316   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7317   shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7318 }
7319
7320 /*-----------------------------------------------------------------*/
7321 /* genrshTwo - right shift two bytes by known amount != 0          */
7322 /*-----------------------------------------------------------------*/
7323 static void genrshTwo (operand *result,operand *left,
7324              int shCount, int sign)
7325 {
7326   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7327   /* if shCount >= 8 */
7328   if (shCount >= 8) {
7329     shCount -= 8 ;
7330     if (shCount)
7331       shiftR1Left2Result(left, MSB16, result, LSB,
7332       shCount, sign);
7333     else
7334       movLeft2Result(left, MSB16, result, LSB);
7335     
7336     emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7337     
7338     if(sign) {
7339       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7340       emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7341     }
7342   }
7343   
7344   /*  1 <= shCount <= 7 */
7345   else
7346     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7347 }
7348
7349 /*-----------------------------------------------------------------*/
7350 /* shiftRLong - shift right one long from left to result           */
7351 /* offl = LSB or MSB16                                             */
7352 /*-----------------------------------------------------------------*/
7353 static void shiftRLong (operand *left, int offl,
7354             operand *result, int sign)
7355 {
7356   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7357   if(!sign)
7358     pic14_emitcode("clr","c");
7359   MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7360   if(sign)
7361     pic14_emitcode("mov","c,acc.7");
7362   pic14_emitcode("rrc","a");
7363   aopPut(AOP(result),"a",MSB32-offl);
7364   if(offl == MSB16)
7365     /* add sign of "a" */
7366     addSign(result, MSB32, sign);
7367   
7368   MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7369   pic14_emitcode("rrc","a");
7370   aopPut(AOP(result),"a",MSB24-offl);
7371   
7372   MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7373   pic14_emitcode("rrc","a");
7374   aopPut(AOP(result),"a",MSB16-offl);
7375   
7376   if(offl == LSB){
7377     MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7378     pic14_emitcode("rrc","a");
7379     aopPut(AOP(result),"a",LSB);
7380   }
7381 }
7382
7383 /*-----------------------------------------------------------------*/
7384 /* genrshFour - shift four byte by a known amount != 0             */
7385 /*-----------------------------------------------------------------*/
7386 static void genrshFour (operand *result, operand *left,
7387             int shCount, int sign)
7388 {
7389   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7390   /* if shifting more that 3 bytes */
7391   if(shCount >= 24 ) {
7392     shCount -= 24;
7393     if(shCount)
7394       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7395     else
7396       movLeft2Result(left, MSB32, result, LSB);
7397     
7398     addSign(result, MSB16, sign);
7399   }
7400   else if(shCount >= 16){
7401     shCount -= 16;
7402     if(shCount)
7403       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7404     else{
7405       movLeft2Result(left, MSB24, result, LSB);
7406       movLeft2Result(left, MSB32, result, MSB16);
7407     }
7408     addSign(result, MSB24, sign);
7409   }
7410   else if(shCount >= 8){
7411     shCount -= 8;
7412     if(shCount == 1)
7413       shiftRLong(left, MSB16, result, sign);
7414     else if(shCount == 0){
7415       movLeft2Result(left, MSB16, result, LSB);
7416       movLeft2Result(left, MSB24, result, MSB16);
7417       movLeft2Result(left, MSB32, result, MSB24);
7418       addSign(result, MSB32, sign);
7419     }
7420     else{
7421       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7422       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7423       /* the last shift is signed */
7424       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7425       addSign(result, MSB32, sign);
7426     }
7427   }
7428   else{   /* 1 <= shCount <= 7 */
7429     if(shCount <= 2){
7430       shiftRLong(left, LSB, result, sign);
7431       if(shCount == 2)
7432         shiftRLong(result, LSB, result, sign);
7433     }
7434     else{
7435       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7436       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7437       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7438     }
7439   }
7440 }
7441
7442 /*-----------------------------------------------------------------*/
7443 /* genRightShiftLiteral - right shifting by known count            */
7444 /*-----------------------------------------------------------------*/
7445 static void genRightShiftLiteral (operand *left,
7446                   operand *right,
7447                   operand *result,
7448                   iCode *ic,
7449                   int sign)
7450 {    
7451   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7452   int lsize,res_size;
7453   
7454   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7455   freeAsmop(right,NULL,ic,TRUE);
7456   
7457   aopOp(left,ic,FALSE);
7458   aopOp(result,ic,FALSE);
7459   
7460 #if VIEW_SIZE
7461   pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7462     AOP_SIZE(left));
7463 #endif
7464   
7465   lsize = pic14_getDataSize(left);
7466   res_size = pic14_getDataSize(result);
7467   /* test the LEFT size !!! */
7468   
7469   /* I suppose that the left size >= result size */
7470   if(shCount == 0){
7471     while(res_size--)
7472       movLeft2Result(left, lsize, result, res_size);
7473   }
7474   
7475   else if(shCount >= (lsize * 8)){
7476     
7477     if(res_size == 1) {
7478       emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7479       if(sign) {
7480         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7481         emitpcode(POC_DECF, popGet(AOP(result),LSB));
7482       }
7483     } else {
7484       
7485       if(sign) {
7486         emitpcode(POC_MOVLW, popGetLit(0));
7487         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7488         emitpcode(POC_MOVLW, popGetLit(0xff));
7489         while(res_size--)
7490           emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7491         
7492       } else {
7493         
7494         while(res_size--)
7495           emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7496       }
7497     }
7498   } else {
7499     
7500     switch (res_size) {
7501     case 1:
7502       genrshOne (result,left,shCount,sign);
7503       break;
7504       
7505     case 2:
7506       genrshTwo (result,left,shCount,sign);
7507       break;
7508       
7509     case 4:
7510       genrshFour (result,left,shCount,sign);
7511       break;
7512     default :
7513       break;
7514     }
7515     
7516   }
7517   
7518   freeAsmop(left,NULL,ic,TRUE);
7519   freeAsmop(result,NULL,ic,TRUE);
7520 }
7521
7522 /*-----------------------------------------------------------------*/
7523 /* genSignedRightShift - right shift of signed number              */
7524 /*-----------------------------------------------------------------*/
7525 static void genSignedRightShift (iCode *ic)
7526 {
7527   operand *right, *left, *result;
7528   int size, offset;
7529   //  char *l;
7530   symbol *tlbl, *tlbl1 ;
7531   pCodeOp *pctemp;
7532   
7533   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7534   
7535   /* we do it the hard way put the shift count in b
7536   and loop thru preserving the sign */
7537   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7538   
7539   right = IC_RIGHT(ic);
7540   left  = IC_LEFT(ic);
7541   result = IC_RESULT(ic);
7542   
7543   aopOp(right,ic,FALSE);  
7544   aopOp(left,ic,FALSE);
7545   aopOp(result,ic,FALSE);
7546   
7547   
7548   if ( AOP_TYPE(right) == AOP_LIT) {
7549     genRightShiftLiteral (left,right,result,ic,1);
7550     return ;
7551   }
7552   /* shift count is unknown then we have to form 
7553   a loop get the loop count in B : Note: we take
7554   only the lower order byte since shifting
7555   more that 32 bits make no sense anyway, ( the
7556   largest size of an object can be only 32 bits ) */  
7557   
7558   //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7559   //pic14_emitcode("inc","b");
7560   //freeAsmop (right,NULL,ic,TRUE);
7561   //aopOp(left,ic,FALSE);
7562   //aopOp(result,ic,FALSE);
7563   
7564   /* now move the left to the result if they are not the
7565   same */
7566   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7567     AOP_SIZE(result) > 1) {
7568     
7569     size = AOP_SIZE(result);
7570     offset=0;
7571     while (size--) { 
7572     /*
7573     l = aopGet(AOP(left),offset,FALSE,TRUE);
7574     if (*l == '@' && IS_AOP_PREG(result)) {
7575     
7576       pic14_emitcode("mov","a,%s",l);
7577       aopPut(AOP(result),"a",offset);
7578       } else
7579       aopPut(AOP(result),l,offset);
7580       */
7581       emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7582       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7583       
7584       offset++;
7585     }
7586   }
7587   
7588   /* mov the highest order bit to OVR */    
7589   tlbl = newiTempLabel(NULL);
7590   tlbl1= newiTempLabel(NULL);
7591   
7592   size = AOP_SIZE(result);
7593   offset = size - 1;
7594   
7595   pctemp = popGetTempReg();  /* grab a temporary working register. */
7596   
7597   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7598   
7599   /* offset should be 0, 1 or 3 */
7600   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7601   emitSKPNZ;
7602   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7603   
7604   emitpcode(POC_MOVWF, pctemp);
7605   
7606   
7607   emitpLabel(tlbl->key);
7608   
7609   emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7610   emitpcode(POC_RRF,   popGet(AOP(result),offset));
7611   
7612   while(--size) {
7613     emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7614   }
7615   
7616   emitpcode(POC_DECFSZ,  pctemp);
7617   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7618   emitpLabel(tlbl1->key);
7619   
7620   popReleaseTempReg(pctemp);
7621 #if 0
7622   size = AOP_SIZE(result);
7623   offset = size - 1;
7624   pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7625   pic14_emitcode("rlc","a");
7626   pic14_emitcode("mov","ov,c");
7627   /* if it is only one byte then */
7628   if (size == 1) {
7629     l = aopGet(AOP(left),0,FALSE,FALSE);
7630     MOVA(l);
7631     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7632     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7633     pic14_emitcode("mov","c,ov");
7634     pic14_emitcode("rrc","a");
7635     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7636     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7637     aopPut(AOP(result),"a",0);
7638     goto release ;
7639   }
7640   
7641   reAdjustPreg(AOP(result));
7642   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7643   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7644   pic14_emitcode("mov","c,ov");
7645   while (size--) {
7646     l = aopGet(AOP(result),offset,FALSE,FALSE);
7647     MOVA(l);
7648     pic14_emitcode("rrc","a");         
7649     aopPut(AOP(result),"a",offset--);
7650   }
7651   reAdjustPreg(AOP(result));
7652   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7653   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7654   
7655 release:
7656 #endif
7657   
7658   freeAsmop(left,NULL,ic,TRUE);
7659   freeAsmop(result,NULL,ic,TRUE);
7660   freeAsmop(right,NULL,ic,TRUE);
7661 }
7662
7663 /*-----------------------------------------------------------------*/
7664 /* genRightShift - generate code for right shifting                */
7665 /*-----------------------------------------------------------------*/
7666 static void genRightShift (iCode *ic)
7667 {
7668   operand *right, *left, *result;
7669   sym_link *retype ;
7670   int size, offset;
7671   char *l;
7672   symbol *tlbl, *tlbl1 ;
7673   
7674   /* if signed then we do it the hard way preserve the
7675   sign bit moving it inwards */
7676   retype = getSpec(operandType(IC_RESULT(ic)));
7677   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7678   
7679   if (!SPEC_USIGN(retype)) {
7680     genSignedRightShift (ic);
7681     return ;
7682   }
7683   
7684   /* signed & unsigned types are treated the same : i.e. the
7685   signed is NOT propagated inwards : quoting from the
7686   ANSI - standard : "for E1 >> E2, is equivalent to division
7687   by 2**E2 if unsigned or if it has a non-negative value,
7688   otherwise the result is implementation defined ", MY definition
7689   is that the sign does not get propagated */
7690   
7691   right = IC_RIGHT(ic);
7692   left  = IC_LEFT(ic);
7693   result = IC_RESULT(ic);
7694   
7695   aopOp(right,ic,FALSE);
7696   
7697   /* if the shift count is known then do it 
7698   as efficiently as possible */
7699   if (AOP_TYPE(right) == AOP_LIT) {
7700     genRightShiftLiteral (left,right,result,ic, 0);
7701     return ;
7702   }
7703   
7704   /* shift count is unknown then we have to form 
7705   a loop get the loop count in B : Note: we take
7706   only the lower order byte since shifting
7707   more that 32 bits make no sense anyway, ( the
7708   largest size of an object can be only 32 bits ) */  
7709   
7710   pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7711   pic14_emitcode("inc","b");
7712   aopOp(left,ic,FALSE);
7713   aopOp(result,ic,FALSE);
7714   
7715   /* now move the left to the result if they are not the
7716   same */
7717   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7718     AOP_SIZE(result) > 1) {
7719     
7720     size = AOP_SIZE(result);
7721     offset=0;
7722     while (size--) {
7723       l = aopGet(AOP(left),offset,FALSE,TRUE);
7724       if (*l == '@' && IS_AOP_PREG(result)) {
7725         
7726         pic14_emitcode("mov","a,%s",l);
7727         aopPut(AOP(result),"a",offset);
7728       } else
7729         aopPut(AOP(result),l,offset);
7730       offset++;
7731     }
7732   }
7733   
7734   tlbl = newiTempLabel(NULL);
7735   tlbl1= newiTempLabel(NULL);
7736   size = AOP_SIZE(result);
7737   offset = size - 1;
7738   
7739   /* if it is only one byte then */
7740   if (size == 1) {
7741     
7742     tlbl = newiTempLabel(NULL);
7743     if (!pic14_sameRegs(AOP(left),AOP(result))) {
7744       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7745       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7746     }
7747     
7748     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7749     emitpcode(POC_RLF,    popGet(AOP(result),0));
7750     emitpLabel(tlbl->key);
7751     emitpcode(POC_RRF,    popGet(AOP(result),0));
7752     emitpcode(POC_ADDLW,  popGetLit(1));
7753     emitSKPC;
7754     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7755     
7756     goto release ;
7757   }
7758   
7759   reAdjustPreg(AOP(result));
7760   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7761   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7762   CLRC;
7763   while (size--) {
7764     l = aopGet(AOP(result),offset,FALSE,FALSE);
7765     MOVA(l);
7766     pic14_emitcode("rrc","a");         
7767     aopPut(AOP(result),"a",offset--);
7768   }
7769   reAdjustPreg(AOP(result));
7770   
7771   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7772   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7773   
7774 release:
7775   freeAsmop(left,NULL,ic,TRUE);
7776   freeAsmop (right,NULL,ic,TRUE);
7777   freeAsmop(result,NULL,ic,TRUE);
7778 }
7779
7780 /*-----------------------------------------------------------------*/
7781 /* genUnpackBits - generates code for unpacking bits               */
7782 /*-----------------------------------------------------------------*/
7783 static void genUnpackBits (operand *result, char *rname, int ptype)
7784 {    
7785   int shCnt ;
7786   int rlen = 0 ;
7787   sym_link *etype;
7788   int offset = 0 ;
7789   
7790   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7791   etype = getSpec(operandType(result));
7792   
7793   /* read the first byte  */
7794   switch (ptype) {
7795     
7796   case POINTER:
7797   case IPOINTER:
7798     pic14_emitcode("mov","a,@%s",rname);
7799     break;
7800     
7801   case PPOINTER:
7802     pic14_emitcode("movx","a,@%s",rname);
7803     break;
7804     
7805   case FPOINTER:
7806     pic14_emitcode("movx","a,@dptr");
7807     break;
7808     
7809   case CPOINTER:
7810     pic14_emitcode("clr","a");
7811     pic14_emitcode("movc","a","@a+dptr");
7812     break;
7813     
7814   case GPOINTER:
7815     pic14_emitcode("lcall","__gptrget");
7816     break;
7817   }
7818   
7819   /* if we have bitdisplacement then it fits   */
7820   /* into this byte completely or if length is */
7821   /* less than a byte                          */
7822   if ((shCnt = SPEC_BSTR(etype)) || 
7823     (SPEC_BLEN(etype) <= 8))  {
7824     
7825     /* shift right acc */
7826     AccRsh(shCnt);
7827     
7828     pic14_emitcode("anl","a,#0x%02x",
7829       ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7830     aopPut(AOP(result),"a",offset);
7831     return ;
7832   }
7833   
7834   /* bit field did not fit in a byte  */
7835   rlen = SPEC_BLEN(etype) - 8;
7836   aopPut(AOP(result),"a",offset++);
7837   
7838   while (1)  {
7839     
7840     switch (ptype) {
7841     case POINTER:
7842     case IPOINTER:
7843       pic14_emitcode("inc","%s",rname);
7844       pic14_emitcode("mov","a,@%s",rname);
7845       break;
7846       
7847     case PPOINTER:
7848       pic14_emitcode("inc","%s",rname);
7849       pic14_emitcode("movx","a,@%s",rname);
7850       break;
7851       
7852     case FPOINTER:
7853       pic14_emitcode("inc","dptr");
7854       pic14_emitcode("movx","a,@dptr");
7855       break;
7856       
7857     case CPOINTER:
7858       pic14_emitcode("clr","a");
7859       pic14_emitcode("inc","dptr");
7860       pic14_emitcode("movc","a","@a+dptr");
7861       break;
7862       
7863     case GPOINTER:
7864       pic14_emitcode("inc","dptr");
7865       pic14_emitcode("lcall","__gptrget");
7866       break;
7867     }
7868     
7869     rlen -= 8;            
7870     /* if we are done */
7871     if ( rlen <= 0 )
7872       break ;
7873     
7874     aopPut(AOP(result),"a",offset++);
7875     
7876   }
7877   
7878   if (rlen) {
7879     pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7880     aopPut(AOP(result),"a",offset);        
7881   }
7882   
7883   return ;
7884 }
7885
7886 #if 0
7887 /*-----------------------------------------------------------------*/
7888 /* genDataPointerGet - generates code when ptr offset is known     */
7889 /*-----------------------------------------------------------------*/
7890 static void genDataPointerGet (operand *left, 
7891                  operand *result, 
7892                  iCode *ic)
7893 {
7894   int size , offset = 0;
7895   
7896   
7897   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7898   
7899   
7900   /* optimization - most of the time, left and result are the same
7901   * address, but different types. for the pic code, we could omit
7902   * the following
7903   */
7904   
7905   aopOp(result,ic,TRUE);
7906   
7907   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7908   
7909   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7910   
7911   size = AOP_SIZE(result);
7912   
7913   while (size--) {
7914     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7915     offset++;
7916   }
7917   
7918   freeAsmop(left,NULL,ic,TRUE);
7919   freeAsmop(result,NULL,ic,TRUE);
7920 }
7921 #endif
7922 /*-----------------------------------------------------------------*/
7923 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7924 /*-----------------------------------------------------------------*/
7925 static void genNearPointerGet (operand *left, 
7926                  operand *result, 
7927                  iCode *ic)
7928 {
7929   asmop *aop = NULL;
7930   //regs *preg = NULL ;
7931   char *rname ;
7932   sym_link *rtype, *retype;
7933   sym_link *ltype = operandType(left);    
7934   //char buffer[80];
7935   
7936   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7937   
7938   rtype = operandType(result);
7939   retype= getSpec(rtype);
7940   
7941   aopOp(left,ic,FALSE);
7942   
7943   /* if left is rematerialisable and
7944   result is not bit variable type and
7945   the left is pointer to data space i.e
7946   lower 128 bytes of space */
7947   if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
7948     !IS_BITVAR(retype)         &&
7949     DCL_TYPE(ltype) == POINTER) {
7950     //genDataPointerGet (left,result,ic);
7951     return ;
7952   }
7953   
7954   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7955   
7956   /* if the value is already in a pointer register
7957   then don't need anything more */
7958   if (!AOP_INPREG(AOP(left))) {
7959     /* otherwise get a free pointer register */
7960     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7961     /*
7962     aop = newAsmop(0);
7963     preg = getFreePtr(ic,&aop,FALSE);
7964     pic14_emitcode("mov","%s,%s",
7965     preg->name,
7966     aopGet(AOP(left),0,FALSE,TRUE));
7967     rname = preg->name ;
7968     */
7969     rname ="BAD";
7970   } else
7971     rname = aopGet(AOP(left),0,FALSE,FALSE);
7972   
7973   aopOp (result,ic,FALSE);
7974   
7975   /* if bitfield then unpack the bits */
7976   if (IS_BITFIELD(retype)) 
7977     genUnpackBits (result,rname,POINTER);
7978   else {
7979     /* we have can just get the values */
7980     int size = AOP_SIZE(result);
7981     int offset = 0 ;  
7982     
7983     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7984     
7985     emitpcode(POC_MOVFW,popGet(AOP(left),0));
7986     emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7987     while(size--) {
7988       emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7989       emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
7990       if(size)
7991         emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7992     }
7993     /*
7994     while (size--) {
7995     if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7996
7997       pic14_emitcode("mov","a,@%s",rname);
7998       aopPut(AOP(result),"a",offset);
7999       } else {
8000       sprintf(buffer,"@%s",rname);
8001       aopPut(AOP(result),buffer,offset);
8002       }
8003       offset++ ;
8004       if (size)
8005       pic14_emitcode("inc","%s",rname);
8006     }
8007     */
8008   }
8009   
8010   /* now some housekeeping stuff */
8011   if (aop) {
8012     /* we had to allocate for this iCode */
8013     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8014     freeAsmop(NULL,aop,ic,TRUE);
8015   } else { 
8016   /* we did not allocate which means left
8017      already in a pointer register, then
8018      if size > 0 && this could be used again
8019      we have to point it back to where it 
8020     belongs */
8021     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8022     if (AOP_SIZE(result) > 1 &&
8023       !OP_SYMBOL(left)->remat &&
8024       ( OP_SYMBOL(left)->liveTo > ic->seq ||
8025       ic->depth )) {
8026       int size = AOP_SIZE(result) - 1;
8027       while (size--)
8028         pic14_emitcode("dec","%s",rname);
8029     }
8030   }
8031   
8032   /* done */
8033   freeAsmop(left,NULL,ic,TRUE);
8034   freeAsmop(result,NULL,ic,TRUE);
8035   
8036 }
8037
8038 /*-----------------------------------------------------------------*/
8039 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8040 /*-----------------------------------------------------------------*/
8041 static void genPagedPointerGet (operand *left, 
8042                 operand *result, 
8043                 iCode *ic)
8044 {
8045   asmop *aop = NULL;
8046   regs *preg = NULL ;
8047   char *rname ;
8048   sym_link *rtype, *retype;    
8049   
8050   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8051   
8052   rtype = operandType(result);
8053   retype= getSpec(rtype);
8054   
8055   aopOp(left,ic,FALSE);
8056   
8057   /* if the value is already in a pointer register
8058   then don't need anything more */
8059   if (!AOP_INPREG(AOP(left))) {
8060     /* otherwise get a free pointer register */
8061     aop = newAsmop(0);
8062     preg = getFreePtr(ic,&aop,FALSE);
8063     pic14_emitcode("mov","%s,%s",
8064       preg->name,
8065       aopGet(AOP(left),0,FALSE,TRUE));
8066     rname = preg->name ;
8067   } else
8068     rname = aopGet(AOP(left),0,FALSE,FALSE);
8069   
8070   freeAsmop(left,NULL,ic,TRUE);
8071   aopOp (result,ic,FALSE);
8072   
8073   /* if bitfield then unpack the bits */
8074   if (IS_BITFIELD(retype)) 
8075     genUnpackBits (result,rname,PPOINTER);
8076   else {
8077     /* we have can just get the values */
8078     int size = AOP_SIZE(result);
8079     int offset = 0 ;  
8080     
8081     while (size--) {
8082       
8083       pic14_emitcode("movx","a,@%s",rname);
8084       aopPut(AOP(result),"a",offset);
8085       
8086       offset++ ;
8087       
8088       if (size)
8089         pic14_emitcode("inc","%s",rname);
8090     }
8091   }
8092   
8093   /* now some housekeeping stuff */
8094   if (aop) {
8095     /* we had to allocate for this iCode */
8096     freeAsmop(NULL,aop,ic,TRUE);
8097   } else { 
8098   /* we did not allocate which means left
8099      already in a pointer register, then
8100      if size > 0 && this could be used again
8101      we have to point it back to where it 
8102     belongs */
8103     if (AOP_SIZE(result) > 1 &&
8104       !OP_SYMBOL(left)->remat &&
8105       ( OP_SYMBOL(left)->liveTo > ic->seq ||
8106       ic->depth )) {
8107       int size = AOP_SIZE(result) - 1;
8108       while (size--)
8109         pic14_emitcode("dec","%s",rname);
8110     }
8111   }
8112   
8113   /* done */
8114   freeAsmop(result,NULL,ic,TRUE);
8115   
8116   
8117 }
8118
8119 /*-----------------------------------------------------------------*/
8120 /* genFarPointerGet - gget value from far space                    */
8121 /*-----------------------------------------------------------------*/
8122 static void genFarPointerGet (operand *left,
8123                 operand *result, iCode *ic)
8124 {
8125   int size, offset ;
8126   sym_link *retype = getSpec(operandType(result));
8127   
8128   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8129   
8130   aopOp(left,ic,FALSE);
8131   
8132   /* if the operand is already in dptr 
8133   then we do nothing else we move the value to dptr */
8134   if (AOP_TYPE(left) != AOP_STR) {
8135     /* if this is remateriazable */
8136     if (AOP_TYPE(left) == AOP_IMMD)
8137       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8138     else { /* we need to get it byte by byte */
8139       pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8140       pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8141       if (options.model == MODEL_FLAT24)
8142       {
8143         pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8144       }
8145     }
8146   }
8147   /* so dptr know contains the address */
8148   freeAsmop(left,NULL,ic,TRUE);
8149   aopOp(result,ic,FALSE);
8150   
8151   /* if bit then unpack */
8152   if (IS_BITFIELD(retype)) 
8153     genUnpackBits(result,"dptr",FPOINTER);
8154   else {
8155     size = AOP_SIZE(result);
8156     offset = 0 ;
8157     
8158     while (size--) {
8159       pic14_emitcode("movx","a,@dptr");
8160       aopPut(AOP(result),"a",offset++);
8161       if (size)
8162         pic14_emitcode("inc","dptr");
8163     }
8164   }
8165   
8166   freeAsmop(result,NULL,ic,TRUE);
8167 }
8168 #if 0
8169 /*-----------------------------------------------------------------*/
8170 /* genCodePointerGet - get value from code space                  */
8171 /*-----------------------------------------------------------------*/
8172 static void genCodePointerGet (operand *left,
8173                  operand *result, iCode *ic)
8174 {
8175   int size, offset ;
8176   sym_link *retype = getSpec(operandType(result));
8177   
8178   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8179   
8180   aopOp(left,ic,FALSE);
8181   
8182   /* if the operand is already in dptr 
8183   then we do nothing else we move the value to dptr */
8184   if (AOP_TYPE(left) != AOP_STR) {
8185     /* if this is remateriazable */
8186     if (AOP_TYPE(left) == AOP_IMMD)
8187       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8188     else { /* we need to get it byte by byte */
8189       pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8190       pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8191       if (options.model == MODEL_FLAT24)
8192       {
8193         pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8194       }
8195     }
8196   }
8197   /* so dptr know contains the address */
8198   freeAsmop(left,NULL,ic,TRUE);
8199   aopOp(result,ic,FALSE);
8200   
8201   /* if bit then unpack */
8202   if (IS_BITFIELD(retype)) 
8203     genUnpackBits(result,"dptr",CPOINTER);
8204   else {
8205     size = AOP_SIZE(result);
8206     offset = 0 ;
8207     
8208     while (size--) {
8209       pic14_emitcode("clr","a");
8210       pic14_emitcode("movc","a,@a+dptr");
8211       aopPut(AOP(result),"a",offset++);
8212       if (size)
8213         pic14_emitcode("inc","dptr");
8214     }
8215   }
8216   
8217   freeAsmop(result,NULL,ic,TRUE);
8218 }
8219 #endif
8220 /*-----------------------------------------------------------------*/
8221 /* genGenPointerGet - gget value from generic pointer space        */
8222 /*-----------------------------------------------------------------*/
8223 static void genGenPointerGet (operand *left,
8224                 operand *result, iCode *ic)
8225 {
8226   int size, offset ;
8227   sym_link *retype = getSpec(operandType(result));
8228   
8229   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8230   aopOp(left,ic,FALSE);
8231   aopOp(result,ic,FALSE);
8232   
8233   
8234   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8235   
8236   /* if the operand is already in dptr 
8237   then we do nothing else we move the value to dptr */
8238   //  if (AOP_TYPE(left) != AOP_STR) {
8239   /* if this is remateriazable */
8240   if (AOP_TYPE(left) == AOP_IMMD) {
8241     pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8242     pic14_emitcode("mov","b,#%d",pointerCode(retype));
8243   }
8244   else { /* we need to get it byte by byte */
8245     
8246     emitpcode(POC_MOVFW,popGet(AOP(left),0));
8247     emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8248     
8249     size = AOP_SIZE(result);
8250     offset = 0 ;
8251     
8252     while(size--) {
8253       emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8254       emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8255       if(size)
8256         emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8257     }
8258     goto release;
8259   }
8260   //}
8261   /* so dptr know contains the address */
8262   
8263   /* if bit then unpack */
8264   //if (IS_BITFIELD(retype)) 
8265   //  genUnpackBits(result,"dptr",GPOINTER);
8266   
8267 release:
8268   freeAsmop(left,NULL,ic,TRUE);
8269   freeAsmop(result,NULL,ic,TRUE);
8270   
8271 }
8272
8273 /*-----------------------------------------------------------------*/
8274 /* genConstPointerGet - get value from const generic pointer space */
8275 /*-----------------------------------------------------------------*/
8276 static void genConstPointerGet (operand *left,
8277                 operand *result, iCode *ic)
8278 {
8279   //sym_link *retype = getSpec(operandType(result));
8280   symbol *albl = newiTempLabel(NULL);
8281   symbol *blbl = newiTempLabel(NULL);
8282   PIC_OPCODE poc;
8283   pCodeOp *pcop;
8284   
8285   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8286   aopOp(left,ic,FALSE);
8287   aopOp(result,ic,FALSE);
8288   
8289   
8290   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8291   
8292   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8293   
8294   emitpcode(POC_CALL,popGetLabel(albl->key));
8295   pcop = popGetLabel(blbl->key);
8296   emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8297   emitpcode(POC_GOTO,pcop);
8298   emitpLabel(albl->key);
8299   
8300   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8301   
8302   emitpcode(poc,popGet(AOP(left),1));
8303   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8304   emitpcode(poc,popGet(AOP(left),0));
8305   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8306   
8307   emitpLabel(blbl->key);
8308   
8309   emitpcode(POC_MOVWF,popGet(AOP(result),0));
8310   
8311   
8312   freeAsmop(left,NULL,ic,TRUE);
8313   freeAsmop(result,NULL,ic,TRUE);
8314   
8315 }
8316 /*-----------------------------------------------------------------*/
8317 /* genPointerGet - generate code for pointer get                   */
8318 /*-----------------------------------------------------------------*/
8319 static void genPointerGet (iCode *ic)
8320 {
8321   operand *left, *result ;
8322   sym_link *type, *etype;
8323   int p_type;
8324   
8325   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8326   
8327   left = IC_LEFT(ic);
8328   result = IC_RESULT(ic) ;
8329   
8330   /* depending on the type of pointer we need to
8331   move it to the correct pointer register */
8332   type = operandType(left);
8333   etype = getSpec(type);
8334   
8335   if (IS_PTR_CONST(type))
8336     DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8337   
8338   /* if left is of type of pointer then it is simple */
8339   if (IS_PTR(type) && !IS_FUNC(type->next)) 
8340     p_type = DCL_TYPE(type);
8341   else {
8342     /* we have to go by the storage class */
8343     p_type = PTR_TYPE(SPEC_OCLS(etype));
8344     
8345     DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8346     
8347     if (SPEC_OCLS(etype)->codesp ) {
8348       DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8349       //p_type = CPOINTER ; 
8350     }
8351     else
8352       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8353         DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8354       /*p_type = FPOINTER ;*/ 
8355       else
8356         if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8357           DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8358         /*        p_type = PPOINTER; */
8359         else
8360           if (SPEC_OCLS(etype) == idata )
8361             DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8362           /*      p_type = IPOINTER; */
8363           else
8364             DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8365           /*      p_type = POINTER ; */
8366   }
8367   
8368   /* now that we have the pointer type we assign
8369   the pointer values */
8370   switch (p_type) {
8371     
8372   case POINTER: 
8373   case IPOINTER:
8374     genNearPointerGet (left,result,ic);
8375     break;
8376     
8377   case PPOINTER:
8378     genPagedPointerGet(left,result,ic);
8379     break;
8380     
8381   case FPOINTER:
8382     genFarPointerGet (left,result,ic);
8383     break;
8384     
8385   case CPOINTER:
8386     genConstPointerGet (left,result,ic);
8387     //pic14_emitcodePointerGet (left,result,ic);
8388     break;
8389     
8390   case GPOINTER:
8391     if (IS_PTR_CONST(type))
8392       genConstPointerGet (left,result,ic);
8393     else
8394       genGenPointerGet (left,result,ic);
8395     break;
8396   }
8397   
8398 }
8399
8400 /*-----------------------------------------------------------------*/
8401 /* genPackBits - generates code for packed bit storage             */
8402 /*-----------------------------------------------------------------*/
8403 static void genPackBits (sym_link    *etype ,
8404              operand *right ,
8405              char *rname, int p_type)
8406 {
8407   int shCount = 0 ;
8408   int offset = 0  ;
8409   int rLen = 0 ;
8410   int blen, bstr ;   
8411   char *l ;
8412   
8413   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8414   blen = SPEC_BLEN(etype);
8415   bstr = SPEC_BSTR(etype);
8416   
8417   l = aopGet(AOP(right),offset++,FALSE,FALSE);
8418   MOVA(l);   
8419   
8420   /* if the bit lenth is less than or    */
8421   /* it exactly fits a byte then         */
8422   if (SPEC_BLEN(etype) <= 8 )  {
8423     shCount = SPEC_BSTR(etype) ;
8424     
8425     /* shift left acc */
8426     AccLsh(shCount);
8427     
8428     if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8429       
8430       
8431       switch (p_type) {
8432       case POINTER:
8433         pic14_emitcode ("mov","b,a");
8434         pic14_emitcode("mov","a,@%s",rname);
8435         break;
8436         
8437       case FPOINTER:
8438         pic14_emitcode ("mov","b,a");
8439         pic14_emitcode("movx","a,@dptr");
8440         break;
8441         
8442       case GPOINTER:
8443         pic14_emitcode ("push","b");
8444         pic14_emitcode ("push","acc");
8445         pic14_emitcode ("lcall","__gptrget");
8446         pic14_emitcode ("pop","b");
8447         break;
8448       }
8449       
8450       pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8451         ((unsigned char)(0xFF << (blen+bstr)) | 
8452         (unsigned char)(0xFF >> (8-bstr)) ) );
8453       pic14_emitcode ("orl","a,b");
8454       if (p_type == GPOINTER)
8455         pic14_emitcode("pop","b");
8456     }
8457   }
8458   
8459   switch (p_type) {
8460   case POINTER:
8461     pic14_emitcode("mov","@%s,a",rname);
8462     break;
8463     
8464   case FPOINTER:
8465     pic14_emitcode("movx","@dptr,a");
8466     break;
8467     
8468   case GPOINTER:
8469     DEBUGpic14_emitcode(";lcall","__gptrput");
8470     break;
8471   }
8472   
8473   /* if we r done */
8474   if ( SPEC_BLEN(etype) <= 8 )
8475     return ;
8476   
8477   pic14_emitcode("inc","%s",rname);
8478   rLen = SPEC_BLEN(etype) ;     
8479   
8480   /* now generate for lengths greater than one byte */
8481   while (1) {
8482     
8483     l = aopGet(AOP(right),offset++,FALSE,TRUE);
8484     
8485     rLen -= 8 ;
8486     if (rLen <= 0 )
8487       break ;
8488     
8489     switch (p_type) {
8490     case POINTER:
8491       if (*l == '@') {
8492         MOVA(l);
8493         pic14_emitcode("mov","@%s,a",rname);
8494       } else
8495         pic14_emitcode("mov","@%s,%s",rname,l);
8496       break;
8497       
8498     case FPOINTER:
8499       MOVA(l);
8500       pic14_emitcode("movx","@dptr,a");
8501       break;
8502       
8503     case GPOINTER:
8504       MOVA(l);
8505       DEBUGpic14_emitcode(";lcall","__gptrput");
8506       break;  
8507     }   
8508     pic14_emitcode ("inc","%s",rname);
8509   }
8510   
8511   MOVA(l);
8512   
8513   /* last last was not complete */
8514   if (rLen)   {
8515     /* save the byte & read byte */
8516     switch (p_type) {
8517     case POINTER:
8518       pic14_emitcode ("mov","b,a");
8519       pic14_emitcode("mov","a,@%s",rname);
8520       break;
8521       
8522     case FPOINTER:
8523       pic14_emitcode ("mov","b,a");
8524       pic14_emitcode("movx","a,@dptr");
8525       break;
8526       
8527     case GPOINTER:
8528       pic14_emitcode ("push","b");
8529       pic14_emitcode ("push","acc");
8530       pic14_emitcode ("lcall","__gptrget");
8531       pic14_emitcode ("pop","b");
8532       break;
8533     }
8534     
8535     pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8536     pic14_emitcode ("orl","a,b");
8537   }
8538   
8539   if (p_type == GPOINTER)
8540     pic14_emitcode("pop","b");
8541   
8542   switch (p_type) {
8543     
8544   case POINTER:
8545     pic14_emitcode("mov","@%s,a",rname);
8546     break;
8547     
8548   case FPOINTER:
8549     pic14_emitcode("movx","@dptr,a");
8550     break;
8551     
8552   case GPOINTER:
8553     DEBUGpic14_emitcode(";lcall","__gptrput");
8554     break;      
8555   }
8556 }
8557 /*-----------------------------------------------------------------*/
8558 /* genDataPointerSet - remat pointer to data space                 */
8559 /*-----------------------------------------------------------------*/
8560 static void genDataPointerSet(operand *right,
8561                 operand *result,
8562                 iCode *ic)
8563 {
8564   int size, offset = 0 ;
8565   char *l, buffer[256];
8566   
8567   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8568   aopOp(right,ic,FALSE);
8569   
8570   l = aopGet(AOP(result),0,FALSE,TRUE);
8571   size = AOP_SIZE(right);
8572   /*
8573   if ( AOP_TYPE(result) == AOP_PCODE) {
8574   fprintf(stderr,"genDataPointerSet   %s, %d\n",
8575   AOP(result)->aopu.pcop->name,
8576   PCOI(AOP(result)->aopu.pcop)->offset);
8577   }
8578   */
8579   
8580   // tsd, was l+1 - the underline `_' prefix was being stripped
8581   while (size--) {
8582     if (offset) {
8583       sprintf(buffer,"(%s + %d)",l,offset);
8584       fprintf(stderr,"oops  %s\n",buffer);
8585     } else
8586       sprintf(buffer,"%s",l);
8587     
8588     if (AOP_TYPE(right) == AOP_LIT) {
8589       unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8590       lit = lit >> (8*offset);
8591       if(lit&0xff) {
8592         pic14_emitcode("movlw","%d",lit);
8593         pic14_emitcode("movwf","%s",buffer);
8594         
8595         emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8596         //emitpcode(POC_MOVWF, popRegFromString(buffer));
8597         emitpcode(POC_MOVWF, popGet(AOP(result),0));
8598         
8599       } else {
8600         pic14_emitcode("clrf","%s",buffer);
8601         //emitpcode(POC_CLRF, popRegFromString(buffer));
8602         emitpcode(POC_CLRF, popGet(AOP(result),0));
8603       }
8604     }else {
8605       pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8606       pic14_emitcode("movwf","%s",buffer);
8607       
8608       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8609       //emitpcode(POC_MOVWF, popRegFromString(buffer));
8610       emitpcode(POC_MOVWF, popGet(AOP(result),0));
8611       
8612     }
8613     
8614     offset++;
8615   }
8616   
8617   freeAsmop(right,NULL,ic,TRUE);
8618   freeAsmop(result,NULL,ic,TRUE);
8619 }
8620
8621 /*-----------------------------------------------------------------*/
8622 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8623 /*-----------------------------------------------------------------*/
8624 static void genNearPointerSet (operand *right,
8625                  operand *result, 
8626                  iCode *ic)
8627 {
8628   asmop *aop = NULL;
8629   char *l;
8630   sym_link *retype;
8631   sym_link *ptype = operandType(result);
8632   
8633   
8634   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8635   retype= getSpec(operandType(right));
8636   
8637   aopOp(result,ic,FALSE);
8638   
8639   
8640   /* if the result is rematerializable &
8641   in data space & not a bit variable */
8642   //if (AOP_TYPE(result) == AOP_IMMD &&
8643   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8644     DCL_TYPE(ptype) == POINTER   &&
8645     !IS_BITFIELD(retype)) {
8646     genDataPointerSet (right,result,ic);
8647     freeAsmop(result,NULL,ic,TRUE);
8648     return;
8649   }
8650   
8651   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8652   aopOp(right,ic,FALSE);
8653   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8654   
8655   /* if the value is already in a pointer register
8656   then don't need anything more */
8657   if (!AOP_INPREG(AOP(result))) {
8658     /* otherwise get a free pointer register */
8659     //aop = newAsmop(0);
8660     //preg = getFreePtr(ic,&aop,FALSE);
8661     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8662     //pic14_emitcode("mov","%s,%s",
8663     //         preg->name,
8664     //         aopGet(AOP(result),0,FALSE,TRUE));
8665     //rname = preg->name ;
8666     //pic14_emitcode("movwf","fsr");
8667     emitpcode(POC_MOVFW, popGet(AOP(result),0));
8668     emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8669     emitpcode(POC_MOVFW, popGet(AOP(right),0));
8670     emitpcode(POC_MOVWF, popCopyReg(&pc_indf));
8671     goto release;
8672     
8673   }// else
8674   //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8675   
8676   
8677   /* if bitfield then unpack the bits */
8678   if (IS_BITFIELD(retype)) {
8679     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8680       "The programmer is obviously confused");
8681     //genPackBits (retype,right,rname,POINTER);
8682     exit(1);
8683   }
8684   else {
8685     /* we have can just get the values */
8686     int size = AOP_SIZE(right);
8687     int offset = 0 ;    
8688     
8689     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8690     while (size--) {
8691       l = aopGet(AOP(right),offset,FALSE,TRUE);
8692       if (*l == '@' ) {
8693         //MOVA(l);
8694         //pic14_emitcode("mov","@%s,a",rname);
8695         pic14_emitcode("movf","indf,w ;1");
8696       } else {
8697         
8698         if (AOP_TYPE(right) == AOP_LIT) {
8699           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8700           if(lit) {
8701             pic14_emitcode("movlw","%s",l);
8702             pic14_emitcode("movwf","indf ;2");
8703           } else 
8704             pic14_emitcode("clrf","indf");
8705         }else {
8706           pic14_emitcode("movf","%s,w",l);
8707           pic14_emitcode("movwf","indf ;2");
8708         }
8709         //pic14_emitcode("mov","@%s,%s",rname,l);
8710       }
8711       if (size)
8712         pic14_emitcode("incf","fsr,f ;3");
8713       //pic14_emitcode("inc","%s",rname);
8714       offset++;
8715     }
8716   }
8717   
8718   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8719   /* now some housekeeping stuff */
8720   if (aop) {
8721     /* we had to allocate for this iCode */
8722     freeAsmop(NULL,aop,ic,TRUE);
8723   } else { 
8724   /* we did not allocate which means left
8725   already in a pointer register, then
8726   if size > 0 && this could be used again
8727   we have to point it back to where it 
8728     belongs */
8729     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8730     if (AOP_SIZE(right) > 1 &&
8731       !OP_SYMBOL(result)->remat &&
8732       ( OP_SYMBOL(result)->liveTo > ic->seq ||
8733       ic->depth )) {
8734       int size = AOP_SIZE(right) - 1;
8735       while (size--)
8736         pic14_emitcode("decf","fsr,f");
8737       //pic14_emitcode("dec","%s",rname);
8738     }
8739   }
8740   
8741   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8742   /* done */
8743 release:
8744   freeAsmop(right,NULL,ic,TRUE);
8745   freeAsmop(result,NULL,ic,TRUE);
8746 }
8747
8748 /*-----------------------------------------------------------------*/
8749 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8750 /*-----------------------------------------------------------------*/
8751 static void genPagedPointerSet (operand *right,
8752                 operand *result, 
8753                 iCode *ic)
8754 {
8755   asmop *aop = NULL;
8756   regs *preg = NULL ;
8757   char *rname , *l;
8758   sym_link *retype;
8759   
8760   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8761   
8762   retype= getSpec(operandType(right));
8763   
8764   aopOp(result,ic,FALSE);
8765   
8766   /* if the value is already in a pointer register
8767   then don't need anything more */
8768   if (!AOP_INPREG(AOP(result))) {
8769     /* otherwise get a free pointer register */
8770     aop = newAsmop(0);
8771     preg = getFreePtr(ic,&aop,FALSE);
8772     pic14_emitcode("mov","%s,%s",
8773       preg->name,
8774       aopGet(AOP(result),0,FALSE,TRUE));
8775     rname = preg->name ;
8776   } else
8777     rname = aopGet(AOP(result),0,FALSE,FALSE);
8778   
8779   freeAsmop(result,NULL,ic,TRUE);
8780   aopOp (right,ic,FALSE);
8781   
8782   /* if bitfield then unpack the bits */
8783   if (IS_BITFIELD(retype)) 
8784     genPackBits (retype,right,rname,PPOINTER);
8785   else {
8786     /* we have can just get the values */
8787     int size = AOP_SIZE(right);
8788     int offset = 0 ;  
8789     
8790     while (size--) {
8791       l = aopGet(AOP(right),offset,FALSE,TRUE);
8792       
8793       MOVA(l);
8794       pic14_emitcode("movx","@%s,a",rname);
8795       
8796       if (size)
8797         pic14_emitcode("inc","%s",rname);
8798       
8799       offset++;
8800     }
8801   }
8802   
8803   /* now some housekeeping stuff */
8804   if (aop) {
8805     /* we had to allocate for this iCode */
8806     freeAsmop(NULL,aop,ic,TRUE);
8807   } else { 
8808   /* we did not allocate which means left
8809      already in a pointer register, then
8810      if size > 0 && this could be used again
8811      we have to point it back to where it 
8812     belongs */
8813     if (AOP_SIZE(right) > 1 &&
8814       !OP_SYMBOL(result)->remat &&
8815       ( OP_SYMBOL(result)->liveTo > ic->seq ||
8816       ic->depth )) {
8817       int size = AOP_SIZE(right) - 1;
8818       while (size--)
8819         pic14_emitcode("dec","%s",rname);
8820     }
8821   }
8822   
8823   /* done */
8824   freeAsmop(right,NULL,ic,TRUE);
8825   
8826   
8827 }
8828
8829 /*-----------------------------------------------------------------*/
8830 /* genFarPointerSet - set value from far space                     */
8831 /*-----------------------------------------------------------------*/
8832 static void genFarPointerSet (operand *right,
8833                 operand *result, iCode *ic)
8834 {
8835   int size, offset ;
8836   sym_link *retype = getSpec(operandType(right));
8837   
8838   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8839   aopOp(result,ic,FALSE);
8840   
8841   /* if the operand is already in dptr 
8842   then we do nothing else we move the value to dptr */
8843   if (AOP_TYPE(result) != AOP_STR) {
8844     /* if this is remateriazable */
8845     if (AOP_TYPE(result) == AOP_IMMD)
8846       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8847     else { /* we need to get it byte by byte */
8848       pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8849       pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8850       if (options.model == MODEL_FLAT24)
8851       {
8852         pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8853       }
8854     }
8855   }
8856   /* so dptr know contains the address */
8857   freeAsmop(result,NULL,ic,TRUE);
8858   aopOp(right,ic,FALSE);
8859   
8860   /* if bit then unpack */
8861   if (IS_BITFIELD(retype)) 
8862     genPackBits(retype,right,"dptr",FPOINTER);
8863   else {
8864     size = AOP_SIZE(right);
8865     offset = 0 ;
8866     
8867     while (size--) {
8868       char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8869       MOVA(l);
8870       pic14_emitcode("movx","@dptr,a");
8871       if (size)
8872         pic14_emitcode("inc","dptr");
8873     }
8874   }
8875   
8876   freeAsmop(right,NULL,ic,TRUE);
8877 }
8878
8879 /*-----------------------------------------------------------------*/
8880 /* genGenPointerSet - set value from generic pointer space         */
8881 /*-----------------------------------------------------------------*/
8882 static void genGenPointerSet (operand *right,
8883                 operand *result, iCode *ic)
8884 {
8885   int size, offset ;
8886   sym_link *retype = getSpec(operandType(right));
8887   
8888   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8889   
8890   aopOp(result,ic,FALSE);
8891   aopOp(right,ic,FALSE);
8892   size = AOP_SIZE(right);
8893   
8894   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8895   
8896   /* if the operand is already in dptr 
8897   then we do nothing else we move the value to dptr */
8898   if (AOP_TYPE(result) != AOP_STR) {
8899     /* if this is remateriazable */
8900     if (AOP_TYPE(result) == AOP_IMMD) {
8901       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8902       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8903     }
8904     else { /* we need to get it byte by byte */
8905       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8906       size = AOP_SIZE(right);
8907       offset = 0 ;
8908       
8909       /* hack hack! see if this the FSR. If so don't load W */
8910       if(AOP_TYPE(right) != AOP_ACC) {
8911         
8912         
8913         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8914         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8915         
8916         if(AOP_SIZE(result) > 1) {
8917           emitpcode(POC_BCF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8918           emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8919           emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8920           
8921         }
8922         
8923         //if(size==2)
8924         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8925         //if(size==4) {
8926         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8927         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8928         //}
8929         
8930         while(size--) {
8931           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
8932           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8933           
8934           if(size)
8935             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8936         }
8937         
8938         
8939         goto release;
8940       } 
8941       
8942       if(aopIdx(AOP(result),0) != 4) {
8943         
8944         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8945         goto release;
8946       }
8947       
8948       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8949       goto release;
8950       
8951     }
8952   }
8953   /* so dptr know contains the address */
8954   
8955   
8956   /* if bit then unpack */
8957   if (IS_BITFIELD(retype)) 
8958     genPackBits(retype,right,"dptr",GPOINTER);
8959   else {
8960     size = AOP_SIZE(right);
8961     offset = 0 ;
8962     
8963     DEBUGpic14_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
8964     
8965     while (size--) {
8966       
8967       emitpcode(POC_MOVFW,popGet(AOP(result),offset));
8968       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8969       
8970       if (AOP_TYPE(right) == AOP_LIT) 
8971         emitpcode(POC_MOVLW, popGet(AOP(right),offset));
8972       else
8973         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8974       
8975       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8976       
8977       offset++;
8978     }
8979   }
8980   
8981 release:
8982   freeAsmop(right,NULL,ic,TRUE);
8983   freeAsmop(result,NULL,ic,TRUE);
8984 }
8985
8986 /*-----------------------------------------------------------------*/
8987 /* genPointerSet - stores the value into a pointer location        */
8988 /*-----------------------------------------------------------------*/
8989 static void genPointerSet (iCode *ic)
8990 {    
8991   operand *right, *result ;
8992   sym_link *type, *etype;
8993   int p_type;
8994   
8995   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8996   
8997   right = IC_RIGHT(ic);
8998   result = IC_RESULT(ic) ;
8999   
9000   /* depending on the type of pointer we need to
9001   move it to the correct pointer register */
9002   type = operandType(result);
9003   etype = getSpec(type);
9004   /* if left is of type of pointer then it is simple */
9005   if (IS_PTR(type) && !IS_FUNC(type->next)) {
9006     p_type = DCL_TYPE(type);
9007   }
9008   else {
9009     /* we have to go by the storage class */
9010     p_type = PTR_TYPE(SPEC_OCLS(etype));
9011     
9012     /*  if (SPEC_OCLS(etype)->codesp ) { */
9013     /*      p_type = CPOINTER ;  */
9014     /*  } */
9015     /*  else */
9016     /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9017     /*    p_type = FPOINTER ; */
9018     /*      else */
9019     /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9020     /*        p_type = PPOINTER ; */
9021     /*    else */
9022     /*        if (SPEC_OCLS(etype) == idata ) */
9023     /*      p_type = IPOINTER ; */
9024     /*        else */
9025     /*      p_type = POINTER ; */
9026   }
9027   
9028   /* now that we have the pointer type we assign
9029   the pointer values */
9030   switch (p_type) {
9031     
9032   case POINTER:
9033   case IPOINTER:
9034     genNearPointerSet (right,result,ic);
9035     break;
9036     
9037   case PPOINTER:
9038     genPagedPointerSet (right,result,ic);
9039     break;
9040     
9041   case FPOINTER:
9042     genFarPointerSet (right,result,ic);
9043     break;
9044     
9045   case GPOINTER:
9046     genGenPointerSet (right,result,ic);
9047     break;
9048     
9049   default:
9050     werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9051       "genPointerSet: illegal pointer type");
9052   }
9053 }
9054
9055 /*-----------------------------------------------------------------*/
9056 /* genIfx - generate code for Ifx statement                        */
9057 /*-----------------------------------------------------------------*/
9058 static void genIfx (iCode *ic, iCode *popIc)
9059 {
9060   operand *cond = IC_COND(ic);
9061   int isbit =0;
9062   
9063   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9064   
9065   aopOp(cond,ic,FALSE);
9066   
9067   /* get the value into acc */
9068   if (AOP_TYPE(cond) != AOP_CRY)
9069     pic14_toBoolean(cond);
9070   else
9071     isbit = 1;
9072   /* the result is now in the accumulator */
9073   freeAsmop(cond,NULL,ic,TRUE);
9074   
9075   /* if there was something to be popped then do it */
9076   if (popIc)
9077     genIpop(popIc);
9078   
9079   /* if the condition is  a bit variable */
9080   if (isbit && IS_ITEMP(cond) && 
9081     SPIL_LOC(cond)) {
9082     genIfxJump(ic,SPIL_LOC(cond)->rname);
9083     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9084   }
9085   else {
9086     if (isbit && !IS_ITEMP(cond))
9087       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9088     else
9089       genIfxJump(ic,"a");
9090   }
9091   ic->generated = 1;
9092   
9093 }
9094
9095 /*-----------------------------------------------------------------*/
9096 /* genAddrOf - generates code for address of                       */
9097 /*-----------------------------------------------------------------*/
9098 static void genAddrOf (iCode *ic)
9099 {
9100   operand *right, *result, *left;
9101   int size, offset ;
9102   
9103   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9104   
9105   
9106   //aopOp(IC_RESULT(ic),ic,FALSE);
9107   
9108   aopOp((left=IC_LEFT(ic)),ic,FALSE);
9109   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9110   aopOp((result=IC_RESULT(ic)),ic,TRUE);
9111   
9112   DEBUGpic14_AopType(__LINE__,left,right,result);
9113   
9114   size = AOP_SIZE(IC_RESULT(ic));
9115   offset = 0;
9116   
9117   while (size--) {
9118     /* fixing bug #863624, reported from (errolv) */
9119     emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9120     emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9121     
9122 #if 0
9123     emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9124     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9125 #endif
9126     offset++;
9127   }
9128   
9129   freeAsmop(left,NULL,ic,FALSE);
9130   freeAsmop(result,NULL,ic,TRUE);
9131   
9132 }
9133
9134 #if 0
9135 /*-----------------------------------------------------------------*/
9136 /* genFarFarAssign - assignment when both are in far space         */
9137 /*-----------------------------------------------------------------*/
9138 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9139 {
9140   int size = AOP_SIZE(right);
9141   int offset = 0;
9142   char *l ;
9143   /* first push the right side on to the stack */
9144   while (size--) {
9145     l = aopGet(AOP(right),offset++,FALSE,FALSE);
9146     MOVA(l);
9147     pic14_emitcode ("push","acc");
9148   }
9149   
9150   freeAsmop(right,NULL,ic,FALSE);
9151   /* now assign DPTR to result */
9152   aopOp(result,ic,FALSE);
9153   size = AOP_SIZE(result);
9154   while (size--) {
9155     pic14_emitcode ("pop","acc");
9156     aopPut(AOP(result),"a",--offset);
9157   }
9158   freeAsmop(result,NULL,ic,FALSE);
9159   
9160 }
9161 #endif
9162
9163 /*-----------------------------------------------------------------*/
9164 /* genAssign - generate code for assignment                        */
9165 /*-----------------------------------------------------------------*/
9166 static void genAssign (iCode *ic)
9167 {
9168   operand *result, *right;
9169   int size, offset,know_W;
9170   unsigned long lit = 0L;
9171   
9172   result = IC_RESULT(ic);
9173   right  = IC_RIGHT(ic) ;
9174   
9175   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9176   
9177   /* if they are the same */
9178   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9179     return ;
9180   
9181   aopOp(right,ic,FALSE);
9182   aopOp(result,ic,TRUE);
9183   
9184   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9185   
9186   /* if they are the same registers */
9187   if (pic14_sameRegs(AOP(right),AOP(result)))
9188     goto release;
9189   
9190   /* if the result is a bit */
9191   if (AOP_TYPE(result) == AOP_CRY) {
9192     
9193   /* if the right size is a literal then
9194     we know what the value is */
9195     if (AOP_TYPE(right) == AOP_LIT) {
9196       
9197       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9198         popGet(AOP(result),0));
9199       
9200       if (((int) operandLitValue(right))) 
9201         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9202         AOP(result)->aopu.aop_dir,
9203         AOP(result)->aopu.aop_dir);
9204       else
9205         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9206         AOP(result)->aopu.aop_dir,
9207         AOP(result)->aopu.aop_dir);
9208       goto release;
9209     }
9210     
9211     /* the right is also a bit variable */
9212     if (AOP_TYPE(right) == AOP_CRY) {
9213       emitpcode(POC_BCF,    popGet(AOP(result),0));
9214       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9215       emitpcode(POC_BSF,    popGet(AOP(result),0));
9216       
9217       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9218         AOP(result)->aopu.aop_dir,
9219         AOP(result)->aopu.aop_dir);
9220       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9221         AOP(right)->aopu.aop_dir,
9222         AOP(right)->aopu.aop_dir);
9223       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9224         AOP(result)->aopu.aop_dir,
9225         AOP(result)->aopu.aop_dir);
9226       goto release ;
9227     }
9228     
9229     /* we need to or */
9230     emitpcode(POC_BCF,    popGet(AOP(result),0));
9231     pic14_toBoolean(right);
9232     emitSKPZ;
9233     emitpcode(POC_BSF,    popGet(AOP(result),0));
9234     //aopPut(AOP(result),"a",0);
9235     goto release ;
9236   }
9237   
9238   /* bit variables done */
9239   /* general case */
9240   size = AOP_SIZE(result);
9241   offset = 0 ;
9242   if(AOP_TYPE(right) == AOP_LIT)
9243     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9244   
9245   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9246     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9247     if(aopIdx(AOP(result),0) == 4) {
9248       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9249       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9250       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9251       goto release;
9252     } else
9253       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9254   }
9255   
9256   know_W=-1;
9257   while (size--) {
9258     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9259     if(AOP_TYPE(right) == AOP_LIT) {
9260       if(lit&0xff) {
9261         if(know_W != (int)(lit&0xff))
9262           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9263         know_W = lit&0xff;
9264         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9265       } else
9266         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9267       
9268       lit >>= 8;
9269       
9270     } else if (AOP_TYPE(right) == AOP_CRY) {
9271       emitpcode(POC_CLRF, popGet(AOP(result),offset));
9272       if(offset == 0) {
9273         emitpcode(POC_BTFSS, popGet(AOP(right),0));
9274         emitpcode(POC_INCF, popGet(AOP(result),0));
9275       }
9276     } else {
9277       mov2w (AOP(right), offset);
9278       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9279     }
9280     
9281     offset++;
9282   }
9283   
9284   
9285 release:
9286   freeAsmop (right,NULL,ic,FALSE);
9287   freeAsmop (result,NULL,ic,TRUE);
9288 }   
9289
9290 /*-----------------------------------------------------------------*/
9291 /* genJumpTab - genrates code for jump table                       */
9292 /*-----------------------------------------------------------------*/
9293 static void genJumpTab (iCode *ic)
9294 {
9295   symbol *jtab;
9296   char *l;
9297   
9298   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9299   
9300   aopOp(IC_JTCOND(ic),ic,FALSE);
9301   /* get the condition into accumulator */
9302   l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9303   MOVA(l);
9304   /* multiply by three */
9305   pic14_emitcode("add","a,acc");
9306   pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9307   
9308   jtab = newiTempLabel(NULL);
9309   pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9310   pic14_emitcode("jmp","@a+dptr");
9311   pic14_emitcode("","%05d_DS_:",jtab->key+100);
9312   
9313   emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
9314   emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
9315   emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9316   emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9317   emitSKPNC;
9318   emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9319   emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9320   emitpLabel(jtab->key);
9321   
9322   freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9323   
9324   /* now generate the jump labels */
9325   for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9326   jtab = setNextItem(IC_JTLABELS(ic))) {
9327     pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9328     emitpcode(POC_GOTO,popGetLabel(jtab->key));
9329     
9330   }
9331   
9332 }
9333
9334 /*-----------------------------------------------------------------*/
9335 /* genMixedOperation - gen code for operators between mixed types  */
9336 /*-----------------------------------------------------------------*/
9337 /*
9338 TSD - Written for the PIC port - but this unfortunately is buggy.
9339 This routine is good in that it is able to efficiently promote 
9340 types to different (larger) sizes. Unfortunately, the temporary
9341 variables that are optimized out by this routine are sometimes
9342 used in other places. So until I know how to really parse the 
9343 iCode tree, I'm going to not be using this routine :(.
9344 */
9345 static int genMixedOperation (iCode *ic)
9346 {
9347 #if 0
9348   operand *result = IC_RESULT(ic);
9349   sym_link *ctype = operandType(IC_LEFT(ic));
9350   operand *right = IC_RIGHT(ic);
9351   int ret = 0;
9352   int big,small;
9353   int offset;
9354   
9355   iCode *nextic;
9356   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9357   
9358   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9359   
9360   nextic = ic->next;
9361   if(!nextic)
9362     return 0;
9363   
9364   nextright = IC_RIGHT(nextic);
9365   nextleft  = IC_LEFT(nextic);
9366   nextresult = IC_RESULT(nextic);
9367   
9368   aopOp(right,ic,FALSE);
9369   aopOp(result,ic,FALSE);
9370   aopOp(nextright,  nextic, FALSE);
9371   aopOp(nextleft,   nextic, FALSE);
9372   aopOp(nextresult, nextic, FALSE);
9373   
9374   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9375     
9376     operand *t = right;
9377     right = nextright;
9378     nextright = t; 
9379     
9380     pic14_emitcode(";remove right +","");
9381     
9382   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9383   /*
9384   operand *t = right;
9385   right = nextleft;
9386   nextleft = t; 
9387     */
9388     pic14_emitcode(";remove left +","");
9389   } else
9390     return 0;
9391   
9392   big = AOP_SIZE(nextleft);
9393   small = AOP_SIZE(nextright);
9394   
9395   switch(nextic->op) {
9396     
9397   case '+':
9398     pic14_emitcode(";optimize a +","");
9399     /* if unsigned or not an integral type */
9400     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9401       pic14_emitcode(";add a bit to something","");
9402     } else {
9403       
9404       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9405       
9406       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9407         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9408         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9409       } else
9410         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9411       
9412       offset = 0;
9413       while(--big) {
9414         
9415         offset++;
9416         
9417         if(--small) {
9418           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9419             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9420             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9421           }
9422           
9423           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9424           emitSKPNC;
9425           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9426             AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9427             AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9428           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9429           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9430           
9431         } else {
9432           pic14_emitcode("rlf","known_zero,w");
9433           
9434           /*
9435           if right is signed
9436           btfsc  right,7
9437           addlw ff
9438           */
9439           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9440             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9441             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9442           } else {
9443             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9444           }
9445         }
9446       }
9447       ret = 1;
9448     }
9449   }
9450   ret = 1;
9451   
9452 release:
9453   freeAsmop(right,NULL,ic,TRUE);
9454   freeAsmop(result,NULL,ic,TRUE);
9455   freeAsmop(nextright,NULL,ic,TRUE);
9456   freeAsmop(nextleft,NULL,ic,TRUE);
9457   if(ret)
9458     nextic->generated = 1;
9459   
9460   return ret;
9461 #else
9462   return 0;
9463 #endif
9464 }
9465 /*-----------------------------------------------------------------*/
9466 /* genCast - gen code for casting                                  */
9467 /*-----------------------------------------------------------------*/
9468 static void genCast (iCode *ic)
9469 {
9470   operand *result = IC_RESULT(ic);
9471   sym_link *ctype = operandType(IC_LEFT(ic));
9472   sym_link *rtype = operandType(IC_RIGHT(ic));
9473   operand *right = IC_RIGHT(ic);
9474   int size, offset ;
9475   
9476   DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9477   /* if they are equivalent then do nothing */
9478   if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9479     return ;
9480   
9481   aopOp(right,ic,FALSE) ;
9482   aopOp(result,ic,FALSE);
9483   
9484   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9485   
9486   /* if the result is a bit */
9487   if (AOP_TYPE(result) == AOP_CRY) {
9488   /* if the right size is a literal then
9489     we know what the value is */
9490     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9491     if (AOP_TYPE(right) == AOP_LIT) {
9492       
9493       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9494         popGet(AOP(result),0));
9495       
9496       if (((int) operandLitValue(right))) 
9497         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9498         AOP(result)->aopu.aop_dir,
9499         AOP(result)->aopu.aop_dir);
9500       else
9501         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9502         AOP(result)->aopu.aop_dir,
9503         AOP(result)->aopu.aop_dir);
9504       
9505       goto release;
9506     }
9507     
9508     /* the right is also a bit variable */
9509     if (AOP_TYPE(right) == AOP_CRY) {
9510       
9511       emitCLRC;
9512       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9513       
9514       pic14_emitcode("clrc","");
9515       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9516         AOP(right)->aopu.aop_dir,
9517         AOP(right)->aopu.aop_dir);
9518       aopPut(AOP(result),"c",0);
9519       goto release ;
9520     }
9521     
9522     /* we need to or */
9523     if (AOP_TYPE(right) == AOP_REG) {
9524       emitpcode(POC_BCF,    popGet(AOP(result),0));
9525       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9526       emitpcode(POC_BSF,    popGet(AOP(result),0));
9527     }
9528     pic14_toBoolean(right);
9529     aopPut(AOP(result),"a",0);
9530     goto release ;
9531   }
9532   
9533   if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9534     int offset = 1;
9535     size = AOP_SIZE(result);
9536     
9537     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9538     
9539     emitpcode(POC_CLRF,   popGet(AOP(result),0));
9540     emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9541     emitpcode(POC_INCF,   popGet(AOP(result),0));
9542     
9543     while (size--)
9544       emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9545     
9546     goto release;
9547   }
9548   
9549   /* if they are the same size : or less */
9550   if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9551     
9552     /* if they are in the same place */
9553     if (pic14_sameRegs(AOP(right),AOP(result)))
9554       goto release;
9555     
9556     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9557     if (IS_PTR_CONST(rtype))
9558       DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9559     if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9560       DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9561     
9562     if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9563       emitpcode(POC_MOVLW, popGet(AOP(right),0));
9564       emitpcode(POC_MOVWF, popGet(AOP(result),0));
9565       emitpcode(POC_MOVLW, popGet(AOP(right),1));
9566       emitpcode(POC_MOVWF, popGet(AOP(result),1));
9567       if(AOP_SIZE(result) <2)
9568         fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9569       
9570     } else {
9571       
9572       /* if they in different places then copy */
9573       size = AOP_SIZE(result);
9574       offset = 0 ;
9575       while (size--) {
9576         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9577         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9578         
9579         //aopPut(AOP(result),
9580         // aopGet(AOP(right),offset,FALSE,FALSE),
9581         // offset);
9582         
9583         offset++;
9584       }
9585     }
9586     goto release;
9587   }
9588   
9589   
9590   /* if the result is of type pointer */
9591   if (IS_PTR(ctype)) {
9592     
9593     int p_type;
9594     sym_link *type = operandType(right);
9595     sym_link *etype = getSpec(type);
9596     DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9597     
9598     /* pointer to generic pointer */
9599     if (IS_GENPTR(ctype)) {
9600       char *l = zero;
9601       
9602       if (IS_PTR(type)) 
9603         p_type = DCL_TYPE(type);
9604       else {
9605         /* we have to go by the storage class */
9606         p_type = PTR_TYPE(SPEC_OCLS(etype));
9607         
9608         /*    if (SPEC_OCLS(etype)->codesp )  */
9609         /*        p_type = CPOINTER ;  */
9610         /*    else */
9611         /*        if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9612         /*      p_type = FPOINTER ; */
9613         /*        else */
9614         /*      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9615         /*          p_type = PPOINTER; */
9616         /*      else */
9617         /*          if (SPEC_OCLS(etype) == idata ) */
9618         /*        p_type = IPOINTER ; */
9619         /*          else */
9620         /*        p_type = POINTER ; */
9621       }
9622       
9623       /* the first two bytes are known */
9624       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9625       size = GPTRSIZE - 1; 
9626       offset = 0 ;
9627       while (size--) {
9628         if(offset < AOP_SIZE(right)) {
9629           DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9630           if ((AOP_TYPE(right) == AOP_PCODE) && 
9631             AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9632             emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9633             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9634           } else { 
9635             aopPut(AOP(result),
9636               aopGet(AOP(right),offset,FALSE,FALSE),
9637               offset);
9638           }
9639         } else 
9640           emitpcode(POC_CLRF,popGet(AOP(result),offset));
9641         offset++;
9642       }
9643       /* the last byte depending on type */
9644       switch (p_type) {
9645       case IPOINTER:
9646       case POINTER:
9647         emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9648         break;
9649       case FPOINTER:
9650         pic14_emitcode(";BUG!? ","%d",__LINE__);
9651         l = one;
9652         break;
9653       case CPOINTER:
9654         pic14_emitcode(";BUG!? ","%d",__LINE__);
9655         l = "#0x02";
9656         break;        
9657       case PPOINTER:
9658         pic14_emitcode(";BUG!? ","%d",__LINE__);
9659         l = "#0x03";
9660         break;
9661         
9662       default:
9663         /* this should never happen */
9664         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9665           "got unknown pointer type");
9666         exit(1);
9667       }
9668       //aopPut(AOP(result),l, GPTRSIZE - 1);      
9669       goto release ;
9670     }
9671     
9672     /* just copy the pointers */
9673     size = AOP_SIZE(result);
9674     offset = 0 ;
9675     while (size--) {
9676       aopPut(AOP(result),
9677         aopGet(AOP(right),offset,FALSE,FALSE),
9678         offset);
9679       offset++;
9680     }
9681     goto release ;
9682   }
9683   
9684   
9685   
9686   /* so we now know that the size of destination is greater
9687   than the size of the source.
9688   Now, if the next iCode is an operator then we might be
9689   able to optimize the operation without performing a cast.
9690   */
9691   if(genMixedOperation(ic))
9692     goto release;
9693   
9694   DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9695   
9696   /* we move to result for the size of source */
9697   size = AOP_SIZE(right);
9698   offset = 0 ;
9699   while (size--) {
9700     emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9701     emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9702     offset++;
9703   }
9704   
9705   /* now depending on the sign of the destination */
9706   size = AOP_SIZE(result) - AOP_SIZE(right);
9707   /* if unsigned or not an integral type */
9708   if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9709     while (size--)
9710       emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9711   } else {
9712     /* we need to extend the sign :{ */
9713     
9714     if(size == 1) {
9715       /* Save one instruction of casting char to int */
9716       emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9717       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9718       emitpcode(POC_DECF,   popGet(AOP(result),offset));
9719     } else {
9720       emitpcodeNULLop(POC_CLRW);
9721       
9722       if(offset)
9723         emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9724       else
9725         emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9726       
9727       emitpcode(POC_MOVLW,   popGetLit(0xff));
9728       
9729       while (size--)
9730         emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9731     }
9732   }
9733   
9734 release:
9735   freeAsmop(right,NULL,ic,TRUE);
9736   freeAsmop(result,NULL,ic,TRUE);
9737   
9738 }
9739
9740 /*-----------------------------------------------------------------*/
9741 /* genDjnz - generate decrement & jump if not zero instrucion      */
9742 /*-----------------------------------------------------------------*/
9743 static int genDjnz (iCode *ic, iCode *ifx)
9744 {
9745   symbol *lbl, *lbl1;
9746   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9747   
9748   if (!ifx)
9749     return 0;
9750   
9751     /* if the if condition has a false label
9752   then we cannot save */
9753   if (IC_FALSE(ifx))
9754     return 0;
9755   
9756     /* if the minus is not of the form 
9757   a = a - 1 */
9758   if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9759     !IS_OP_LITERAL(IC_RIGHT(ic)))
9760     return 0;
9761   
9762   if (operandLitValue(IC_RIGHT(ic)) != 1)
9763     return 0;
9764   
9765     /* if the size of this greater than one then no
9766   saving */
9767   if (getSize(operandType(IC_RESULT(ic))) > 1)
9768     return 0;
9769   
9770   /* otherwise we can save BIG */
9771   lbl = newiTempLabel(NULL);
9772   lbl1= newiTempLabel(NULL);
9773   
9774   aopOp(IC_RESULT(ic),ic,FALSE);
9775   
9776   if (IS_AOP_PREG(IC_RESULT(ic))) {
9777     pic14_emitcode("dec","%s",
9778       aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9779     pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9780     pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9781   } else {  
9782     
9783     
9784     emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9785     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9786     
9787     pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9788     pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9789     
9790   }
9791   /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9792   /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9793   /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9794   /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9795   
9796   
9797   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9798   ifx->generated = 1;
9799   return 1;
9800 }
9801
9802 /*-----------------------------------------------------------------*/
9803 /* genReceive - generate code for a receive iCode                  */
9804 /*-----------------------------------------------------------------*/
9805 static void genReceive (iCode *ic)
9806 {
9807   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9808   
9809   if (isOperandInFarSpace(IC_RESULT(ic)) &&
9810     ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9811     IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9812     
9813     int size = getSize(operandType(IC_RESULT(ic)));
9814     int offset =  fReturnSizePic - size;
9815     while (size--) {
9816       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9817         fReturn[fReturnSizePic - offset - 1] : "acc"));
9818       offset++;
9819     }
9820     aopOp(IC_RESULT(ic),ic,FALSE);
9821     size = AOP_SIZE(IC_RESULT(ic));
9822     offset = 0;
9823     while (size--) {
9824       pic14_emitcode ("pop","acc");
9825       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9826     }
9827     
9828   } else {
9829     _G.accInUse++;
9830     aopOp(IC_RESULT(ic),ic,FALSE);
9831     _G.accInUse--;
9832     assignResultValue(IC_RESULT(ic));
9833   }
9834   
9835   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9836 }
9837
9838 /*-----------------------------------------------------------------*/
9839 /* genDummyRead - generate code for dummy read of volatiles        */
9840 /*-----------------------------------------------------------------*/
9841 static void
9842 genDummyRead (iCode * ic)
9843 {
9844   pic14_emitcode ("; genDummyRead","");
9845   pic14_emitcode ("; not implemented","");
9846   
9847   ic = ic;
9848 }
9849
9850 /*-----------------------------------------------------------------*/
9851 /* genpic14Code - generate code for pic14 based controllers        */
9852 /*-----------------------------------------------------------------*/
9853 /*
9854 * At this point, ralloc.c has gone through the iCode and attempted
9855 * to optimize in a way suitable for a PIC. Now we've got to generate
9856 * PIC instructions that correspond to the iCode.
9857 *
9858 * Once the instructions are generated, we'll pass through both the
9859 * peep hole optimizer and the pCode optimizer.
9860 *-----------------------------------------------------------------*/
9861
9862 void genpic14Code (iCode *lic)
9863 {
9864   iCode *ic;
9865   int cln = 0;
9866   
9867   lineHead = lineCurr = NULL;
9868   
9869   pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9870   addpBlock(pb);
9871   
9872   /* if debug information required */
9873   if (options.debug && currFunc) { 
9874     if (currFunc) {
9875       debugFile->writeFunction (currFunc, lic);
9876     }
9877   }
9878   
9879   
9880   for (ic = lic ; ic ; ic = ic->next ) {
9881     
9882     DEBUGpic14_emitcode(";ic","");
9883     if ( cln != ic->lineno ) {
9884       if ( options.debug ) {
9885         debugFile->writeCLine (ic);
9886       }
9887       /*
9888       pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9889       pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9890       printCLine(ic->filename, ic->lineno));
9891       */
9892       if (!options.noCcodeInAsm) {
9893         addpCode2pBlock(pb,
9894           newpCodeCSource(ic->lineno, 
9895           ic->filename, 
9896           printCLine(ic->filename, ic->lineno)));
9897       }
9898       
9899       cln = ic->lineno ;
9900     }
9901     
9902     // if you want printILine too, look at ../mcs51/gen.c, i don't understand this :)
9903     
9904     /* if the result is marked as
9905     spilt and rematerializable or code for
9906     this has already been generated then
9907     do nothing */
9908     if (resultRemat(ic) || ic->generated ) 
9909       continue ;
9910     
9911     /* depending on the operation */
9912     switch (ic->op) {
9913     case '!' :
9914       genNot(ic);
9915       break;
9916       
9917     case '~' :
9918       genCpl(ic);
9919       break;
9920       
9921     case UNARYMINUS:
9922       genUminus (ic);
9923       break;
9924       
9925     case IPUSH:
9926       genIpush (ic);
9927       break;
9928       
9929     case IPOP:
9930     /* IPOP happens only when trying to restore a 
9931     spilt live range, if there is an ifx statement
9932     following this pop then the if statement might
9933     be using some of the registers being popped which
9934     would destory the contents of the register so
9935       we need to check for this condition and handle it */
9936       if (ic->next            && 
9937         ic->next->op == IFX &&
9938         regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9939         genIfx (ic->next,ic);
9940       else
9941         genIpop (ic);
9942       break; 
9943       
9944     case CALL:
9945       genCall (ic);
9946       break;
9947       
9948     case PCALL:
9949       genPcall (ic);
9950       break;
9951       
9952     case FUNCTION:
9953       genFunction (ic);
9954       break;
9955       
9956     case ENDFUNCTION:
9957       genEndFunction (ic);
9958       break;
9959       
9960     case RETURN:
9961       genRet (ic);
9962       break;
9963       
9964     case LABEL:
9965       genLabel (ic);
9966       break;
9967       
9968     case GOTO:
9969       genGoto (ic);
9970       break;
9971       
9972     case '+' :
9973       genPlus (ic) ;
9974       break;
9975       
9976     case '-' :
9977       if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9978         genMinus (ic);
9979       break;
9980       
9981     case '*' :
9982       genMult (ic);
9983       break;
9984       
9985     case '/' :
9986       genDiv (ic) ;
9987       break;
9988       
9989     case '%' :
9990       genMod (ic);
9991       break;
9992       
9993     case '>' :
9994       genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
9995       break;
9996       
9997     case '<' :
9998       genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9999       break;
10000       
10001     case LE_OP:
10002     case GE_OP:
10003     case NE_OP:
10004       
10005     /* note these two are xlated by algebraic equivalence
10006       during parsing SDCC.y */
10007       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10008         "got '>=' or '<=' shouldn't have come here");
10009       break;  
10010       
10011     case EQ_OP:
10012       genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10013       break;      
10014       
10015     case AND_OP:
10016       genAndOp (ic);
10017       break;
10018       
10019     case OR_OP:
10020       genOrOp (ic);
10021       break;
10022       
10023     case '^' :
10024       genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10025       break;
10026       
10027     case '|' :
10028       genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10029       break;
10030       
10031     case BITWISEAND:
10032       genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10033       break;
10034       
10035     case INLINEASM:
10036       genInline (ic);
10037       break;
10038       
10039     case RRC:
10040       genRRC (ic);
10041       break;
10042       
10043     case RLC:
10044       genRLC (ic);
10045       break;
10046       
10047     case GETHBIT:
10048       genGetHbit (ic);
10049       break;
10050       
10051     case LEFT_OP:
10052       genLeftShift (ic);
10053       break;
10054       
10055     case RIGHT_OP:
10056       genRightShift (ic);
10057       break;
10058       
10059     case GET_VALUE_AT_ADDRESS:
10060       genPointerGet(ic);
10061       break;
10062       
10063     case '=' :
10064       if (POINTER_SET(ic))
10065         genPointerSet(ic);
10066       else
10067         genAssign(ic);
10068       break;
10069       
10070     case IFX:
10071       genIfx (ic,NULL);
10072       break;
10073       
10074     case ADDRESS_OF:
10075       genAddrOf (ic);
10076       break;
10077       
10078     case JUMPTABLE:
10079       genJumpTab (ic);
10080       break;
10081       
10082     case CAST:
10083       genCast (ic);
10084       break;
10085       
10086     case RECEIVE:
10087       genReceive(ic);
10088       break;
10089       
10090     case SEND:
10091       addSet(&_G.sendSet,ic);
10092       break;
10093       
10094     case DUMMY_READ_VOLATILE:
10095       genDummyRead (ic);
10096       break;
10097       
10098     default :
10099       ic = ic;
10100     }
10101   }
10102   
10103   
10104   /* now we are ready to call the
10105   peep hole optimizer */
10106   if (!options.nopeep) {
10107     peepHole (&lineHead);
10108   }
10109   /* now do the actual printing */
10110   printLine (lineHead,codeOutFile);
10111   
10112 #ifdef PCODE_DEBUG
10113   DFPRINTF((stderr,"printing pBlock\n\n"));
10114   printpBlock(stdout,pb);
10115 #endif
10116   
10117   return;
10118 }