* src/hc08/gen.c (hc08_emitDebuggerSymbol),
[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 (strcmp(sym1->rname,sym2->rname) == 0)
701     return TRUE;
702   
703   
704   /* if left is a tmp & right is not */
705   if (IS_ITEMP(op1)  && 
706     !IS_ITEMP(op2) &&
707     sym1->isspilt  &&
708     (sym1->usl.spillLoc == sym2))
709     return TRUE;
710   
711   if (IS_ITEMP(op2)  && 
712     !IS_ITEMP(op1) &&
713     sym2->isspilt  &&
714     sym1->level > 0 &&
715     (sym2->usl.spillLoc == sym1))
716     return TRUE ;
717   
718   return FALSE ;
719 }
720
721 /*-----------------------------------------------------------------*/
722 /* pic14_sameRegs - two asmops have the same registers                   */
723 /*-----------------------------------------------------------------*/
724 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
725 {
726   int i;
727   
728   if (aop1 == aop2)
729     return TRUE ;
730   
731   if (aop1->type != AOP_REG ||
732     aop2->type != AOP_REG )
733     return FALSE ;
734   
735   if (aop1->size != aop2->size )
736     return FALSE ;
737   
738   for (i = 0 ; i < aop1->size ; i++ )
739     if (aop1->aopu.aop_reg[i] !=
740       aop2->aopu.aop_reg[i] )
741       return FALSE ;
742     
743     return TRUE ;
744 }
745
746 /*-----------------------------------------------------------------*/
747 /* aopOp - allocates an asmop for an operand  :                    */
748 /*-----------------------------------------------------------------*/
749 void aopOp (operand *op, iCode *ic, bool result)
750 {
751   asmop *aop;
752   symbol *sym;
753   int i;
754   
755   if (!op)
756     return ;
757   
758   //    DEBUGpic14_emitcode(";","%d",__LINE__);
759   /* if this a literal */
760   if (IS_OP_LITERAL(op)) {
761     op->aop = aop = newAsmop(AOP_LIT);
762     aop->aopu.aop_lit = op->operand.valOperand;
763     aop->size = getSize(operandType(op));
764     return;
765   }
766   
767   {
768     sym_link *type = operandType(op);
769     if(IS_PTR_CONST(type))
770       DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
771   }
772   
773   /* if already has a asmop then continue */
774   if (op->aop)
775     return ;
776   
777   /* if the underlying symbol has a aop */
778   if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
779     DEBUGpic14_emitcode(";","%d",__LINE__);
780     op->aop = OP_SYMBOL(op)->aop;
781     return;
782   }
783   
784   /* if this is a true symbol */
785   if (IS_TRUE_SYMOP(op)) {    
786     //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
787     op->aop = aopForSym(ic,OP_SYMBOL(op),result);
788     return ;
789   }
790   
791   /* this is a temporary : this has
792   only four choices :
793   a) register
794   b) spillocation
795   c) rematerialize 
796   d) conditional   
797   e) can be a return use only */
798   
799   sym = OP_SYMBOL(op);
800   
801   
802   /* if the type is a conditional */
803   if (sym->regType == REG_CND) {
804     aop = op->aop = sym->aop = newAsmop(AOP_CRY);
805     aop->size = 0;
806     return;
807   }
808   
809   /* if it is spilt then two situations
810   a) is rematerialize 
811   b) has a spill location */
812   if (sym->isspilt || sym->nRegs == 0) {
813     
814     DEBUGpic14_emitcode(";","%d",__LINE__);
815     /* rematerialize it NOW */
816     if (sym->remat) {
817       
818       sym->aop = op->aop = aop =
819         aopForRemat (op);
820       aop->size = getSize(sym->type);
821       //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
822       return;
823     }
824     
825     if (sym->accuse) {
826       int i;
827       aop = op->aop = sym->aop = newAsmop(AOP_ACC);
828       aop->size = getSize(sym->type);
829       for ( i = 0 ; i < 2 ; i++ )
830         aop->aopu.aop_str[i] = accUse[i];
831       DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
832       return;  
833     }
834     
835     if (sym->ruonly ) {
836       if(sym->isptr) {  // && sym->uptr 
837         aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
838         aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
839         
840         //PCOI(aop->aopu.pcop)->_const = 0;
841         //PCOI(aop->aopu.pcop)->index = 0;
842         /*
843         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
844         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
845         */
846         //allocDirReg (IC_LEFT(ic));
847         
848         aop->size = getSize(sym->type);
849         DEBUGpic14_emitcode(";","%d",__LINE__);
850         return;
851         
852       } else {
853         
854         unsigned i;
855         
856         aop = op->aop = sym->aop = newAsmop(AOP_STR);
857         aop->size = getSize(sym->type);
858         for ( i = 0 ; i < fReturnSizePic ; i++ )
859           aop->aopu.aop_str[i] = fReturn[i];
860         
861         DEBUGpic14_emitcode(";","%d",__LINE__);
862         return;
863       }
864     }
865     
866     /* else spill location  */
867     if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
868       /* force a new aop if sizes differ */
869       sym->usl.spillLoc->aop = NULL;
870     }
871     DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
872       __FUNCTION__,__LINE__,
873       sym->usl.spillLoc->rname,
874       sym->rname, sym->usl.spillLoc->offset);
875     
876     sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
877     //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
878     aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
879       getSize(sym->type), 
880       sym->usl.spillLoc->offset);
881     aop->size = getSize(sym->type);
882     
883     return;
884   }
885   
886   {
887     sym_link *type = operandType(op);
888     if(IS_PTR_CONST(type)) 
889       DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
890   }
891   
892   /* must be in a register */
893   DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
894   sym->aop = op->aop = aop = newAsmop(AOP_REG);
895   aop->size = sym->nRegs;
896   for ( i = 0 ; i < sym->nRegs ;i++)
897     aop->aopu.aop_reg[i] = sym->regs[i];
898 }
899
900 /*-----------------------------------------------------------------*/
901 /* freeAsmop - free up the asmop given to an operand               */
902 /*----------------------------------------------------------------*/
903 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
904 {   
905   asmop *aop ;
906   
907   if (!op)
908     aop = aaop;
909   else 
910     aop = op->aop;
911   
912   if (!aop)
913     return ;
914   
915   if (aop->freed)
916     goto dealloc; 
917   
918   aop->freed = 1;
919   
920   /* depending on the asmop type only three cases need work AOP_RO
921   , AOP_R1 && AOP_STK */
922 #if 0
923   switch (aop->type) {
924   case AOP_R0 :
925     if (_G.r0Pushed ) {
926       if (pop) {
927         pic14_emitcode ("pop","ar0");     
928         _G.r0Pushed--;
929       }
930     }
931     bitVectUnSetBit(ic->rUsed,R0_IDX);
932     break;
933     
934   case AOP_R1 :
935     if (_G.r1Pushed ) {
936       if (pop) {
937         pic14_emitcode ("pop","ar1");
938         _G.r1Pushed--;
939       }
940     }
941     bitVectUnSetBit(ic->rUsed,R1_IDX);          
942     break;
943     
944   case AOP_STK :
945     {
946       int sz = aop->size;    
947       int stk = aop->aopu.aop_stk + aop->size;
948       bitVectUnSetBit(ic->rUsed,R0_IDX);
949       bitVectUnSetBit(ic->rUsed,R1_IDX);          
950       
951       getFreePtr(ic,&aop,FALSE);
952       
953       if (options.stack10bit)
954       {
955         /* I'm not sure what to do here yet... */
956         /* #STUB */
957         fprintf(stderr, 
958           "*** Warning: probably generating bad code for "
959           "10 bit stack mode.\n");
960       }
961       
962       if (stk) {
963         pic14_emitcode ("mov","a,_bp");
964         pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
965         pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
966       } else {
967         pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
968       }
969       
970       while (sz--) {
971         pic14_emitcode("pop","acc");
972         pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
973         if (!sz) break;
974         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
975       }
976       op->aop = aop;
977       freeAsmop(op,NULL,ic,TRUE);
978       if (_G.r0Pushed) {
979         pic14_emitcode("pop","ar0");
980         _G.r0Pushed--;
981       }
982       
983       if (_G.r1Pushed) {
984         pic14_emitcode("pop","ar1");
985         _G.r1Pushed--;
986       }       
987     }
988   }
989 #endif
990   
991 dealloc:
992   /* all other cases just dealloc */
993   if (op ) {
994     op->aop = NULL;
995     if (IS_SYMOP(op)) {
996       OP_SYMBOL(op)->aop = NULL;    
997       /* if the symbol has a spill */
998       if (SPIL_LOC(op))
999         SPIL_LOC(op)->aop = NULL;
1000     }
1001   }
1002 }
1003
1004 /*-----------------------------------------------------------------*/
1005 /* aopGet - for fetching value of the aop                          */
1006 /*-----------------------------------------------------------------*/
1007 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1008 {
1009   char *s = buffer ;
1010   char *rs;
1011   
1012   //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1013   /* offset is greater than
1014   size then zero */
1015   if (offset > (aop->size - 1) &&
1016     aop->type != AOP_LIT)
1017     return zero;
1018   
1019   /* depending on type */
1020   switch (aop->type) {
1021     
1022   case AOP_R0:
1023   case AOP_R1:
1024     DEBUGpic14_emitcode(";","%d",__LINE__);
1025     /* if we need to increment it */       
1026     while (offset > aop->coff) {        
1027       pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1028       aop->coff++;
1029     }
1030     
1031     while (offset < aop->coff) {
1032       pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1033       aop->coff--;
1034     }
1035     
1036     aop->coff = offset ;
1037     if (aop->paged) {
1038       pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1039       return (dname ? "acc" : "a");
1040     }       
1041     sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1042     rs = Safe_calloc(1,strlen(s)+1);
1043     strcpy(rs,s);   
1044     return rs;
1045     
1046   case AOP_DPTR:
1047   case AOP_DPTR2:
1048     DEBUGpic14_emitcode(";","%d",__LINE__);
1049     if (aop->type == AOP_DPTR2)
1050     {
1051       genSetDPTR(1);
1052     }
1053     
1054     while (offset > aop->coff) {
1055       pic14_emitcode ("inc","dptr");
1056       aop->coff++;
1057     }
1058     
1059     while (offset < aop->coff) {        
1060       pic14_emitcode("lcall","__decdptr");
1061       aop->coff--;
1062     }
1063     
1064     aop->coff = offset;
1065     if (aop->code) {
1066       pic14_emitcode("clr","a");
1067       pic14_emitcode("movc","a,@a+dptr");
1068     }
1069     else {
1070       pic14_emitcode("movx","a,@dptr");
1071     }
1072     
1073     if (aop->type == AOP_DPTR2)
1074     {
1075       genSetDPTR(0);
1076     }
1077     
1078     return (dname ? "acc" : "a");
1079     
1080     
1081   case AOP_IMMD:
1082     if (bit16) 
1083       sprintf (s,"%s",aop->aopu.aop_immd);
1084     else
1085       if (offset) 
1086         sprintf(s,"(%s >> %d)",
1087         aop->aopu.aop_immd,
1088         offset*8);
1089       else
1090         sprintf(s,"%s",
1091         aop->aopu.aop_immd);
1092       DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1093       rs = Safe_calloc(1,strlen(s)+1);
1094       strcpy(rs,s);   
1095       return rs;
1096       
1097   case AOP_DIR:
1098     if (offset) {
1099       sprintf(s,"(%s + %d)",
1100         aop->aopu.aop_dir,
1101         offset);
1102       DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1103     } else
1104       sprintf(s,"%s",aop->aopu.aop_dir);
1105     rs = Safe_calloc(1,strlen(s)+1);
1106     strcpy(rs,s);   
1107     return rs;
1108     
1109   case AOP_REG:
1110     //if (dname) 
1111     //    return aop->aopu.aop_reg[offset]->dname;
1112     //else
1113     return aop->aopu.aop_reg[offset]->name;
1114     
1115   case AOP_CRY:
1116     //pic14_emitcode(";","%d",__LINE__);
1117     return aop->aopu.aop_dir;
1118     
1119   case AOP_ACC:
1120     DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1121     return "AOP_accumulator_bug";
1122     
1123   case AOP_LIT:
1124     sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1125     rs = Safe_calloc(1,strlen(s)+1);
1126     strcpy(rs,s);   
1127     return rs;
1128     
1129   case AOP_STR:
1130     aop->coff = offset ;
1131     if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1132       dname)
1133       return "acc";
1134     DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1135     
1136     return aop->aopu.aop_str[offset];
1137     
1138   case AOP_PCODE:
1139     {
1140       pCodeOp *pcop = aop->aopu.pcop;
1141       DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1142       if(pcop->name) {
1143         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1144         //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1145         sprintf(s,"%s", pcop->name);
1146       } else
1147         sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1148       
1149     }
1150     rs = Safe_calloc(1,strlen(s)+1);
1151     strcpy(rs,s);   
1152     return rs;
1153     
1154   }
1155   
1156   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1157     "aopget got unsupported aop->type");
1158   exit(0);
1159 }
1160
1161
1162 /*-----------------------------------------------------------------*/
1163 /* popGetTempReg - create a new temporary pCodeOp                  */
1164 /*-----------------------------------------------------------------*/
1165 pCodeOp *popGetTempReg(void)
1166 {
1167   
1168   pCodeOp *pcop;
1169   
1170   pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1171   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1172     PCOR(pcop)->r->wasUsed=1;
1173     PCOR(pcop)->r->isFree=0;
1174   }
1175   
1176   return pcop;
1177 }
1178
1179 /*-----------------------------------------------------------------*/
1180 /* popGetTempReg - create a new temporary pCodeOp                  */
1181 /*-----------------------------------------------------------------*/
1182 void popReleaseTempReg(pCodeOp *pcop)
1183 {
1184   
1185   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1186     PCOR(pcop)->r->isFree = 1;
1187   
1188 }
1189 /*-----------------------------------------------------------------*/
1190 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1191 /*-----------------------------------------------------------------*/
1192 pCodeOp *popGetLabel(unsigned int key)
1193 {
1194   
1195   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1196   
1197   if(key>(unsigned int)max_key)
1198     max_key = key;
1199   
1200   return newpCodeOpLabel(NULL,key+100+labelOffset);
1201 }
1202
1203 /*-------------------------------------------------------------------*/
1204 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1205 /*-------------------------------------------------------------------*/
1206 pCodeOp *popGetHighLabel(unsigned int key)
1207 {
1208   pCodeOp *pcop;
1209   pcop = popGetLabel(key);
1210   PCOLAB(pcop)->offset = 1;
1211   return pcop;
1212 }
1213
1214 /*-----------------------------------------------------------------*/
1215 /* popGet - asm operator to pcode operator conversion              */
1216 /*-----------------------------------------------------------------*/
1217 pCodeOp *popGetLit(unsigned int lit)
1218 {
1219   
1220   return newpCodeOpLit(lit);
1221 }
1222
1223 /*-----------------------------------------------------------------*/
1224 /* popGetImmd - asm operator to pcode immediate conversion         */
1225 /*-----------------------------------------------------------------*/
1226 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1227 {
1228   
1229   return newpCodeOpImmd(name, offset,index, 0, is_func);
1230 }
1231
1232
1233 /*-----------------------------------------------------------------*/
1234 /* popGet - asm operator to pcode operator conversion              */
1235 /*-----------------------------------------------------------------*/
1236 pCodeOp *popGetWithString(char *str, int isExtern)
1237 {
1238   pCodeOp *pcop;
1239   
1240   
1241   if(!str) {
1242     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1243     exit (1);
1244   }
1245   
1246   pcop = newpCodeOp(str,PO_STR);
1247   PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1248   
1249   return pcop;
1250 }
1251
1252 /*-----------------------------------------------------------------*/
1253 /* popRegFromString -                                              */
1254 /*-----------------------------------------------------------------*/
1255 pCodeOp *popRegFromString(char *str, int size, int offset)
1256 {
1257   
1258   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1259   pcop->type = PO_DIR;
1260   
1261   DEBUGpic14_emitcode(";","%d",__LINE__);
1262   
1263   if(!str)
1264     str = "BAD_STRING";
1265   
1266   pcop->name = Safe_calloc(1,strlen(str)+1);
1267   strcpy(pcop->name,str);
1268   
1269   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1270   
1271   PCOR(pcop)->r = dirregWithName(pcop->name);
1272   if(PCOR(pcop)->r == NULL) {
1273     //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1274     PCOR(pcop)->r = allocRegByName (pcop->name,size);
1275     DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1276   } else {
1277     DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1278   }
1279   PCOR(pcop)->instance = offset;
1280   
1281   return pcop;
1282 }
1283
1284 /*-----------------------------------------------------------------*/
1285 /*-----------------------------------------------------------------*/
1286 pCodeOp *popRegFromIdx(int rIdx)
1287 {
1288   pCodeOp *pcop;
1289   
1290   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1291     __FUNCTION__,__LINE__,rIdx);
1292   
1293   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1294   
1295   PCOR(pcop)->rIdx = rIdx;
1296   PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1297   PCOR(pcop)->r->isFree = 0;
1298   PCOR(pcop)->r->wasUsed = 1;
1299   
1300   pcop->type = PCOR(pcop)->r->pc_type;
1301   
1302   
1303   return pcop;
1304 }
1305
1306 /*-----------------------------------------------------------------*/
1307 /* popGet - asm operator to pcode operator conversion              */
1308 /*-----------------------------------------------------------------*/
1309 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1310 {
1311   //char *s = buffer ;
1312   //char *rs;
1313   
1314   pCodeOp *pcop;
1315   
1316   //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1317   /* offset is greater than
1318   size then zero */
1319   
1320   if (offset > (aop->size - 1) &&
1321     aop->type != AOP_LIT)
1322     return NULL;  //zero;
1323   
1324   /* depending on type */
1325   switch (aop->type) {
1326     
1327   case AOP_R0:
1328   case AOP_R1:
1329   case AOP_DPTR:
1330   case AOP_DPTR2:
1331   case AOP_ACC:
1332     DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1333     return NULL;
1334     
1335   case AOP_IMMD:
1336     DEBUGpic14_emitcode(";","%d",__LINE__);
1337     return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1338     
1339   case AOP_DIR:
1340     return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1341 #if 0
1342     pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1343     pcop->type = PO_DIR;
1344     
1345     /*
1346     if (offset)
1347     sprintf(s,"(%s + %d)",
1348     aop->aopu.aop_dir,
1349     offset);
1350     else
1351     sprintf(s,"%s",aop->aopu.aop_dir);
1352     pcop->name = Safe_calloc(1,strlen(s)+1);
1353     strcpy(pcop->name,s);   
1354     */
1355     pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1356     strcpy(pcop->name,aop->aopu.aop_dir);   
1357     PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1358     if(PCOR(pcop)->r == NULL) {
1359       //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1360       PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1361       DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1362     } else {
1363       DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1364     }
1365     PCOR(pcop)->instance = offset;
1366     
1367     return pcop;
1368 #endif
1369     
1370   case AOP_REG:
1371     {
1372       int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1373       
1374       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1375       PCOR(pcop)->rIdx = rIdx;
1376       PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1377       PCOR(pcop)->r->wasUsed=1;
1378       PCOR(pcop)->r->isFree=0;
1379       
1380       PCOR(pcop)->instance = offset;
1381       pcop->type = PCOR(pcop)->r->pc_type;
1382       //rs = aop->aopu.aop_reg[offset]->name;
1383       DEBUGpic14_emitcode(";","%d regiser idx = %d ",__LINE__,rIdx);
1384       return pcop;
1385     }
1386     
1387   case AOP_CRY:
1388     pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1389     PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1390     //if(PCOR(pcop)->r == NULL)
1391     //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1392     return pcop;
1393     
1394   case AOP_LIT:
1395     return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1396     
1397   case AOP_STR:
1398     DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1399     return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1400     /*
1401     pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1402     PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1403     PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1404     pcop->type = PCOR(pcop)->r->pc_type;
1405     pcop->name = PCOR(pcop)->r->name;
1406     
1407       return pcop;
1408     */
1409     
1410   case AOP_PCODE:
1411     DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s) %d %s",pCodeOpType(aop->aopu.pcop),
1412       __LINE__, 
1413       ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1414     pcop = pCodeOpCopy(aop->aopu.pcop);
1415     PCOI(pcop)->offset = offset;
1416     return pcop;
1417   }
1418   
1419   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1420     "popGet got unsupported aop->type");
1421   exit(0);
1422 }
1423 /*-----------------------------------------------------------------*/
1424 /* aopPut - puts a string for a aop                                */
1425 /*-----------------------------------------------------------------*/
1426 void aopPut (asmop *aop, char *s, int offset)
1427 {
1428   char *d = buffer ;
1429   symbol *lbl ;
1430   
1431   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1432   
1433   if (aop->size && offset > ( aop->size - 1)) {
1434     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1435       "aopPut got offset > aop->size");
1436     exit(0);
1437   }
1438   
1439   /* will assign value to value */
1440   /* depending on where it is ofcourse */
1441   switch (aop->type) {
1442   case AOP_DIR:
1443     if (offset) {
1444       sprintf(d,"(%s + %d)",
1445         aop->aopu.aop_dir,offset);
1446       fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1447       
1448     } else
1449       sprintf(d,"%s",aop->aopu.aop_dir);
1450     
1451     if (strcmp(d,s)) {
1452       DEBUGpic14_emitcode(";","%d",__LINE__);
1453       if(strcmp(s,"W"))
1454         pic14_emitcode("movf","%s,w",s);
1455       pic14_emitcode("movwf","%s",d);
1456       
1457       if(strcmp(s,"W")) {
1458         pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1459         if(offset >= aop->size) {
1460           emitpcode(POC_CLRF,popGet(aop,offset));
1461           break;
1462         } else
1463           emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1464       }
1465       
1466       emitpcode(POC_MOVWF,popGet(aop,offset));
1467       
1468       
1469     }
1470     break;
1471     
1472   case AOP_REG:
1473     if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1474       //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1475       /*
1476       if (*s == '@'           ||
1477       strcmp(s,"r0") == 0 ||
1478       strcmp(s,"r1") == 0 ||
1479       strcmp(s,"r2") == 0 ||
1480       strcmp(s,"r3") == 0 ||
1481       strcmp(s,"r4") == 0 ||
1482       strcmp(s,"r5") == 0 ||
1483       strcmp(s,"r6") == 0 || 
1484       strcmp(s,"r7") == 0 )
1485       pic14_emitcode("mov","%s,%s  ; %d",
1486       aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1487       else
1488       */
1489       
1490       if(strcmp(s,"W")==0 )
1491         pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1492       
1493       pic14_emitcode("movwf","%s",
1494         aop->aopu.aop_reg[offset]->name);
1495       
1496       if(strcmp(s,zero)==0) {
1497         emitpcode(POC_CLRF,popGet(aop,offset));
1498         
1499       } else if(strcmp(s,"W")==0) {
1500         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1501         pcop->type = PO_GPR_REGISTER;
1502         
1503         PCOR(pcop)->rIdx = -1;
1504         PCOR(pcop)->r = NULL;
1505         
1506         DEBUGpic14_emitcode(";","%d",__LINE__);
1507         pcop->name = Safe_strdup(s);
1508         emitpcode(POC_MOVFW,pcop);
1509         emitpcode(POC_MOVWF,popGet(aop,offset));
1510       } else if(strcmp(s,one)==0) {
1511         emitpcode(POC_CLRF,popGet(aop,offset));
1512         emitpcode(POC_INCF,popGet(aop,offset));
1513       } else {
1514         emitpcode(POC_MOVWF,popGet(aop,offset));
1515       }
1516     }
1517     break;
1518     
1519   case AOP_DPTR:
1520   case AOP_DPTR2:
1521     
1522     if (aop->type == AOP_DPTR2)
1523     {
1524       genSetDPTR(1);
1525     }
1526     
1527     if (aop->code) {
1528       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1529         "aopPut writting to code space");
1530       exit(0);
1531     }
1532     
1533     while (offset > aop->coff) {
1534       aop->coff++;
1535       pic14_emitcode ("inc","dptr");
1536     }
1537     
1538     while (offset < aop->coff) {
1539       aop->coff-- ;
1540       pic14_emitcode("lcall","__decdptr");
1541     }
1542     
1543     aop->coff = offset;
1544     
1545     /* if not in accumulater */
1546     MOVA(s);
1547     
1548     pic14_emitcode ("movx","@dptr,a");
1549     
1550     if (aop->type == AOP_DPTR2)
1551     {
1552       genSetDPTR(0);
1553     }
1554     break;
1555     
1556   case AOP_R0:
1557   case AOP_R1:
1558     while (offset > aop->coff) {
1559       aop->coff++;
1560       pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1561     }
1562     while (offset < aop->coff) {
1563       aop->coff-- ;
1564       pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1565     }
1566     aop->coff = offset;
1567     
1568     if (aop->paged) {
1569       MOVA(s);           
1570       pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1571       
1572     } else
1573       if (*s == '@') {
1574         MOVA(s);
1575         pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1576       } else
1577         if (strcmp(s,"r0") == 0 ||
1578           strcmp(s,"r1") == 0 ||
1579           strcmp(s,"r2") == 0 ||
1580           strcmp(s,"r3") == 0 ||
1581           strcmp(s,"r4") == 0 ||
1582           strcmp(s,"r5") == 0 ||
1583           strcmp(s,"r6") == 0 || 
1584           strcmp(s,"r7") == 0 ) {
1585           char buffer[10];
1586           sprintf(buffer,"a%s",s);
1587           pic14_emitcode("mov","@%s,%s",
1588             aop->aopu.aop_ptr->name,buffer);
1589         } else
1590           pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1591         
1592         break;
1593         
1594   case AOP_STK:
1595     if (strcmp(s,"a") == 0)
1596       pic14_emitcode("push","acc");
1597     else
1598       pic14_emitcode("push","%s",s);
1599     
1600     break;
1601     
1602   case AOP_CRY:
1603     /* if bit variable */
1604     if (!aop->aopu.aop_dir) {
1605       pic14_emitcode("clr","a");
1606       pic14_emitcode("rlc","a");
1607     } else {
1608       if (s == zero) 
1609         pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1610       else
1611         if (s == one)
1612           pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1613         else
1614           if (!strcmp(s,"c"))
1615             pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1616           else {
1617             lbl = newiTempLabel(NULL);
1618             
1619             if (strcmp(s,"a")) {
1620               MOVA(s);
1621             }
1622             pic14_emitcode("clr","c");
1623             pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1624             pic14_emitcode("cpl","c");
1625             pic14_emitcode("","%05d_DS_:",lbl->key+100);
1626             pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1627           }
1628     }
1629     break;
1630     
1631   case AOP_STR:
1632     aop->coff = offset;
1633     if (strcmp(aop->aopu.aop_str[offset],s))
1634       pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1635     break;
1636     
1637   case AOP_ACC:
1638     aop->coff = offset;
1639     if (!offset && (strcmp(s,"acc") == 0))
1640       break;
1641     
1642     if (strcmp(aop->aopu.aop_str[offset],s))
1643       pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1644     break;
1645     
1646   default :
1647     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1648       "aopPut got unsupported aop->type");
1649     exit(0);    
1650   }    
1651   
1652 }
1653
1654 /*-----------------------------------------------------------------*/
1655 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1656 /*-----------------------------------------------------------------*/
1657 void mov2w (asmop *aop, int offset)
1658 {
1659   
1660   if(!aop)
1661     return;
1662   
1663   DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1664   
1665   if ( aop->type == AOP_PCODE ||
1666     aop->type == AOP_LIT ||
1667     aop->type == AOP_IMMD )
1668     emitpcode(POC_MOVLW,popGet(aop,offset));
1669   else
1670     emitpcode(POC_MOVFW,popGet(aop,offset));
1671   
1672 }
1673
1674 /*-----------------------------------------------------------------*/
1675 /* reAdjustPreg - points a register back to where it should        */
1676 /*-----------------------------------------------------------------*/
1677 static void reAdjustPreg (asmop *aop)
1678 {
1679   int size ;
1680   
1681   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1682   aop->coff = 0;
1683   if ((size = aop->size) <= 1)
1684     return ;
1685   size-- ;
1686   switch (aop->type) {
1687   case AOP_R0 :
1688   case AOP_R1 :
1689     while (size--)
1690       pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1691     break;          
1692   case AOP_DPTR :
1693   case AOP_DPTR2:
1694     if (aop->type == AOP_DPTR2)
1695     {
1696       genSetDPTR(1);
1697     } 
1698     while (size--)
1699     {
1700       pic14_emitcode("lcall","__decdptr");
1701     }
1702     
1703     if (aop->type == AOP_DPTR2)
1704     {
1705       genSetDPTR(0);
1706     }
1707     break;
1708     
1709   }
1710   
1711 }
1712
1713
1714 #if 0
1715 /*-----------------------------------------------------------------*/
1716 /* opIsGptr: returns non-zero if the passed operand is       */   
1717 /* a generic pointer type.             */
1718 /*-----------------------------------------------------------------*/ 
1719 static int opIsGptr(operand *op)
1720 {
1721   sym_link *type = operandType(op);
1722   
1723   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1724   if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1725   {
1726     return 1;
1727   }
1728   return 0;        
1729 }
1730 #endif
1731
1732 /*-----------------------------------------------------------------*/
1733 /* pic14_getDataSize - get the operand data size                         */
1734 /*-----------------------------------------------------------------*/
1735 int pic14_getDataSize(operand *op)
1736 {
1737   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1738   
1739   
1740   return AOP_SIZE(op);
1741   
1742   // tsd- in the pic port, the genptr size is 1, so this code here
1743   // fails. ( in the 8051 port, the size was 4).
1744 #if 0
1745   int size;
1746   size = AOP_SIZE(op);
1747   if (size == GPTRSIZE)
1748   {
1749     sym_link *type = operandType(op);
1750     if (IS_GENPTR(type))
1751     {
1752     /* generic pointer; arithmetic operations
1753     * should ignore the high byte (pointer type).
1754       */
1755       size--;
1756       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1757     }
1758   }
1759   return size;
1760 #endif
1761 }
1762
1763 /*-----------------------------------------------------------------*/
1764 /* pic14_outAcc - output Acc                                             */
1765 /*-----------------------------------------------------------------*/
1766 void pic14_outAcc(operand *result)
1767 {
1768   int size,offset;
1769   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1770   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1771   
1772   
1773   size = pic14_getDataSize(result);
1774   if(size){
1775     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1776     size--;
1777     offset = 1;
1778     /* unsigned or positive */
1779     while(size--)
1780       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1781   }
1782   
1783 }
1784
1785 /*-----------------------------------------------------------------*/
1786 /* pic14_outBitC - output a bit C                                        */
1787 /*-----------------------------------------------------------------*/
1788 void pic14_outBitC(operand *result)
1789 {
1790   
1791   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1792   /* if the result is bit */
1793   if (AOP_TYPE(result) == AOP_CRY) 
1794     aopPut(AOP(result),"c",0);
1795   else {
1796     pic14_emitcode("clr","a  ; %d", __LINE__);
1797     pic14_emitcode("rlc","a");
1798     pic14_outAcc(result);
1799   }
1800 }
1801
1802 /*-----------------------------------------------------------------*/
1803 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1804 /*-----------------------------------------------------------------*/
1805 void pic14_toBoolean(operand *oper)
1806 {
1807   int size = AOP_SIZE(oper) - 1;
1808   int offset = 1;
1809   
1810   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1811   
1812   if ( AOP_TYPE(oper) != AOP_ACC) {
1813     emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1814   }
1815   while (size--) {
1816     emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1817   }
1818 }
1819
1820
1821 /*-----------------------------------------------------------------*/
1822 /* genNot - generate code for ! operation                          */
1823 /*-----------------------------------------------------------------*/
1824 static void genNot (iCode *ic)
1825 {
1826   symbol *tlbl;
1827   int size;
1828   
1829   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1830   /* assign asmOps to operand & result */
1831   aopOp (IC_LEFT(ic),ic,FALSE);
1832   aopOp (IC_RESULT(ic),ic,TRUE);
1833   
1834   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1835   /* if in bit space then a special case */
1836   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1837     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1838       emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1839       emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1840     } else {
1841       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1842       emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1843       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1844     }
1845     goto release;
1846   }
1847   
1848   size = AOP_SIZE(IC_LEFT(ic));
1849   if(size == 1) {
1850     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1851     emitpcode(POC_ANDLW,popGetLit(1));
1852     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1853     goto release;
1854   }
1855   pic14_toBoolean(IC_LEFT(ic));
1856   
1857   tlbl = newiTempLabel(NULL);
1858   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1859   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1860   pic14_outBitC(IC_RESULT(ic));
1861   
1862 release:    
1863   /* release the aops */
1864   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1865   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1866 }
1867
1868
1869 /*-----------------------------------------------------------------*/
1870 /* genCpl - generate code for complement                           */
1871 /*-----------------------------------------------------------------*/
1872 static void genCpl (iCode *ic)
1873 {
1874   operand *left, *result;
1875   int size, offset=0;  
1876   
1877   
1878   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1879   aopOp((left = IC_LEFT(ic)),ic,FALSE);
1880   aopOp((result=IC_RESULT(ic)),ic,TRUE);
1881   
1882   /* if both are in bit space then 
1883   a special case */
1884   if (AOP_TYPE(result) == AOP_CRY &&
1885     AOP_TYPE(left) == AOP_CRY ) { 
1886     
1887     pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
1888     pic14_emitcode("cpl","c"); 
1889     pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
1890     goto release; 
1891   } 
1892   
1893   size = AOP_SIZE(result);
1894   while (size--) {
1895     
1896     if(AOP_TYPE(left) == AOP_ACC) 
1897       emitpcode(POC_XORLW, popGetLit(0xff));
1898     else
1899       emitpcode(POC_COMFW,popGet(AOP(left),offset));
1900     
1901     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1902     offset++;
1903   }
1904   
1905   
1906 release:
1907   /* release the aops */
1908   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1909   freeAsmop(result,NULL,ic,TRUE);
1910 }
1911
1912 /*-----------------------------------------------------------------*/
1913 /* genUminusFloat - unary minus for floating points                */
1914 /*-----------------------------------------------------------------*/
1915 static void genUminusFloat(operand *op,operand *result)
1916 {
1917   int size ,offset =0 ;
1918   char *l;
1919   
1920   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1921   /* for this we just need to flip the 
1922   first it then copy the rest in place */
1923   size = AOP_SIZE(op) - 1;
1924   l = aopGet(AOP(op),3,FALSE,FALSE);
1925   
1926   MOVA(l);    
1927   
1928   pic14_emitcode("cpl","acc.7");
1929   aopPut(AOP(result),"a",3);    
1930   
1931   while(size--) {
1932     aopPut(AOP(result),
1933       aopGet(AOP(op),offset,FALSE,FALSE),
1934       offset);
1935     offset++;
1936   }          
1937 }
1938
1939 /*-----------------------------------------------------------------*/
1940 /* genUminus - unary minus code generation                         */
1941 /*-----------------------------------------------------------------*/
1942 static void genUminus (iCode *ic)
1943 {
1944   int size, i;
1945   sym_link *optype, *rtype;
1946   
1947   
1948   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1949   /* assign asmops */
1950   aopOp(IC_LEFT(ic),ic,FALSE);
1951   aopOp(IC_RESULT(ic),ic,TRUE);
1952   
1953   /* if both in bit space then special
1954   case */
1955   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1956     AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1957     
1958     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1959     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1960     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1961     
1962     goto release; 
1963   } 
1964   
1965   optype = operandType(IC_LEFT(ic));
1966   rtype = operandType(IC_RESULT(ic));
1967   
1968   /* if float then do float stuff */
1969   if (IS_FLOAT(optype)) {
1970     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1971     goto release;
1972   }
1973   
1974   /* otherwise subtract from zero by taking the 2's complement */
1975   size = AOP_SIZE(IC_LEFT(ic));
1976   
1977   for(i=0; i<size; i++) {
1978     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1979       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1980     else {
1981       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1982       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1983     }
1984   }
1985   
1986   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
1987   for(i=1; i<size; i++) {
1988     emitSKPNZ;
1989     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
1990   }
1991   
1992 release:
1993   /* release the aops */
1994   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1995   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1996 }
1997
1998 /*-----------------------------------------------------------------*/
1999 /* saveRegisters - will look for a call and save the registers     */
2000 /*-----------------------------------------------------------------*/
2001 static void saveRegisters(iCode *lic) 
2002 {
2003   int i;
2004   iCode *ic;
2005   bitVect *rsave;
2006   sym_link *dtype;
2007   
2008   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2009   /* look for call */
2010   for (ic = lic ; ic ; ic = ic->next) 
2011     if (ic->op == CALL || ic->op == PCALL)
2012       break;
2013     
2014     if (!ic) {
2015       fprintf(stderr,"found parameter push with no function call\n");
2016       return ;
2017     }
2018     
2019     /* if the registers have been saved already then
2020     do nothing */
2021     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2022       return ;
2023     
2024       /* find the registers in use at this time 
2025     and push them away to safety */
2026     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2027       ic->rUsed);
2028     
2029     ic->regsSaved = 1;
2030     if (options.useXstack) {
2031       if (bitVectBitValue(rsave,R0_IDX))
2032         pic14_emitcode("mov","b,r0");
2033       pic14_emitcode("mov","r0,%s",spname);
2034       for (i = 0 ; i < pic14_nRegs ; i++) {
2035         if (bitVectBitValue(rsave,i)) {
2036           if (i == R0_IDX)
2037             pic14_emitcode("mov","a,b");
2038           else
2039             pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2040           pic14_emitcode("movx","@r0,a");
2041           pic14_emitcode("inc","r0");
2042         }
2043       }
2044       pic14_emitcode("mov","%s,r0",spname);
2045       if (bitVectBitValue(rsave,R0_IDX))
2046         pic14_emitcode("mov","r0,b");     
2047     }// else
2048     //for (i = 0 ; i < pic14_nRegs ; i++) {
2049     //    if (bitVectBitValue(rsave,i))
2050     //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2051     //}
2052     
2053     dtype = operandType(IC_LEFT(ic));
2054     if (currFunc && dtype && 
2055       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2056       IFFUNC_ISISR(currFunc->type) &&
2057       !ic->bankSaved) 
2058       
2059       saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2060     
2061 }
2062 /*-----------------------------------------------------------------*/
2063 /* unsaveRegisters - pop the pushed registers                      */
2064 /*-----------------------------------------------------------------*/
2065 static void unsaveRegisters (iCode *ic)
2066 {
2067   int i;
2068   bitVect *rsave;
2069   
2070   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2071   /* find the registers in use at this time 
2072   and push them away to safety */
2073   rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2074     ic->rUsed);
2075   
2076   if (options.useXstack) {
2077     pic14_emitcode("mov","r0,%s",spname); 
2078     for (i =  pic14_nRegs ; i >= 0 ; i--) {
2079       if (bitVectBitValue(rsave,i)) {
2080         pic14_emitcode("dec","r0");
2081         pic14_emitcode("movx","a,@r0");
2082         if (i == R0_IDX)
2083           pic14_emitcode("mov","b,a");
2084         else
2085           pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2086       }     
2087       
2088     }
2089     pic14_emitcode("mov","%s,r0",spname);
2090     if (bitVectBitValue(rsave,R0_IDX))
2091       pic14_emitcode("mov","r0,b");
2092   } //else
2093   //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2094   //    if (bitVectBitValue(rsave,i))
2095   //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2096   //}
2097   
2098 }  
2099
2100
2101 /*-----------------------------------------------------------------*/
2102 /* pushSide -                */
2103 /*-----------------------------------------------------------------*/
2104 static void pushSide(operand * oper, int size)
2105 {
2106 #if 0
2107   int offset = 0;
2108   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2109   while (size--) {
2110     char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2111     if (AOP_TYPE(oper) != AOP_REG &&
2112       AOP_TYPE(oper) != AOP_DIR &&
2113       strcmp(l,"a") ) {
2114       pic14_emitcode("mov","a,%s",l);
2115       pic14_emitcode("push","acc");
2116     } else
2117       pic14_emitcode("push","%s",l);
2118   }
2119 #endif
2120 }
2121
2122 /*-----------------------------------------------------------------*/
2123 /* assignResultValue -               */
2124 /*-----------------------------------------------------------------*/
2125 static void assignResultValue(operand * oper)
2126 {
2127   int size = AOP_SIZE(oper);
2128   
2129   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2130   
2131   DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2132   
2133   while (size--) {
2134     if (GpsuedoStkPtr++)
2135       emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2136     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2137   }
2138 }
2139
2140
2141 /*-----------------------------------------------------------------*/
2142 /* genIpush - genrate code for pushing this gets a little complex  */
2143 /*-----------------------------------------------------------------*/
2144 static void genIpush (iCode *ic)
2145 {
2146   
2147   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2148 #if 0
2149   int size, offset = 0 ;
2150   char *l;
2151   
2152   
2153   /* if this is not a parm push : ie. it is spill push 
2154   and spill push is always done on the local stack */
2155   if (!ic->parmPush) {
2156     
2157     /* and the item is spilt then do nothing */
2158     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2159       return ;
2160     
2161     aopOp(IC_LEFT(ic),ic,FALSE);
2162     size = AOP_SIZE(IC_LEFT(ic));
2163     /* push it on the stack */
2164     while(size--) {
2165       l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2166       if (*l == '#') {
2167         MOVA(l);
2168         l = "acc";
2169       }
2170       pic14_emitcode("push","%s",l);
2171     }
2172     return ;        
2173   }
2174   
2175   /* this is a paramter push: in this case we call
2176   the routine to find the call and save those
2177   registers that need to be saved */   
2178   saveRegisters(ic);
2179   
2180   /* then do the push */
2181   aopOp(IC_LEFT(ic),ic,FALSE);
2182   
2183   
2184   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2185   size = AOP_SIZE(IC_LEFT(ic));
2186   
2187   while (size--) {
2188     l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2189     if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2190       AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2191       strcmp(l,"a") ) {
2192       pic14_emitcode("mov","a,%s",l);
2193       pic14_emitcode("push","acc");
2194     } else
2195       pic14_emitcode("push","%s",l);
2196   }       
2197   
2198   freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2199 #endif
2200 }
2201
2202 /*-----------------------------------------------------------------*/
2203 /* genIpop - recover the registers: can happen only for spilling   */
2204 /*-----------------------------------------------------------------*/
2205 static void genIpop (iCode *ic)
2206 {
2207   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2208 #if 0
2209   int size,offset ;
2210   
2211   
2212   /* if the temp was not pushed then */
2213   if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2214     return ;
2215   
2216   aopOp(IC_LEFT(ic),ic,FALSE);
2217   size = AOP_SIZE(IC_LEFT(ic));
2218   offset = (size-1);
2219   while (size--) 
2220     pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2221     FALSE,TRUE));
2222   
2223   freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2224 #endif
2225 }
2226
2227 /*-----------------------------------------------------------------*/
2228 /* unsaverbank - restores the resgister bank from stack            */
2229 /*-----------------------------------------------------------------*/
2230 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2231 {
2232   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2233 #if 0
2234   int i;
2235   asmop *aop ;
2236   regs *r = NULL;
2237   
2238   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2239   if (popPsw) {
2240     if (options.useXstack) {
2241       aop = newAsmop(0);
2242       r = getFreePtr(ic,&aop,FALSE);
2243       
2244       
2245       pic14_emitcode("mov","%s,_spx",r->name);
2246       pic14_emitcode("movx","a,@%s",r->name);
2247       pic14_emitcode("mov","psw,a");
2248       pic14_emitcode("dec","%s",r->name);
2249       
2250     }else
2251       pic14_emitcode ("pop","psw");
2252   }
2253   
2254   for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2255     if (options.useXstack) {       
2256       pic14_emitcode("movx","a,@%s",r->name);
2257       //pic14_emitcode("mov","(%s+%d),a",
2258       //       regspic14[i].base,8*bank+regspic14[i].offset);
2259       pic14_emitcode("dec","%s",r->name);
2260       
2261     } else 
2262       pic14_emitcode("pop",""); //"(%s+%d)",
2263     //regspic14[i].base,8*bank); //+regspic14[i].offset);
2264   }
2265   
2266   if (options.useXstack) {
2267     
2268     pic14_emitcode("mov","_spx,%s",r->name);
2269     freeAsmop(NULL,aop,ic,TRUE);
2270     
2271   }
2272 #endif 
2273 }
2274
2275 /*-----------------------------------------------------------------*/
2276 /* saverbank - saves an entire register bank on the stack          */
2277 /*-----------------------------------------------------------------*/
2278 static void saverbank (int bank, iCode *ic, bool pushPsw)
2279 {
2280   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2281 #if 0
2282   int i;
2283   asmop *aop ;
2284   regs *r = NULL;
2285   
2286   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2287   if (options.useXstack) {
2288     
2289     aop = newAsmop(0);
2290     r = getFreePtr(ic,&aop,FALSE);  
2291     pic14_emitcode("mov","%s,_spx",r->name);
2292     
2293   }
2294   
2295   for (i = 0 ; i < pic14_nRegs ;i++) {
2296     if (options.useXstack) {
2297       pic14_emitcode("inc","%s",r->name);
2298       //pic14_emitcode("mov","a,(%s+%d)",
2299       //         regspic14[i].base,8*bank+regspic14[i].offset);
2300       pic14_emitcode("movx","@%s,a",r->name);           
2301     } else 
2302       pic14_emitcode("push","");// "(%s+%d)",
2303     //regspic14[i].base,8*bank+regspic14[i].offset);
2304   }
2305   
2306   if (pushPsw) {
2307     if (options.useXstack) {
2308       pic14_emitcode("mov","a,psw");
2309       pic14_emitcode("movx","@%s,a",r->name); 
2310       pic14_emitcode("inc","%s",r->name);
2311       pic14_emitcode("mov","_spx,%s",r->name);       
2312       freeAsmop (NULL,aop,ic,TRUE);
2313       
2314     } else
2315       pic14_emitcode("push","psw");
2316     
2317     pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2318   }
2319   ic->bankSaved = 1;
2320 #endif
2321 }
2322
2323 /*-----------------------------------------------------------------*/
2324 /* genCall - generates a call statement                            */
2325 /*-----------------------------------------------------------------*/
2326 static void genCall (iCode *ic)
2327 {
2328   sym_link *dtype;   
2329   symbol *sym;
2330   unsigned char *name;
2331   int isExtern;
2332   
2333   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2334   
2335   /* if caller saves & we have not saved then */
2336   if (!ic->regsSaved)
2337     saveRegisters(ic);
2338   
2339     /* if we are calling a function that is not using
2340     the same register bank then we need to save the
2341   destination registers on the stack */
2342   dtype = operandType(IC_LEFT(ic));
2343   if (currFunc && dtype && 
2344     (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2345     IFFUNC_ISISR(currFunc->type) &&
2346     !ic->bankSaved) 
2347     
2348     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2349   
2350   /* if send set is not empty the assign */
2351   if (_G.sendSet) {
2352     iCode *sic;
2353     /* For the Pic port, there is no data stack.
2354     * So parameters passed to functions are stored
2355     * in registers. (The pCode optimizer will get
2356     * rid of most of these :).
2357     */
2358     int psuedoStkPtr=-1;
2359     int firstTimeThruLoop = 1;
2360     
2361     _G.sendSet = reverseSet(_G.sendSet);
2362     
2363     /* First figure how many parameters are getting passed */
2364     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2365     sic = setNextItem(_G.sendSet)) {
2366       
2367       aopOp(IC_LEFT(sic),sic,FALSE);
2368       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2369       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2370     }
2371     
2372     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2373     sic = setNextItem(_G.sendSet)) {
2374       int size, offset = 0;
2375       
2376       aopOp(IC_LEFT(sic),sic,FALSE);
2377       size = AOP_SIZE(IC_LEFT(sic));
2378       
2379       while (size--) {
2380         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2381           AopType(AOP_TYPE(IC_LEFT(sic))));
2382         
2383         if(!firstTimeThruLoop) {
2384         /* If this is not the first time we've been through the loop
2385         * then we need to save the parameter in a temporary
2386         * register. The last byte of the last parameter is
2387           * passed in W. */
2388           emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2389           
2390         }
2391         firstTimeThruLoop=0;
2392         
2393         mov2w (AOP(IC_LEFT(sic)),  offset);
2394         offset++;
2395       }
2396       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2397     }
2398     _G.sendSet = NULL;
2399   }
2400   /* make the call */
2401   sym = OP_SYMBOL(IC_LEFT(ic));
2402   name = sym->rname[0] ? sym->rname : sym->name;
2403   isExtern = IS_EXTERN(sym->etype);
2404   if (isExtern) {
2405     emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2406   }
2407   emitpcode(POC_CALL,popGetWithString(name,isExtern));
2408   if (isExtern) {
2409     emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel */
2410   }
2411   GpsuedoStkPtr=0;
2412   /* if we need assign a result value */
2413   if ((IS_ITEMP(IC_RESULT(ic)) && 
2414     (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2415     OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2416     IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2417     
2418     _G.accInUse++;
2419     aopOp(IC_RESULT(ic),ic,FALSE);
2420     _G.accInUse--;
2421     
2422     assignResultValue(IC_RESULT(ic));
2423     
2424     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2425       AopType(AOP_TYPE(IC_RESULT(ic))));
2426     
2427     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2428   }
2429   
2430   /* adjust the stack for parameters if 
2431   required */
2432   if (ic->parmBytes) {
2433     int i;
2434     if (ic->parmBytes > 3) {
2435       pic14_emitcode("mov","a,%s",spname);
2436       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2437       pic14_emitcode("mov","%s,a",spname);
2438     } else 
2439       for ( i = 0 ; i <  ic->parmBytes ;i++)
2440         pic14_emitcode("dec","%s",spname);
2441       
2442   }
2443   
2444   /* if register bank was saved then pop them */
2445   if (ic->bankSaved)
2446     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2447   
2448   /* if we hade saved some registers then unsave them */
2449   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2450     unsaveRegisters (ic);
2451   
2452   
2453 }
2454
2455 /*-----------------------------------------------------------------*/
2456 /* genPcall - generates a call by pointer statement                */
2457 /*-----------------------------------------------------------------*/
2458 static void genPcall (iCode *ic)
2459 {
2460   sym_link *dtype;
2461   symbol *albl = newiTempLabel(NULL);
2462   symbol *blbl = newiTempLabel(NULL);
2463   PIC_OPCODE poc;
2464   pCodeOp *pcop;
2465   operand *left;
2466   
2467   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2468   /* if caller saves & we have not saved then */
2469   if (!ic->regsSaved)
2470     saveRegisters(ic);
2471   
2472     /* if we are calling a function that is not using
2473     the same register bank then we need to save the
2474   destination registers on the stack */
2475   dtype = operandType(IC_LEFT(ic));
2476   if (currFunc && dtype && 
2477     IFFUNC_ISISR(currFunc->type) &&
2478     (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2479     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2480   
2481   left = IC_LEFT(ic);
2482   aopOp(left,ic,FALSE);
2483   DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2484   
2485   pushSide(IC_LEFT(ic), FPTRSIZE);
2486   
2487   /* if send set is not empty, assign parameters */
2488   if (_G.sendSet) {
2489     
2490     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2491     /* no way to pass args - W always gets used to make the call */
2492   }
2493   /* first idea - factor out a common helper function and call it.
2494   But don't know how to get it generated only once in its own block
2495   
2496     if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2497     char *rname;
2498     char *buffer;
2499     rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2500     DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2501     buffer = Safe_calloc(1,strlen(rname)+16);
2502     sprintf(buffer, "%s_goto_helper", rname);
2503     addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2504     free(buffer);
2505     }
2506   */
2507   emitpcode(POC_CALL,popGetLabel(albl->key));
2508   pcop = popGetLabel(blbl->key);
2509   emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2510   emitpcode(POC_GOTO,pcop);
2511   emitpLabel(albl->key);
2512   
2513   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
2514   
2515   emitpcode(poc,popGet(AOP(left),1));
2516   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2517   emitpcode(poc,popGet(AOP(left),0));
2518   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2519   
2520   emitpLabel(blbl->key);
2521   
2522   freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2523   
2524   /* if we need to assign a result value */
2525   if ((IS_ITEMP(IC_RESULT(ic)) &&
2526     (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2527     OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2528     IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2529     
2530     _G.accInUse++;
2531     aopOp(IC_RESULT(ic),ic,FALSE);
2532     _G.accInUse--;
2533     
2534     assignResultValue(IC_RESULT(ic));
2535     
2536     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2537   }
2538   
2539   /* if register bank was saved then unsave them */
2540   if (currFunc && dtype && 
2541     (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2542     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2543   
2544     /* if we hade saved some registers then
2545   unsave them */
2546   if (ic->regsSaved)
2547     unsaveRegisters (ic);
2548   
2549 }
2550
2551 /*-----------------------------------------------------------------*/
2552 /* resultRemat - result  is rematerializable                       */
2553 /*-----------------------------------------------------------------*/
2554 static int resultRemat (iCode *ic)
2555 {
2556   //    DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2557   if (SKIP_IC(ic) || ic->op == IFX)
2558     return 0;
2559   
2560   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2561     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2562     if (sym->remat && !POINTER_SET(ic)) 
2563       return 1;
2564   }
2565   
2566   return 0;
2567 }
2568
2569 #if defined(__BORLANDC__) || defined(_MSC_VER)
2570 #define STRCASECMP stricmp
2571 #else
2572 #define STRCASECMP strcasecmp
2573 #endif
2574
2575 #if 0
2576 /*-----------------------------------------------------------------*/
2577 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2578 /*-----------------------------------------------------------------*/
2579 static bool inExcludeList(char *s)
2580 {
2581   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2582   int i =0;
2583   
2584   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2585   if (options.excludeRegs[i] &&
2586     STRCASECMP(options.excludeRegs[i],"none") == 0)
2587     return FALSE ;
2588   
2589   for ( i = 0 ; options.excludeRegs[i]; i++) {
2590     if (options.excludeRegs[i] &&
2591       STRCASECMP(s,options.excludeRegs[i]) == 0)
2592       return TRUE;
2593   }
2594   return FALSE ;
2595 }
2596 #endif
2597
2598 /*-----------------------------------------------------------------*/
2599 /* genFunction - generated code for function entry                 */
2600 /*-----------------------------------------------------------------*/
2601 static void genFunction (iCode *ic)
2602 {
2603   symbol *sym;
2604   sym_link *ftype;
2605   
2606   DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2607   
2608   labelOffset += (max_key+4);
2609   max_key=0;
2610   GpsuedoStkPtr=0;
2611   _G.nRegsSaved = 0;
2612   /* create the function header */
2613   pic14_emitcode(";","-----------------------------------------");
2614   pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2615   pic14_emitcode(";","-----------------------------------------");
2616   
2617   pic14_emitcode("","%s:",sym->rname);
2618   addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2619   
2620   ftype = operandType(IC_LEFT(ic));
2621   
2622   /* if critical function then turn interrupts off */
2623   if (IFFUNC_ISCRITICAL(ftype))
2624     pic14_emitcode("clr","ea");
2625   
2626     /* here we need to generate the equates for the
2627   register bank if required */
2628 #if 0
2629   if (FUNC_REGBANK(ftype) != rbank) {
2630     int i ;
2631     
2632     rbank = FUNC_REGBANK(ftype);
2633     for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2634       if (strcmp(regspic14[i].base,"0") == 0)
2635         pic14_emitcode("","%s = 0x%02x",
2636         regspic14[i].dname,
2637         8*rbank+regspic14[i].offset);
2638       else
2639         pic14_emitcode ("","%s = %s + 0x%02x",
2640         regspic14[i].dname,
2641         regspic14[i].base,
2642         8*rbank+regspic14[i].offset);
2643     }
2644   }
2645 #endif
2646   
2647   /* if this is an interrupt service routine */
2648   if (IFFUNC_ISISR(sym->type)) {
2649   /*  already done in pic14createInterruptVect() - delete me
2650   addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2651   emitpcodeNULLop(POC_NOP);
2652   emitpcodeNULLop(POC_NOP);
2653   emitpcodeNULLop(POC_NOP);
2654     */
2655     emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2656     emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2657     emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2658     emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2659     emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2660     emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2661     emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2662     
2663     pBlockConvert2ISR(pb);
2664 #if 0  
2665     if (!inExcludeList("acc"))      
2666       pic14_emitcode ("push","acc");  
2667     if (!inExcludeList("b"))
2668       pic14_emitcode ("push","b");
2669     if (!inExcludeList("dpl"))
2670       pic14_emitcode ("push","dpl");
2671     if (!inExcludeList("dph"))
2672       pic14_emitcode ("push","dph");
2673     if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2674     {
2675       pic14_emitcode ("push", "dpx");
2676       /* Make sure we're using standard DPTR */
2677       pic14_emitcode ("push", "dps");
2678       pic14_emitcode ("mov", "dps, #0x00");
2679       if (options.stack10bit)
2680       { 
2681         /* This ISR could conceivably use DPTR2. Better save it. */
2682         pic14_emitcode ("push", "dpl1");
2683         pic14_emitcode ("push", "dph1");
2684         pic14_emitcode ("push", "dpx1");
2685       }
2686     }
2687     /* if this isr has no bank i.e. is going to
2688     run with bank 0 , then we need to save more
2689 registers :-) */
2690     if (!FUNC_REGBANK(sym->type)) {
2691       
2692     /* if this function does not call any other
2693     function then we can be economical and
2694       save only those registers that are used */
2695       if (! IFFUNC_HASFCALL(sym->type)) {
2696         int i;
2697         
2698         /* if any registers used */
2699         if (sym->regsUsed) {
2700           /* save the registers used */
2701           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2702             if (bitVectBitValue(sym->regsUsed,i) ||
2703               (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2704               pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);         
2705           }
2706         }
2707         
2708       } else {
2709       /* this function has  a function call cannot
2710       determines register usage so we will have the
2711         entire bank */
2712         saverbank(0,ic,FALSE);
2713       }     
2714     }
2715 #endif
2716   } else {
2717   /* if callee-save to be used for this function
2718     then save the registers being used in this function */
2719     if (IFFUNC_CALLEESAVES(sym->type)) {
2720       int i;
2721       
2722       /* if any registers used */
2723       if (sym->regsUsed) {
2724         /* save the registers used */
2725         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2726           if (bitVectBitValue(sym->regsUsed,i) ||
2727             (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2728             //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2729             _G.nRegsSaved++;
2730           }
2731         }
2732       }
2733     }
2734   }
2735   
2736   /* set the register bank to the desired value */
2737   if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2738     pic14_emitcode("push","psw");
2739     pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2740   }
2741   
2742   if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2743     
2744     if (options.useXstack) {
2745       pic14_emitcode("mov","r0,%s",spname);
2746       pic14_emitcode("mov","a,_bp");
2747       pic14_emitcode("movx","@r0,a");
2748       pic14_emitcode("inc","%s",spname);
2749     }
2750     else
2751     {
2752       /* set up the stack */
2753       pic14_emitcode ("push","_bp");     /* save the callers stack  */
2754     }
2755     pic14_emitcode ("mov","_bp,%s",spname);
2756   }
2757   
2758   /* adjust the stack for the function */
2759   if (sym->stack) {
2760     
2761     int i = sym->stack;
2762     if (i > 256 ) 
2763       werror(W_STACK_OVERFLOW,sym->name);
2764     
2765     if (i > 3 && sym->recvSize < 4) {        
2766       
2767       pic14_emitcode ("mov","a,sp");
2768       pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2769       pic14_emitcode ("mov","sp,a");
2770       
2771     }
2772     else
2773       while(i--)
2774         pic14_emitcode("inc","sp");
2775   }
2776   
2777   if (sym->xstack) {
2778     
2779     pic14_emitcode ("mov","a,_spx");
2780     pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2781     pic14_emitcode ("mov","_spx,a");
2782   }    
2783   
2784 }
2785
2786 /*-----------------------------------------------------------------*/
2787 /* genEndFunction - generates epilogue for functions               */
2788 /*-----------------------------------------------------------------*/
2789 static void genEndFunction (iCode *ic)
2790 {
2791   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2792   
2793   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2794   
2795   if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2796   {
2797     pic14_emitcode ("mov","%s,_bp",spname);
2798   }
2799   
2800   /* if use external stack but some variables were
2801   added to the local stack then decrement the
2802   local stack */
2803   if (options.useXstack && sym->stack) {      
2804     pic14_emitcode("mov","a,sp");
2805     pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2806     pic14_emitcode("mov","sp,a");
2807   }
2808   
2809   
2810   if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2811     if (options.useXstack) {
2812       pic14_emitcode("mov","r0,%s",spname);
2813       pic14_emitcode("movx","a,@r0");
2814       pic14_emitcode("mov","_bp,a");
2815       pic14_emitcode("dec","%s",spname);
2816     }
2817     else
2818     {
2819       pic14_emitcode ("pop","_bp");
2820     }
2821   }
2822   
2823   /* restore the register bank  */    
2824   if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2825     pic14_emitcode ("pop","psw");
2826   
2827   if (IFFUNC_ISISR(sym->type)) {
2828     
2829     /* now we need to restore the registers */
2830     /* if this isr has no bank i.e. is going to
2831     run with bank 0 , then we need to save more
2832 registers :-) */
2833     if (!FUNC_REGBANK(sym->type)) {
2834       
2835     /* if this function does not call any other
2836     function then we can be economical and
2837       save only those registers that are used */
2838       if (! IFFUNC_HASFCALL(sym->type)) {
2839         int i;
2840         
2841         /* if any registers used */
2842         if (sym->regsUsed) {
2843           /* save the registers used */
2844           for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2845             if (bitVectBitValue(sym->regsUsed,i) ||
2846               (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2847               pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2848           }
2849         }
2850         
2851       } else {
2852       /* this function has  a function call cannot
2853       determines register usage so we will have the
2854         entire bank */
2855         unsaverbank(0,ic,FALSE);
2856       }     
2857     }
2858 #if 0
2859     if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2860     {
2861       if (options.stack10bit)
2862       {
2863         pic14_emitcode ("pop", "dpx1");
2864         pic14_emitcode ("pop", "dph1");
2865         pic14_emitcode ("pop", "dpl1");
2866       } 
2867       pic14_emitcode ("pop", "dps");
2868       pic14_emitcode ("pop", "dpx");
2869     }
2870     if (!inExcludeList("dph"))
2871       pic14_emitcode ("pop","dph");
2872     if (!inExcludeList("dpl"))
2873       pic14_emitcode ("pop","dpl");
2874     if (!inExcludeList("b"))
2875       pic14_emitcode ("pop","b");
2876     if (!inExcludeList("acc"))
2877       pic14_emitcode ("pop","acc");
2878     
2879     if (IFFUNC_ISCRITICAL(sym->type))
2880       pic14_emitcode("setb","ea");
2881 #endif
2882     
2883     /* if debug then send end of function */
2884     /*  if (options.debug && currFunc) { */
2885     if (currFunc) {
2886       debugFile->writeEndFunction (currFunc, ic, 1);
2887     }
2888     
2889     pic14_emitcode ("reti","");
2890     emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
2891     emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
2892     emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2893     emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2894     emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2895     emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2896     emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2897     addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2898     emitpcodeNULLop(POC_RETFIE);
2899   }
2900   else {
2901     if (IFFUNC_ISCRITICAL(sym->type))
2902       pic14_emitcode("setb","ea");
2903     
2904     if (IFFUNC_CALLEESAVES(sym->type)) {
2905       int i;
2906       
2907       /* if any registers used */
2908       if (sym->regsUsed) {
2909         /* save the registers used */
2910         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2911           if (bitVectBitValue(sym->regsUsed,i) ||
2912             (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2913             pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2914         }
2915       }
2916       
2917     }
2918     
2919     /* if debug then send end of function */
2920     if (currFunc) {
2921       debugFile->writeEndFunction (currFunc, ic, 1);
2922     }
2923     
2924     pic14_emitcode ("return","");
2925     emitpcodeNULLop(POC_RETURN);
2926     
2927     /* Mark the end of a function */
2928     addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2929   }
2930   
2931 }
2932
2933 /*-----------------------------------------------------------------*/
2934 /* genRet - generate code for return statement                     */
2935 /*-----------------------------------------------------------------*/
2936 static void genRet (iCode *ic)
2937 {
2938   int size,offset = 0 , pushed = 0;
2939   
2940   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2941   /* if we have no return value then
2942   just generate the "ret" */
2943   if (!IC_LEFT(ic)) 
2944     goto jumpret;       
2945   
2946     /* we have something to return then
2947   move the return value into place */
2948   aopOp(IC_LEFT(ic),ic,FALSE);
2949   size = AOP_SIZE(IC_LEFT(ic));
2950   
2951   while (size--) {
2952     char *l ;
2953     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2954       /* #NOCHANGE */
2955       l = aopGet(AOP(IC_LEFT(ic)),offset++,
2956         FALSE,TRUE);
2957       pic14_emitcode("push","%s",l);
2958       pushed++;
2959     } else {
2960       l = aopGet(AOP(IC_LEFT(ic)),offset,
2961         FALSE,FALSE);
2962       if (strcmp(fReturn[offset],l)) {
2963         if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
2964           AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
2965           ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2966           ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
2967           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
2968         }else {
2969           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
2970         }
2971         if(size) {
2972           emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
2973         }
2974         offset++;
2975       }
2976     }
2977   }    
2978   
2979   if (pushed) {
2980     while(pushed) {
2981       pushed--;
2982       if (strcmp(fReturn[pushed],"a"))
2983         pic14_emitcode("pop",fReturn[pushed]);
2984       else
2985         pic14_emitcode("pop","acc");
2986     }
2987   }
2988   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2989   
2990 jumpret:
2991 /* generate a jump to the return label
2992   if the next is not the return statement */
2993   if (!(ic->next && ic->next->op == LABEL &&
2994     IC_LABEL(ic->next) == returnLabel)) {
2995     
2996     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2997     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2998   }
2999   
3000 }
3001
3002 /*-----------------------------------------------------------------*/
3003 /* genLabel - generates a label                                    */
3004 /*-----------------------------------------------------------------*/
3005 static void genLabel (iCode *ic)
3006 {
3007   /* special case never generate */
3008   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3009   if (IC_LABEL(ic) == entryLabel)
3010     return ;
3011   
3012   emitpLabel(IC_LABEL(ic)->key);
3013   pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3014 }
3015
3016 /*-----------------------------------------------------------------*/
3017 /* genGoto - generates a goto                                      */
3018 /*-----------------------------------------------------------------*/
3019 //tsd
3020 static void genGoto (iCode *ic)
3021 {
3022   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3023   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3024 }
3025
3026
3027 /*-----------------------------------------------------------------*/
3028 /* genMultbits :- multiplication of bits                           */
3029 /*-----------------------------------------------------------------*/
3030 static void genMultbits (operand *left, 
3031              operand *right, 
3032              operand *result)
3033 {
3034   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3035   
3036   if(!pic14_sameRegs(AOP(result),AOP(right)))
3037     emitpcode(POC_BSF,  popGet(AOP(result),0));
3038   
3039   emitpcode(POC_BTFSC,popGet(AOP(right),0));
3040   emitpcode(POC_BTFSS,popGet(AOP(left),0));
3041   emitpcode(POC_BCF,  popGet(AOP(result),0));
3042   
3043 }
3044
3045
3046 /*-----------------------------------------------------------------*/
3047 /* genMultOneByte : 8 bit multiplication & division                */
3048 /*-----------------------------------------------------------------*/
3049 static void genMultOneByte (operand *left,
3050               operand *right,
3051               operand *result)
3052 {
3053   sym_link *opetype = operandType(result);
3054   
3055   // symbol *lbl ;
3056   int size,offset;
3057   
3058   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3059   DEBUGpic14_AopType(__LINE__,left,right,result);
3060   DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3061   
3062   /* (if two literals, the value is computed before) */
3063   /* if one literal, literal on the right */
3064   if (AOP_TYPE(left) == AOP_LIT){
3065     operand *t = right;
3066     right = left;
3067     left = t;
3068   }
3069   
3070   size = AOP_SIZE(result);
3071   if(size == 1) {
3072     
3073     if (AOP_TYPE(right) == AOP_LIT){
3074       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3075         aopGet(AOP(right),0,FALSE,FALSE), 
3076         aopGet(AOP(left),0,FALSE,FALSE), 
3077         aopGet(AOP(result),0,FALSE,FALSE));
3078       pic14_emitcode("call","genMultLit");
3079     } else {
3080       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3081         aopGet(AOP(right),0,FALSE,FALSE), 
3082         aopGet(AOP(left),0,FALSE,FALSE), 
3083         aopGet(AOP(result),0,FALSE,FALSE));
3084       pic14_emitcode("call","genMult8X8_8");
3085       
3086     }
3087     genMult8X8_8 (left, right,result);
3088     
3089     
3090     /* signed or unsigned */
3091     //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3092     //l = aopGet(AOP(left),0,FALSE,FALSE);
3093     //MOVA(l);       
3094     //pic14_emitcode("mul","ab");
3095     /* if result size = 1, mul signed = mul unsigned */
3096     //aopPut(AOP(result),"a",0);
3097     
3098   } else {  // (size > 1)
3099     
3100     pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3101       aopGet(AOP(right),0,FALSE,FALSE), 
3102       aopGet(AOP(left),0,FALSE,FALSE), 
3103       aopGet(AOP(result),0,FALSE,FALSE));
3104     
3105     if (SPEC_USIGN(opetype)){
3106       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3107       genUMult8X8_16 (left, right, result, NULL);
3108       
3109       if (size > 2) {
3110         /* for filling the MSBs */
3111         emitpcode(POC_CLRF,  popGet(AOP(result),2));
3112         emitpcode(POC_CLRF,  popGet(AOP(result),3));
3113       }
3114     }
3115     else{
3116       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3117       
3118       pic14_emitcode("mov","a,b");
3119       
3120       /* adjust the MSB if left or right neg */
3121       
3122       /* if one literal */
3123       if (AOP_TYPE(right) == AOP_LIT){
3124         pic14_emitcode("multiply ","right is a lit");
3125         /* AND literal negative */
3126         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3127           /* adjust MSB (c==0 after mul) */
3128           pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3129         }
3130       }
3131       else{
3132         genSMult8X8_16 (left, right, result, NULL);
3133       }
3134       
3135       if(size > 2){
3136         pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3137         /* get the sign */
3138         pic14_emitcode("rlc","a");
3139         pic14_emitcode("subb","a,acc");
3140       }
3141     }
3142     
3143     size -= 2;   
3144     offset = 2;
3145     if (size > 0)
3146       while (size--)
3147         pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3148       //aopPut(AOP(result),"a",offset++);
3149   }
3150 }
3151
3152 /*-----------------------------------------------------------------*/
3153 /* genMult - generates code for multiplication                     */
3154 /*-----------------------------------------------------------------*/
3155 static void genMult (iCode *ic)
3156 {
3157   operand *left = IC_LEFT(ic);
3158   operand *right = IC_RIGHT(ic);
3159   operand *result= IC_RESULT(ic);   
3160   
3161   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3162   /* assign the amsops */
3163   aopOp (left,ic,FALSE);
3164   aopOp (right,ic,FALSE);
3165   aopOp (result,ic,TRUE);
3166   
3167   DEBUGpic14_AopType(__LINE__,left,right,result);
3168   
3169   /* special cases first */
3170   /* both are bits */
3171   if (AOP_TYPE(left) == AOP_CRY &&
3172     AOP_TYPE(right)== AOP_CRY) {
3173     genMultbits(left,right,result);
3174     goto release ;
3175   }
3176   
3177   /* if both are of size == 1 */
3178   if (AOP_SIZE(left) == 1 &&
3179     AOP_SIZE(right) == 1 ) {
3180     genMultOneByte(left,right,result);
3181     goto release ;
3182   }
3183   
3184   pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3185   
3186   /* should have been converted to function call */
3187   //assert(0) ;
3188   
3189 release :
3190   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3191   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3192   freeAsmop(result,NULL,ic,TRUE); 
3193 }
3194
3195 /*-----------------------------------------------------------------*/
3196 /* genDivbits :- division of bits                                  */
3197 /*-----------------------------------------------------------------*/
3198 static void genDivbits (operand *left, 
3199             operand *right, 
3200             operand *result)
3201 {
3202   
3203   char *l;
3204   
3205   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3206   /* the result must be bit */    
3207   pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3208   l = aopGet(AOP(left),0,FALSE,FALSE);
3209   
3210   MOVA(l);    
3211   
3212   pic14_emitcode("div","ab");
3213   pic14_emitcode("rrc","a");
3214   aopPut(AOP(result),"c",0);
3215 }
3216
3217 /*-----------------------------------------------------------------*/
3218 /* genDivOneByte : 8 bit division                                  */
3219 /*-----------------------------------------------------------------*/
3220 static void genDivOneByte (operand *left,
3221                operand *right,
3222                operand *result)
3223 {
3224   sym_link *opetype = operandType(result);
3225   char *l ;
3226   symbol *lbl ;
3227   int size,offset;
3228   
3229   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3230   size = AOP_SIZE(result) - 1;
3231   offset = 1;
3232   /* signed or unsigned */
3233   if (SPEC_USIGN(opetype)) {
3234     /* unsigned is easy */
3235     pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3236     l = aopGet(AOP(left),0,FALSE,FALSE);
3237     MOVA(l);        
3238     pic14_emitcode("div","ab");
3239     aopPut(AOP(result),"a",0);
3240     while (size--)
3241       aopPut(AOP(result),zero,offset++);
3242     return ;
3243   }
3244   
3245   /* signed is a little bit more difficult */
3246   
3247   /* save the signs of the operands */
3248   l = aopGet(AOP(left),0,FALSE,FALSE);    
3249   MOVA(l);    
3250   pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3251   pic14_emitcode("push","acc"); /* save it on the stack */
3252   
3253   /* now sign adjust for both left & right */
3254   l =  aopGet(AOP(right),0,FALSE,FALSE);    
3255   MOVA(l);       
3256   lbl = newiTempLabel(NULL);
3257   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3258   pic14_emitcode("cpl","a");   
3259   pic14_emitcode("inc","a");
3260   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3261   pic14_emitcode("mov","b,a");
3262   
3263   /* sign adjust left side */
3264   l =  aopGet(AOP(left),0,FALSE,FALSE);    
3265   MOVA(l);
3266   
3267   lbl = newiTempLabel(NULL);
3268   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3269   pic14_emitcode("cpl","a");
3270   pic14_emitcode("inc","a");
3271   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3272   
3273   /* now the division */
3274   pic14_emitcode("div","ab");
3275   /* we are interested in the lower order
3276   only */
3277   pic14_emitcode("mov","b,a");
3278   lbl = newiTempLabel(NULL);
3279   pic14_emitcode("pop","acc");   
3280   /* if there was an over flow we don't 
3281   adjust the sign of the result */
3282   pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3283   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3284   CLRC;
3285   pic14_emitcode("clr","a");
3286   pic14_emitcode("subb","a,b");
3287   pic14_emitcode("mov","b,a");
3288   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3289   
3290   /* now we are done */
3291   aopPut(AOP(result),"b",0);
3292   if(size > 0){
3293     pic14_emitcode("mov","c,b.7");
3294     pic14_emitcode("subb","a,acc");   
3295   }
3296   while (size--)
3297     aopPut(AOP(result),"a",offset++);
3298   
3299 }
3300
3301 /*-----------------------------------------------------------------*/
3302 /* genDiv - generates code for division                            */
3303 /*-----------------------------------------------------------------*/
3304 static void genDiv (iCode *ic)
3305 {
3306   operand *left = IC_LEFT(ic);
3307   operand *right = IC_RIGHT(ic);
3308   operand *result= IC_RESULT(ic);   
3309   
3310   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3311   /* assign the amsops */
3312   aopOp (left,ic,FALSE);
3313   aopOp (right,ic,FALSE);
3314   aopOp (result,ic,TRUE);
3315   
3316   /* special cases first */
3317   /* both are bits */
3318   if (AOP_TYPE(left) == AOP_CRY &&
3319     AOP_TYPE(right)== AOP_CRY) {
3320     genDivbits(left,right,result);
3321     goto release ;
3322   }
3323   
3324   /* if both are of size == 1 */
3325   if (AOP_SIZE(left) == 1 &&
3326     AOP_SIZE(right) == 1 ) {
3327     genDivOneByte(left,right,result);
3328     goto release ;
3329   }
3330   
3331   /* should have been converted to function call */
3332   assert(0);
3333 release :
3334   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3335   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3336   freeAsmop(result,NULL,ic,TRUE); 
3337 }
3338
3339 /*-----------------------------------------------------------------*/
3340 /* genModbits :- modulus of bits                                   */
3341 /*-----------------------------------------------------------------*/
3342 static void genModbits (operand *left, 
3343             operand *right, 
3344             operand *result)
3345 {
3346   
3347   char *l;
3348   
3349   /* the result must be bit */    
3350   pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3351   l = aopGet(AOP(left),0,FALSE,FALSE);
3352   
3353   MOVA(l);       
3354   
3355   pic14_emitcode("div","ab");
3356   pic14_emitcode("mov","a,b");
3357   pic14_emitcode("rrc","a");
3358   aopPut(AOP(result),"c",0);
3359 }
3360
3361 /*-----------------------------------------------------------------*/
3362 /* genModOneByte : 8 bit modulus                                   */
3363 /*-----------------------------------------------------------------*/
3364 static void genModOneByte (operand *left,
3365                operand *right,
3366                operand *result)
3367 {
3368   sym_link *opetype = operandType(result);
3369   char *l ;
3370   symbol *lbl ;
3371   
3372   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3373   /* signed or unsigned */
3374   if (SPEC_USIGN(opetype)) {
3375     /* unsigned is easy */
3376     pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3377     l = aopGet(AOP(left),0,FALSE,FALSE);
3378     MOVA(l);    
3379     pic14_emitcode("div","ab");
3380     aopPut(AOP(result),"b",0);
3381     return ;
3382   }
3383   
3384   /* signed is a little bit more difficult */
3385   
3386   /* save the signs of the operands */
3387   l = aopGet(AOP(left),0,FALSE,FALSE);    
3388   MOVA(l);
3389   
3390   pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3391   pic14_emitcode("push","acc"); /* save it on the stack */
3392   
3393   /* now sign adjust for both left & right */
3394   l =  aopGet(AOP(right),0,FALSE,FALSE);    
3395   MOVA(l);
3396   
3397   lbl = newiTempLabel(NULL);
3398   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3399   pic14_emitcode("cpl","a");   
3400   pic14_emitcode("inc","a");
3401   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3402   pic14_emitcode("mov","b,a"); 
3403   
3404   /* sign adjust left side */
3405   l =  aopGet(AOP(left),0,FALSE,FALSE);    
3406   MOVA(l);
3407   
3408   lbl = newiTempLabel(NULL);
3409   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3410   pic14_emitcode("cpl","a");   
3411   pic14_emitcode("inc","a");
3412   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3413   
3414   /* now the multiplication */
3415   pic14_emitcode("div","ab");
3416   /* we are interested in the lower order
3417   only */
3418   lbl = newiTempLabel(NULL);
3419   pic14_emitcode("pop","acc");   
3420   /* if there was an over flow we don't 
3421   adjust the sign of the result */
3422   pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3423   pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3424   CLRC ;
3425   pic14_emitcode("clr","a");
3426   pic14_emitcode("subb","a,b");
3427   pic14_emitcode("mov","b,a");
3428   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3429   
3430   /* now we are done */
3431   aopPut(AOP(result),"b",0);
3432   
3433 }
3434
3435 /*-----------------------------------------------------------------*/
3436 /* genMod - generates code for division                            */
3437 /*-----------------------------------------------------------------*/
3438 static void genMod (iCode *ic)
3439 {
3440   operand *left = IC_LEFT(ic);
3441   operand *right = IC_RIGHT(ic);
3442   operand *result= IC_RESULT(ic);  
3443   
3444   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3445   /* assign the amsops */
3446   aopOp (left,ic,FALSE);
3447   aopOp (right,ic,FALSE);
3448   aopOp (result,ic,TRUE);
3449   
3450   /* special cases first */
3451   /* both are bits */
3452   if (AOP_TYPE(left) == AOP_CRY &&
3453     AOP_TYPE(right)== AOP_CRY) {
3454     genModbits(left,right,result);
3455     goto release ;
3456   }
3457   
3458   /* if both are of size == 1 */
3459   if (AOP_SIZE(left) == 1 &&
3460     AOP_SIZE(right) == 1 ) {
3461     genModOneByte(left,right,result);
3462     goto release ;
3463   }
3464   
3465   /* should have been converted to function call */
3466   assert(0);
3467   
3468 release :
3469   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3470   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3471   freeAsmop(result,NULL,ic,TRUE); 
3472 }
3473
3474 /*-----------------------------------------------------------------*/
3475 /* genIfxJump :- will create a jump depending on the ifx           */
3476 /*-----------------------------------------------------------------*/
3477 /*
3478 note: May need to add parameter to indicate when a variable is in bit space.
3479 */
3480 static void genIfxJump (iCode *ic, char *jval)
3481 {
3482   
3483   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3484   /* if true label then we jump if condition
3485   supplied is true */
3486   if ( IC_TRUE(ic) ) {
3487     
3488     if(strcmp(jval,"a") == 0)
3489       emitSKPZ;
3490     else if (strcmp(jval,"c") == 0)
3491       emitSKPC;
3492     else {
3493       DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);   
3494       emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3495     }
3496     
3497     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3498     pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3499     
3500   }
3501   else {
3502     /* false label is present */
3503     if(strcmp(jval,"a") == 0)
3504       emitSKPNZ;
3505     else if (strcmp(jval,"c") == 0)
3506       emitSKPNC;
3507     else {
3508       DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);   
3509       emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3510     }
3511     
3512     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3513     pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3514     
3515   }
3516   
3517   
3518   /* mark the icode as generated */
3519   ic->generated = 1;
3520 }
3521
3522 /*-----------------------------------------------------------------*/
3523 /* genSkip                                                         */
3524 /*-----------------------------------------------------------------*/
3525 static void genSkip(iCode *ifx,int status_bit)
3526 {
3527   if(!ifx)
3528     return;
3529   
3530   if ( IC_TRUE(ifx) ) {
3531     switch(status_bit) {
3532     case 'z':
3533       emitSKPNZ;
3534       break;
3535       
3536     case 'c':
3537       emitSKPNC;
3538       break;
3539       
3540     case 'd':
3541       emitSKPDC;
3542       break;
3543       
3544     }
3545     
3546     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3547     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3548     
3549   } else {
3550     
3551     switch(status_bit) {
3552       
3553     case 'z':
3554       emitSKPZ;
3555       break;
3556       
3557     case 'c':
3558       emitSKPC;
3559       break;
3560       
3561     case 'd':
3562       emitSKPDC;
3563       break;
3564     }
3565     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3566     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3567     
3568   }
3569   
3570 }
3571
3572 /*-----------------------------------------------------------------*/
3573 /* genSkipc                                                        */
3574 /*-----------------------------------------------------------------*/
3575 static void genSkipc(resolvedIfx *rifx)
3576 {
3577   if(!rifx)
3578     return;
3579   
3580   if(rifx->condition)
3581     emitSKPC;
3582   else
3583     emitSKPNC;
3584   
3585   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3586   rifx->generated = 1;
3587 }
3588
3589 /*-----------------------------------------------------------------*/
3590 /* genSkipz2                                                       */
3591 /*-----------------------------------------------------------------*/
3592 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3593 {
3594   if(!rifx)
3595     return;
3596   
3597   if( (rifx->condition ^ invert_condition) & 1)
3598     emitSKPZ;
3599   else
3600     emitSKPNZ;
3601   
3602   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3603   rifx->generated = 1;
3604 }
3605
3606 /*-----------------------------------------------------------------*/
3607 /* genSkipz                                                        */
3608 /*-----------------------------------------------------------------*/
3609 static void genSkipz(iCode *ifx, int condition)
3610 {
3611   if(!ifx)
3612     return;
3613   
3614   if(condition)
3615     emitSKPNZ;
3616   else
3617     emitSKPZ;
3618   
3619   if ( IC_TRUE(ifx) )
3620     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3621   else
3622     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3623   
3624   if ( IC_TRUE(ifx) )
3625     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3626   else
3627     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3628   
3629 }
3630 /*-----------------------------------------------------------------*/
3631 /* genSkipCond                                                     */
3632 /*-----------------------------------------------------------------*/
3633 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3634 {
3635   if(!rifx)
3636     return;
3637   
3638   if(rifx->condition)
3639     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3640   else
3641     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3642   
3643   
3644   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3645   rifx->generated = 1;
3646 }
3647
3648 #if 0
3649 /*-----------------------------------------------------------------*/
3650 /* genChkZeroes :- greater or less than comparison                 */
3651 /*     For each byte in a literal that is zero, inclusive or the   */
3652 /*     the corresponding byte in the operand with W                */
3653 /*     returns true if any of the bytes are zero                   */
3654 /*-----------------------------------------------------------------*/
3655 static int genChkZeroes(operand *op, int lit,  int size)
3656 {
3657   
3658   int i;
3659   int flag =1;
3660   
3661   while(size--) {
3662     i = (lit >> (size*8)) & 0xff;
3663     
3664     if(i==0) {
3665       if(flag) 
3666         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3667       else
3668         emitpcode(POC_IORFW, popGet(AOP(op),size));
3669       flag = 0;
3670     }
3671   }
3672   
3673   return (flag==0);
3674 }
3675 #endif
3676
3677 /*-----------------------------------------------------------------*/
3678 /* genCmp :- greater or less than comparison                       */
3679 /*-----------------------------------------------------------------*/
3680 static void genCmp (operand *left,operand *right,
3681           operand *result, iCode *ifx, int sign)
3682 {
3683   int size; //, offset = 0 ;
3684   unsigned long lit = 0L,i = 0;
3685   resolvedIfx rFalseIfx;
3686   //  resolvedIfx rTrueIfx;
3687   symbol *truelbl;
3688   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3689   /*
3690   if(ifx) {
3691   DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3692   DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3693   }
3694   */
3695   
3696   resolveIfx(&rFalseIfx,ifx);
3697   truelbl  = newiTempLabel(NULL);
3698   size = max(AOP_SIZE(left),AOP_SIZE(right));
3699   
3700   DEBUGpic14_AopType(__LINE__,left,right,result);
3701   
3702 #define _swapp
3703   
3704   /* if literal is on the right then swap with left */
3705   if ((AOP_TYPE(right) == AOP_LIT)) {
3706     operand *tmp = right ;
3707     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3708     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3709 #ifdef _swapp
3710     
3711     lit = (lit - 1) & mask;
3712     right = left;
3713     left = tmp;
3714     rFalseIfx.condition ^= 1;
3715 #endif
3716     
3717   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3718     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3719   }
3720   
3721   
3722   //if(IC_TRUE(ifx) == NULL)
3723   /* if left & right are bit variables */
3724   if (AOP_TYPE(left) == AOP_CRY &&
3725     AOP_TYPE(right) == AOP_CRY ) {
3726     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3727     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3728   } else {
3729   /* subtract right from left if at the
3730   end the carry flag is set then we know that
3731     left is greater than right */
3732     
3733     //    {
3734     
3735     symbol *lbl  = newiTempLabel(NULL);
3736     
3737 #ifndef _swapp
3738     if(AOP_TYPE(right) == AOP_LIT) {
3739       
3740       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3741       
3742       DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3743       
3744       /* special cases */
3745       
3746       if(lit == 0) {
3747         
3748         if(sign != 0) 
3749           genSkipCond(&rFalseIfx,left,size-1,7);
3750         else 
3751           /* no need to compare to 0...*/
3752           /* NOTE: this is a de-generate compare that most certainly 
3753           *       creates some dead code. */
3754           emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3755         
3756         if(ifx) ifx->generated = 1;
3757         return;
3758         
3759       }
3760       size--;
3761       
3762       if(size == 0) {
3763         //i = (lit >> (size*8)) & 0xff;
3764         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3765         
3766         emitpcode(POC_MOVFW, popGet(AOP(left),size));
3767         
3768         i = ((0-lit) & 0xff);
3769         if(sign) {
3770           if( i == 0x81) { 
3771           /* lit is 0x7f, all signed chars are less than
3772             * this except for 0x7f itself */
3773             emitpcode(POC_XORLW, popGetLit(0x7f));
3774             genSkipz2(&rFalseIfx,0);
3775           } else {
3776             emitpcode(POC_ADDLW, popGetLit(0x80));
3777             emitpcode(POC_ADDLW, popGetLit(i^0x80));
3778             genSkipc(&rFalseIfx);
3779           }
3780           
3781         } else {
3782           if(lit == 1) {
3783             genSkipz2(&rFalseIfx,1);
3784           } else {
3785             emitpcode(POC_ADDLW, popGetLit(i));
3786             genSkipc(&rFalseIfx);
3787           }
3788         }
3789         
3790         if(ifx) ifx->generated = 1;
3791         return;
3792       }
3793       
3794       /* chars are out of the way. now do ints and longs */
3795       
3796       
3797       DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3798       
3799       /* special cases */
3800       
3801       if(sign) {
3802         
3803         if(lit == 0) {
3804           genSkipCond(&rFalseIfx,left,size,7);
3805           if(ifx) ifx->generated = 1;
3806           return;
3807         }
3808         
3809         if(lit <0x100) {
3810           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3811           
3812           //rFalseIfx.condition ^= 1;
3813           //genSkipCond(&rFalseIfx,left,size,7);
3814           //rFalseIfx.condition ^= 1;
3815           
3816           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3817           if(rFalseIfx.condition)
3818             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3819           else
3820             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3821           
3822           emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3823           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3824           emitpcode(POC_MOVFW, popGet(AOP(left),1));
3825           
3826           while(size > 1)
3827             emitpcode(POC_IORFW, popGet(AOP(left),size--));
3828           
3829           if(rFalseIfx.condition) {
3830             emitSKPZ;
3831             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3832             
3833           } else {
3834             emitSKPNZ;
3835           }
3836           
3837           genSkipc(&rFalseIfx);
3838           emitpLabel(truelbl->key);
3839           if(ifx) ifx->generated = 1;
3840           return;
3841           
3842         }
3843         
3844         if(size == 1) {
3845           
3846           if( (lit & 0xff) == 0) {
3847             /* lower byte is zero */
3848             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3849             i = ((lit >> 8) & 0xff) ^0x80;
3850             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3851             emitpcode(POC_ADDLW, popGetLit( 0x80));
3852             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3853             genSkipc(&rFalseIfx);
3854             
3855             
3856             if(ifx) ifx->generated = 1;
3857             return;
3858             
3859           }
3860         } else {
3861           /* Special cases for signed longs */
3862           if( (lit & 0xffffff) == 0) {
3863             /* lower byte is zero */
3864             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3865             i = ((lit >> 8*3) & 0xff) ^0x80;
3866             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3867             emitpcode(POC_ADDLW, popGetLit( 0x80));
3868             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3869             genSkipc(&rFalseIfx);
3870             
3871             
3872             if(ifx) ifx->generated = 1;
3873             return;
3874             
3875           }
3876           
3877         }
3878         
3879         
3880         if(lit & (0x80 << (size*8))) {
3881           /* lit is negative */
3882           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3883           
3884           //genSkipCond(&rFalseIfx,left,size,7);
3885           
3886           emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3887           
3888           if(rFalseIfx.condition)
3889             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3890           else
3891             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3892           
3893           
3894         } else {
3895           /* lit is positive */
3896           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3897           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3898           if(rFalseIfx.condition)
3899             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3900           else
3901             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3902           
3903         }
3904         
3905         /* There are no more special cases, so perform a general compare */
3906         
3907         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3908         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3909         
3910         while(size--) {
3911           
3912           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3913           emitSKPNZ;
3914           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3915         }
3916         //rFalseIfx.condition ^= 1;
3917         genSkipc(&rFalseIfx);
3918         
3919         emitpLabel(truelbl->key);
3920         
3921         if(ifx) ifx->generated = 1;
3922         return;
3923         
3924         
3925     }
3926     
3927     
3928     /* sign is out of the way. So now do an unsigned compare */
3929     DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3930     
3931     
3932     /* General case - compare to an unsigned literal on the right.*/
3933     
3934     i = (lit >> (size*8)) & 0xff;
3935     emitpcode(POC_MOVLW, popGetLit(i));
3936     emitpcode(POC_SUBFW, popGet(AOP(left),size));
3937     while(size--) {
3938       i = (lit >> (size*8)) & 0xff;
3939       
3940       if(i) {
3941         emitpcode(POC_MOVLW, popGetLit(i));
3942         emitSKPNZ;
3943         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3944       } else {
3945       /* this byte of the lit is zero, 
3946         *if it's not the last then OR in the variable */
3947         if(size)
3948           emitpcode(POC_IORFW, popGet(AOP(left),size));
3949       }
3950     }
3951     
3952     
3953     emitpLabel(lbl->key);
3954     //if(emitFinalCheck)
3955     genSkipc(&rFalseIfx);
3956     if(sign)
3957       emitpLabel(truelbl->key);
3958     
3959     if(ifx) ifx->generated = 1;
3960     return;
3961     
3962     
3963   }
3964 #endif  // _swapp
3965   
3966   if(AOP_TYPE(left) == AOP_LIT) {
3967     //symbol *lbl = newiTempLabel(NULL);
3968     
3969     //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3970     
3971     
3972     DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
3973     
3974     /* Special cases */
3975     if((lit == 0) && (sign == 0)){
3976       
3977       size--;
3978       emitpcode(POC_MOVFW, popGet(AOP(right),size));
3979       while(size) 
3980         emitpcode(POC_IORFW, popGet(AOP(right),--size));
3981       
3982       genSkipz2(&rFalseIfx,0);
3983       if(ifx) ifx->generated = 1;
3984       return;
3985     }
3986     
3987     if(size==1) {
3988       /* Special cases */
3989       lit &= 0xff;
3990       if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3991         /* degenerate compare can never be true */
3992         if(rFalseIfx.condition == 0)
3993           emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3994         
3995         if(ifx) ifx->generated = 1;
3996         return;
3997       }
3998       
3999       if(sign) {
4000         /* signed comparisons to a literal byte */
4001         
4002         int lp1 = (lit+1) & 0xff;
4003         
4004         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4005         switch (lp1) {
4006         case 0:
4007           rFalseIfx.condition ^= 1;
4008           genSkipCond(&rFalseIfx,right,0,7);
4009           break;
4010         case 0x7f:
4011           emitpcode(POC_MOVFW, popGet(AOP(right),0));
4012           emitpcode(POC_XORLW, popGetLit(0x7f));
4013           genSkipz2(&rFalseIfx,1);
4014           break;
4015         default:
4016           emitpcode(POC_MOVFW, popGet(AOP(right),0));
4017           emitpcode(POC_ADDLW, popGetLit(0x80));
4018           emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4019           rFalseIfx.condition ^= 1;
4020           genSkipc(&rFalseIfx);
4021           break;
4022         }
4023         if(ifx) ifx->generated = 1;
4024       } else {
4025         /* unsigned comparisons to a literal byte */
4026         
4027         switch(lit & 0xff ) {
4028         case 0:
4029           emitpcode(POC_MOVFW, popGet(AOP(right),0));
4030           genSkipz2(&rFalseIfx,0);
4031           if(ifx) ifx->generated = 1;
4032           break;
4033         case 0x7f:
4034           genSkipCond(&rFalseIfx,right,0,7);
4035           if(ifx) ifx->generated = 1;
4036           break;
4037           
4038         default:
4039           emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4040           emitpcode(POC_SUBFW, popGet(AOP(right),0));
4041           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4042           rFalseIfx.condition ^= 1;
4043           if (AOP_TYPE(result) == AOP_CRY) {
4044             genSkipc(&rFalseIfx);
4045             if(ifx) ifx->generated = 1;
4046           } else {
4047             DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4048             emitpcode(POC_CLRF, popGet(AOP(result),0));
4049             emitpcode(POC_RLF, popGet(AOP(result),0));
4050             emitpcode(POC_MOVLW, popGetLit(0x01));
4051             emitpcode(POC_XORWF, popGet(AOP(result),0));
4052           }       
4053           break;
4054         }
4055       }
4056       
4057       //goto check_carry;
4058       return;
4059       
4060     } else {
4061       
4062       /* Size is greater than 1 */
4063       
4064       if(sign) {
4065         int lp1 = lit+1;
4066         
4067         size--;
4068         
4069         if(lp1 == 0) {
4070           /* this means lit = 0xffffffff, or -1 */
4071           
4072           
4073           DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4074           rFalseIfx.condition ^= 1;
4075           genSkipCond(&rFalseIfx,right,size,7);
4076           if(ifx) ifx->generated = 1;
4077           return;
4078         }
4079         
4080         if(lit == 0) {
4081           int s = size;
4082           
4083           if(rFalseIfx.condition) {
4084             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4085             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4086           }
4087           
4088           emitpcode(POC_MOVFW, popGet(AOP(right),size));
4089           while(size--)
4090             emitpcode(POC_IORFW, popGet(AOP(right),size));
4091           
4092           
4093           emitSKPZ;
4094           if(rFalseIfx.condition) {
4095             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4096             emitpLabel(truelbl->key);
4097           }else {
4098             rFalseIfx.condition ^= 1;
4099             genSkipCond(&rFalseIfx,right,s,7);
4100           }
4101           
4102           if(ifx) ifx->generated = 1;
4103           return;
4104         }
4105         
4106         if((size == 1) &&  (0 == (lp1&0xff))) {
4107           /* lower byte of signed word is zero */
4108           DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4109           i = ((lp1 >> 8) & 0xff) ^0x80;
4110           emitpcode(POC_MOVFW, popGet(AOP(right),size));
4111           emitpcode(POC_ADDLW, popGetLit( 0x80));
4112           emitpcode(POC_ADDLW, popGetLit(0x100-i));
4113           rFalseIfx.condition ^= 1;
4114           genSkipc(&rFalseIfx);
4115           
4116           
4117           if(ifx) ifx->generated = 1;
4118           return;
4119         }
4120         
4121         if(lit & (0x80 << (size*8))) {
4122           /* Lit is less than zero */
4123           DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4124           //rFalseIfx.condition ^= 1;
4125           //genSkipCond(&rFalseIfx,left,size,7);
4126           //rFalseIfx.condition ^= 1;
4127           emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4128           //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4129           
4130           if(rFalseIfx.condition)
4131             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4132           else
4133             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4134           
4135           
4136         } else {
4137           /* Lit is greater than or equal to zero */
4138           DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4139           //rFalseIfx.condition ^= 1;
4140           //genSkipCond(&rFalseIfx,right,size,7);
4141           //rFalseIfx.condition ^= 1;
4142           
4143           //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4144           //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4145           
4146           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4147           if(rFalseIfx.condition)
4148             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4149           else
4150             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4151           
4152         }
4153         
4154         
4155         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4156         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4157         
4158         while(size--) {
4159           
4160           emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4161           emitSKPNZ;
4162           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4163         }
4164         rFalseIfx.condition ^= 1;
4165         //rFalseIfx.condition = 1;
4166         genSkipc(&rFalseIfx);
4167         
4168         emitpLabel(truelbl->key);
4169         
4170         if(ifx) ifx->generated = 1;
4171         return;
4172         // end of if (sign)
4173   } else {
4174     
4175     /* compare word or long to an unsigned literal on the right.*/
4176     
4177     
4178     size--;
4179     if(lit < 0xff) {
4180       DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4181       switch (lit) {
4182       case 0:
4183         break; /* handled above */
4184       /*
4185       case 0xff:
4186       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4187       while(size--)
4188       emitpcode(POC_IORFW, popGet(AOP(right),size));
4189       genSkipz2(&rFalseIfx,0);
4190       break;
4191       */
4192       default:
4193         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4194         while(--size)
4195           emitpcode(POC_IORFW, popGet(AOP(right),size));
4196         
4197         emitSKPZ;
4198         if(rFalseIfx.condition)
4199           emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4200         else
4201           emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4202         
4203         
4204         emitpcode(POC_MOVLW, popGetLit(lit+1));
4205         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4206         
4207         rFalseIfx.condition ^= 1;
4208         genSkipc(&rFalseIfx);
4209       }
4210       
4211       emitpLabel(truelbl->key);
4212       
4213       if(ifx) ifx->generated = 1;
4214       return;
4215     }
4216     
4217     
4218     lit++;
4219     DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4220     i = (lit >> (size*8)) & 0xff;
4221     
4222     emitpcode(POC_MOVLW, popGetLit(i));
4223     emitpcode(POC_SUBFW, popGet(AOP(right),size));
4224     
4225     while(size--) {
4226       i = (lit >> (size*8)) & 0xff;
4227       
4228       if(i) {
4229         emitpcode(POC_MOVLW, popGetLit(i));
4230         emitSKPNZ;
4231         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4232       } else {
4233       /* this byte of the lit is zero, 
4234         *if it's not the last then OR in the variable */
4235         if(size)
4236           emitpcode(POC_IORFW, popGet(AOP(right),size));
4237       }
4238     }
4239     
4240     
4241     emitpLabel(lbl->key);
4242     
4243     rFalseIfx.condition ^= 1;
4244     genSkipc(&rFalseIfx);
4245   }
4246   
4247   if(sign)
4248     emitpLabel(truelbl->key);
4249   if(ifx) ifx->generated = 1;
4250   return;
4251     }
4252   }
4253   /* Compare two variables */
4254   
4255   DEBUGpic14_emitcode(";sign","%d",sign);
4256   
4257   size--;
4258   if(sign) {
4259     /* Sigh. thus sucks... */
4260     if(size) {
4261       emitpcode(POC_MOVFW, popGet(AOP(left),size));
4262       emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4263       emitpcode(POC_MOVLW, popGetLit(0x80));
4264       emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4265       emitpcode(POC_XORFW, popGet(AOP(right),size));
4266       emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4267     } else {
4268       /* Signed char comparison */
4269       /* Special thanks to Nikolai Golovchenko for this snippet */
4270       emitpcode(POC_MOVFW, popGet(AOP(right),0));
4271       emitpcode(POC_SUBFW, popGet(AOP(left),0));
4272       emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4273       emitpcode(POC_XORFW, popGet(AOP(left),0));
4274       emitpcode(POC_XORFW, popGet(AOP(right),0));
4275       emitpcode(POC_ADDLW, popGetLit(0x80));
4276       
4277       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4278       genSkipc(&rFalseIfx);
4279       
4280       if(ifx) ifx->generated = 1;
4281       return;
4282     }
4283     
4284   } else {
4285     
4286     emitpcode(POC_MOVFW, popGet(AOP(right),size));
4287     emitpcode(POC_SUBFW, popGet(AOP(left),size));
4288   }
4289   
4290   
4291   /* The rest of the bytes of a multi-byte compare */
4292   while (size) {
4293     
4294     emitSKPZ;
4295     emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4296     size--;
4297     
4298     emitpcode(POC_MOVFW, popGet(AOP(right),size));
4299     emitpcode(POC_SUBFW, popGet(AOP(left),size));
4300     
4301     
4302   }
4303   
4304   emitpLabel(lbl->key);
4305   
4306   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4307   if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4308     (AOP_TYPE(result) == AOP_REG)) {
4309     emitpcode(POC_CLRF, popGet(AOP(result),0));
4310     emitpcode(POC_RLF, popGet(AOP(result),0));
4311   } else {
4312     genSkipc(&rFalseIfx);
4313   }       
4314   //genSkipc(&rFalseIfx);
4315   if(ifx) ifx->generated = 1;
4316   
4317   return;
4318   
4319   }
4320   
4321   // check_carry:
4322   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4323     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4324     pic14_outBitC(result);
4325   } else {
4326     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4327     /* if the result is used in the next
4328     ifx conditional branch then generate
4329     code a little differently */
4330     if (ifx )
4331       genIfxJump (ifx,"c");
4332     else
4333       pic14_outBitC(result);
4334     /* leave the result in acc */
4335   }
4336   
4337 }
4338
4339 /*-----------------------------------------------------------------*/
4340 /* genCmpGt :- greater than comparison                             */
4341 /*-----------------------------------------------------------------*/
4342 static void genCmpGt (iCode *ic, iCode *ifx)
4343 {
4344   operand *left, *right, *result;
4345   sym_link *letype , *retype;
4346   int sign ;
4347   
4348   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4349   left = IC_LEFT(ic);
4350   right= IC_RIGHT(ic);
4351   result = IC_RESULT(ic);
4352   
4353   letype = getSpec(operandType(left));
4354   retype =getSpec(operandType(right));
4355   sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4356   /* assign the amsops */
4357   aopOp (left,ic,FALSE);
4358   aopOp (right,ic,FALSE);
4359   aopOp (result,ic,TRUE);
4360   
4361   genCmp(right, left, result, ifx, sign);
4362   
4363   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4364   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4365   freeAsmop(result,NULL,ic,TRUE); 
4366 }
4367
4368 /*-----------------------------------------------------------------*/
4369 /* genCmpLt - less than comparisons                                */
4370 /*-----------------------------------------------------------------*/
4371 static void genCmpLt (iCode *ic, iCode *ifx)
4372 {
4373   operand *left, *right, *result;
4374   sym_link *letype , *retype;
4375   int sign ;
4376   
4377   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4378   left = IC_LEFT(ic);
4379   right= IC_RIGHT(ic);
4380   result = IC_RESULT(ic);
4381   
4382   letype = getSpec(operandType(left));
4383   retype =getSpec(operandType(right));
4384   sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4385   
4386   /* assign the amsops */
4387   aopOp (left,ic,FALSE);
4388   aopOp (right,ic,FALSE);
4389   aopOp (result,ic,TRUE);
4390   
4391   genCmp(left, right, result, ifx, sign);
4392   
4393   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4394   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4395   freeAsmop(result,NULL,ic,TRUE); 
4396 }
4397
4398 /*-----------------------------------------------------------------*/
4399 /* genc16bit2lit - compare a 16 bit value to a literal             */
4400 /*-----------------------------------------------------------------*/
4401 static void genc16bit2lit(operand *op, int lit, int offset)
4402 {
4403   int i;
4404   
4405   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4406   if( (lit&0xff) == 0) 
4407     i=1;
4408   else
4409     i=0;
4410   
4411   switch( BYTEofLONG(lit,i)) { 
4412   case 0:
4413     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4414     break;
4415   case 1:
4416     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4417     break;
4418   case 0xff:
4419     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4420     break;
4421   default:
4422     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4423     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4424   }
4425   
4426   i ^= 1;
4427   
4428   switch( BYTEofLONG(lit,i)) { 
4429   case 0:
4430     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4431     break;
4432   case 1:
4433     emitSKPNZ;
4434     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4435     break;
4436   case 0xff:
4437     emitSKPNZ;
4438     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4439     break;
4440   default:
4441     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4442     emitSKPNZ;
4443     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4444     
4445   }
4446   
4447 }
4448
4449 /*-----------------------------------------------------------------*/
4450 /* gencjneshort - compare and jump if not equal                    */
4451 /*-----------------------------------------------------------------*/
4452 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4453 {
4454   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4455   int offset = 0;
4456   int res_offset = 0;  /* the result may be a different size then left or right */
4457   int res_size = AOP_SIZE(result);
4458   resolvedIfx rIfx;
4459   symbol *lbl;
4460   
4461   unsigned long lit = 0L;
4462   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4463   DEBUGpic14_AopType(__LINE__,left,right,result);
4464   if(result)
4465     DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4466   resolveIfx(&rIfx,ifx);
4467   lbl =  newiTempLabel(NULL);
4468   
4469   
4470   /* if the left side is a literal or 
4471   if the right is in a pointer register and left 
4472   is not */
4473   if ((AOP_TYPE(left) == AOP_LIT) || 
4474     (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4475     operand *t = right;
4476     right = left;
4477     left = t;
4478   }
4479   if(AOP_TYPE(right) == AOP_LIT)
4480     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4481   
4482   /* if the right side is a literal then anything goes */
4483   if (AOP_TYPE(right) == AOP_LIT &&
4484     AOP_TYPE(left) != AOP_DIR ) {
4485     switch(size) {
4486     case 2:
4487       genc16bit2lit(left, lit, 0);
4488       emitSKPNZ;
4489       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4490       break;
4491     default:
4492       while (size--) {
4493         if(lit & 0xff) {
4494           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4495           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4496         } else {
4497           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4498         }
4499         
4500         emitSKPNZ;
4501         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4502         offset++;
4503         if(res_offset < res_size-1)
4504           res_offset++;
4505         lit >>= 8;
4506       }
4507       break;
4508     }
4509   }
4510   
4511   /* if the right side is in a register or in direct space or
4512   if the left is a pointer register & right is not */    
4513   else if (AOP_TYPE(right) == AOP_REG ||
4514     AOP_TYPE(right) == AOP_DIR || 
4515     (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4516     (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4517     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4518     int lbl_key = lbl->key;
4519     
4520     if(result) {
4521       emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4522       //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4523     }else {
4524       DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4525       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4526         __FUNCTION__,__LINE__);
4527       return;
4528     }
4529     
4530     /*     switch(size) { */
4531     /*     case 2: */
4532     /*       genc16bit2lit(left, lit, 0); */
4533     /*       emitSKPNZ; */
4534     /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4535     /*       break; */
4536     /*     default: */
4537     while (size--) {
4538       int emit_skip=1;
4539       if((AOP_TYPE(left) == AOP_DIR) && 
4540         ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4541         
4542         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4543         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4544         
4545       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4546         
4547         switch (lit & 0xff) {
4548         case 0:
4549           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4550           break;
4551         case 1:
4552           emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4553           emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4554           //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4555           emit_skip=0;
4556           break;
4557         case 0xff:
4558           emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4559           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4560           //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4561           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4562           emit_skip=0;
4563           break;
4564         default:
4565           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4566           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4567         }
4568         lit >>= 8;
4569         
4570       } else {
4571         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4572       }
4573       if(emit_skip) {
4574         if(AOP_TYPE(result) == AOP_CRY) {
4575           pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4576           if(rIfx.condition)
4577             emitSKPNZ;
4578           else
4579             emitSKPZ;
4580           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4581         } else {
4582           /* fix me. probably need to check result size too */
4583           //emitpcode(POC_CLRF,popGet(AOP(result),0));
4584           if(rIfx.condition)
4585             emitSKPZ;
4586           else
4587             emitSKPNZ;
4588           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4589           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4590         }
4591         if(ifx)
4592           ifx->generated=1;
4593       }
4594       emit_skip++;
4595       offset++;
4596       if(res_offset < res_size-1)
4597         res_offset++;
4598     }
4599     /*       break; */
4600     /*     } */
4601   } else if(AOP_TYPE(right) == AOP_REG &&
4602     AOP_TYPE(left) != AOP_DIR){
4603     
4604     while(size--) {
4605       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4606       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4607       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4608       if(rIfx.condition)
4609         emitSKPNZ;
4610       else
4611         emitSKPZ;
4612       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4613       offset++;
4614       if(res_offset < res_size-1)
4615         res_offset++;
4616     }
4617     
4618   }else{
4619     /* right is a pointer reg need both a & b */
4620     while(size--) {
4621       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4622       if(strcmp(l,"b"))
4623         pic14_emitcode("mov","b,%s",l);
4624       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4625       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4626       offset++;
4627     }
4628   }
4629   
4630   emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4631   if(!rIfx.condition)
4632     emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4633   
4634   emitpLabel(lbl->key);
4635   
4636   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4637   
4638   if(ifx)
4639     ifx->generated = 1;
4640 }
4641
4642 #if 0
4643 /*-----------------------------------------------------------------*/
4644 /* gencjne - compare and jump if not equal                         */
4645 /*-----------------------------------------------------------------*/
4646 static void gencjne(operand *left, operand *right, iCode *ifx)
4647 {
4648   symbol *tlbl  = newiTempLabel(NULL);
4649   
4650   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4651   gencjneshort(left, right, lbl);
4652   
4653   pic14_emitcode("mov","a,%s",one);
4654   pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4655   pic14_emitcode("","%05d_DS_:",lbl->key+100);
4656   pic14_emitcode("clr","a");
4657   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4658   
4659   emitpLabel(lbl->key);
4660   emitpLabel(tlbl->key);
4661   
4662 }
4663 #endif
4664
4665 /*-----------------------------------------------------------------*/
4666 /* genCmpEq - generates code for equal to                          */
4667 /*-----------------------------------------------------------------*/
4668 static void genCmpEq (iCode *ic, iCode *ifx)
4669 {
4670   operand *left, *right, *result;
4671   unsigned long lit = 0L;
4672   int size,offset=0;
4673   
4674   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4675   
4676   if(ifx)
4677     DEBUGpic14_emitcode ("; ifx is non-null","");
4678   else
4679     DEBUGpic14_emitcode ("; ifx is null","");
4680   
4681   aopOp((left=IC_LEFT(ic)),ic,FALSE);
4682   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4683   aopOp((result=IC_RESULT(ic)),ic,TRUE);
4684   
4685   size = max(AOP_SIZE(left),AOP_SIZE(right));
4686   
4687   DEBUGpic14_AopType(__LINE__,left,right,result);
4688   
4689   /* if literal, literal on the right or 
4690   if the right is in a pointer register and left 
4691   is not */
4692   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4693     (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4694     operand *tmp = right ;
4695     right = left;
4696     left = tmp;
4697   }
4698   
4699   
4700   if(ifx && !AOP_SIZE(result)){
4701     symbol *tlbl;
4702     /* if they are both bit variables */
4703     if (AOP_TYPE(left) == AOP_CRY &&
4704       ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4705       if(AOP_TYPE(right) == AOP_LIT){
4706         unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4707         if(lit == 0L){
4708           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4709           pic14_emitcode("cpl","c");
4710         } else if(lit == 1L) {
4711           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4712         } else {
4713           pic14_emitcode("clr","c");
4714         }
4715         /* AOP_TYPE(right) == AOP_CRY */
4716       } else {
4717         symbol *lbl = newiTempLabel(NULL);
4718         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4719         pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4720         pic14_emitcode("cpl","c");
4721         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4722       }
4723       /* if true label then we jump if condition
4724       supplied is true */
4725       tlbl = newiTempLabel(NULL);
4726       if ( IC_TRUE(ifx) ) {
4727         pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4728         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4729       } else {
4730         pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4731         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4732       }
4733       pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4734       
4735       {
4736         /* left and right are both bit variables, result is carry */
4737         resolvedIfx rIfx;
4738         
4739         resolveIfx(&rIfx,ifx);
4740         
4741         emitpcode(POC_MOVLW,popGet(AOP(left),0));
4742         emitpcode(POC_ANDFW,popGet(AOP(left),0));
4743         emitpcode(POC_BTFSC,popGet(AOP(right),0));
4744         emitpcode(POC_ANDLW,popGet(AOP(left),0));
4745         genSkipz2(&rIfx,0);
4746       }
4747     } else {
4748       
4749       /* They're not both bit variables. Is the right a literal? */
4750       if(AOP_TYPE(right) == AOP_LIT) {
4751         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4752         
4753         switch(size) {
4754           
4755         case 1:
4756           switch(lit & 0xff) {
4757           case 1:
4758             if ( IC_TRUE(ifx) ) {
4759               emitpcode(POC_DECFW,popGet(AOP(left),offset));
4760               emitSKPNZ;
4761               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4762             } else {
4763               emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4764               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4765             }
4766             break;
4767           case 0xff:
4768             if ( IC_TRUE(ifx) ) {
4769               emitpcode(POC_INCFW,popGet(AOP(left),offset));
4770               emitSKPNZ;
4771               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4772             } else {
4773               emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4774               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4775             }
4776             break;
4777           default:
4778             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4779             if(lit)
4780               emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4781             genSkip(ifx,'z');
4782           }
4783           
4784           
4785           /* end of size == 1 */
4786           break;
4787           
4788           case 2:
4789             genc16bit2lit(left,lit,offset);
4790             genSkip(ifx,'z');
4791             break;
4792             /* end of size == 2 */
4793             
4794           default:
4795             /* size is 4 */
4796             if(lit==0) {
4797               emitpcode(POC_MOVFW,popGet(AOP(left),0));
4798               emitpcode(POC_IORFW,popGet(AOP(left),1));
4799               emitpcode(POC_IORFW,popGet(AOP(left),2));
4800               emitpcode(POC_IORFW,popGet(AOP(left),3));
4801               
4802             } else {
4803               
4804               /* search for patterns that can be optimized */
4805               
4806               genc16bit2lit(left,lit,0);
4807               lit >>= 16;
4808               if(lit) {
4809                 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4810                 //genSkip(ifx,'z');
4811                 genc16bit2lit(left,lit,2);
4812               } else {
4813                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4814                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4815                 
4816               }
4817               
4818             }
4819             
4820             genSkip(ifx,'z');
4821         }
4822         
4823         ifx->generated = 1;
4824         goto release ;
4825         
4826         
4827       } else if(AOP_TYPE(right) == AOP_CRY ) {
4828         /* we know the left is not a bit, but that the right is */
4829         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4830         emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4831           popGet(AOP(right),offset));
4832         emitpcode(POC_XORLW,popGetLit(1));
4833         
4834         /* if the two are equal, then W will be 0 and the Z bit is set
4835         * we could test Z now, or go ahead and check the high order bytes if
4836         * the variable we're comparing is larger than a byte. */
4837         
4838         while(--size)
4839           emitpcode(POC_IORFW,popGet(AOP(left),offset));
4840         
4841         if ( IC_TRUE(ifx) ) {
4842           emitSKPNZ;
4843           emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4844           pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4845         } else {
4846           emitSKPZ;
4847           emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4848           pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4849         }
4850         
4851       } else {
4852         /* They're both variables that are larger than bits */
4853         int s = size;
4854         
4855         tlbl = newiTempLabel(NULL);
4856         
4857         while(size--) {
4858           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4859           emitpcode(POC_XORFW,popGet(AOP(right),offset));
4860           
4861           if ( IC_TRUE(ifx) ) {
4862             if(size) {
4863               emitSKPZ;
4864               emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4865               pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4866             } else {
4867               emitSKPNZ;
4868               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4869               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4870             }
4871           } else {
4872             emitSKPZ;
4873             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4874             pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4875           }
4876           offset++;
4877         }
4878         if(s>1 && IC_TRUE(ifx)) {
4879           emitpLabel(tlbl->key);
4880           pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4881         }
4882       }
4883     }
4884     /* mark the icode as generated */
4885     ifx->generated = 1;
4886     goto release ;
4887   }
4888   
4889   /* if they are both bit variables */
4890   if (AOP_TYPE(left) == AOP_CRY &&
4891     ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4892     if(AOP_TYPE(right) == AOP_LIT){
4893       unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4894       if(lit == 0L){
4895         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4896         pic14_emitcode("cpl","c");
4897       } else if(lit == 1L) {
4898         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4899       } else {
4900         pic14_emitcode("clr","c");
4901       }
4902       /* AOP_TYPE(right) == AOP_CRY */
4903     } else {
4904       symbol *lbl = newiTempLabel(NULL);
4905       pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4906       pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4907       pic14_emitcode("cpl","c");
4908       pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4909     }
4910     /* c = 1 if egal */
4911     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4912       pic14_outBitC(result);
4913       goto release ;
4914     }
4915     if (ifx) {
4916       genIfxJump (ifx,"c");
4917       goto release ;
4918     }
4919     /* if the result is used in an arithmetic operation
4920     then put the result in place */
4921     pic14_outBitC(result);
4922   } else {
4923     
4924     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4925     gencjne(left,right,result,ifx);
4926     /*
4927     if(ifx) 
4928     gencjne(left,right,newiTempLabel(NULL));
4929     else {
4930     if(IC_TRUE(ifx)->key)
4931     gencjne(left,right,IC_TRUE(ifx)->key);
4932     else
4933     gencjne(left,right,IC_FALSE(ifx)->key);
4934     ifx->generated = 1;
4935     goto release ;
4936     }
4937     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4938     aopPut(AOP(result),"a",0);
4939     goto release ;
4940     }
4941     
4942       if (ifx) {
4943       genIfxJump (ifx,"a");
4944       goto release ;
4945       }
4946     */
4947     /* if the result is used in an arithmetic operation
4948     then put the result in place */
4949     /*
4950     if (AOP_TYPE(result) != AOP_CRY) 
4951     pic14_outAcc(result);
4952     */
4953     /* leave the result in acc */
4954   }
4955   
4956 release:
4957   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4958   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4959   freeAsmop(result,NULL,ic,TRUE);
4960 }
4961
4962 /*-----------------------------------------------------------------*/
4963 /* ifxForOp - returns the icode containing the ifx for operand     */
4964 /*-----------------------------------------------------------------*/
4965 static iCode *ifxForOp ( operand *op, iCode *ic )
4966 {
4967   /* if true symbol then needs to be assigned */
4968   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4969   if (IS_TRUE_SYMOP(op))
4970     return NULL ;
4971   
4972     /* if this has register type condition and
4973     the next instruction is ifx with the same operand
4974   and live to of the operand is upto the ifx only then */
4975   if (ic->next &&
4976     ic->next->op == IFX &&
4977     IC_COND(ic->next)->key == op->key &&
4978     OP_SYMBOL(op)->liveTo <= ic->next->seq )
4979     return ic->next;
4980   
4981   if (ic->next &&
4982     ic->next->op == IFX &&
4983     IC_COND(ic->next)->key == op->key) {
4984     DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4985     return ic->next;
4986   }
4987   
4988   DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4989   if (ic->next &&
4990     ic->next->op == IFX)
4991     DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4992   
4993   if (ic->next &&
4994     ic->next->op == IFX &&
4995     IC_COND(ic->next)->key == op->key) {
4996     DEBUGpic14_emitcode ("; "," key is okay");
4997     DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4998       OP_SYMBOL(op)->liveTo,
4999       ic->next->seq);
5000   }
5001   
5002   
5003   return NULL;
5004 }
5005 /*-----------------------------------------------------------------*/
5006 /* genAndOp - for && operation                                     */
5007 /*-----------------------------------------------------------------*/
5008 static void genAndOp (iCode *ic)
5009 {
5010   operand *left,*right, *result;
5011   /*     symbol *tlbl; */
5012   
5013   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5014   /* note here that && operations that are in an
5015   if statement are taken away by backPatchLabels
5016   only those used in arthmetic operations remain */
5017   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5018   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5019   aopOp((result=IC_RESULT(ic)),ic,FALSE);
5020   
5021   DEBUGpic14_AopType(__LINE__,left,right,result);
5022   
5023   emitpcode(POC_MOVFW,popGet(AOP(left),0));
5024   emitpcode(POC_ANDFW,popGet(AOP(right),0));
5025   emitpcode(POC_MOVWF,popGet(AOP(result),0));
5026   
5027   /* if both are bit variables */
5028   /*     if (AOP_TYPE(left) == AOP_CRY && */
5029   /*         AOP_TYPE(right) == AOP_CRY ) { */
5030   /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5031   /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5032   /*         pic14_outBitC(result); */
5033   /*     } else { */
5034   /*         tlbl = newiTempLabel(NULL); */
5035   /*         pic14_toBoolean(left);     */
5036   /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5037   /*         pic14_toBoolean(right); */
5038   /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5039   /*         pic14_outBitAcc(result); */
5040   /*     } */
5041   
5042   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5043   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5044   freeAsmop(result,NULL,ic,TRUE);
5045 }
5046
5047
5048 /*-----------------------------------------------------------------*/
5049 /* genOrOp - for || operation                                      */
5050 /*-----------------------------------------------------------------*/
5051 /*
5052 tsd pic port -
5053 modified this code, but it doesn't appear to ever get called
5054 */
5055
5056 static void genOrOp (iCode *ic)
5057 {
5058   operand *left,*right, *result;
5059   symbol *tlbl;
5060   
5061   /* note here that || operations that are in an
5062   if statement are taken away by backPatchLabels
5063   only those used in arthmetic operations remain */
5064   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5065   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5066   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5067   aopOp((result=IC_RESULT(ic)),ic,FALSE);
5068   
5069   DEBUGpic14_AopType(__LINE__,left,right,result);
5070   
5071   /* if both are bit variables */
5072   if (AOP_TYPE(left) == AOP_CRY &&
5073     AOP_TYPE(right) == AOP_CRY ) {
5074     pic14_emitcode("clrc","");
5075     pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5076       AOP(left)->aopu.aop_dir,
5077       AOP(left)->aopu.aop_dir);
5078     pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5079       AOP(right)->aopu.aop_dir,
5080       AOP(right)->aopu.aop_dir);
5081     pic14_emitcode("setc","");
5082     
5083   } else {
5084     tlbl = newiTempLabel(NULL);
5085     pic14_toBoolean(left);
5086     emitSKPZ;
5087     pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5088     pic14_toBoolean(right);
5089     pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5090     
5091     pic14_outBitAcc(result);
5092   }
5093   
5094   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5095   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5096   freeAsmop(result,NULL,ic,TRUE);            
5097 }
5098
5099 /*-----------------------------------------------------------------*/
5100 /* isLiteralBit - test if lit == 2^n                               */
5101 /*-----------------------------------------------------------------*/
5102 static int isLiteralBit(unsigned long lit)
5103 {
5104   unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5105     0x100L,0x200L,0x400L,0x800L,
5106     0x1000L,0x2000L,0x4000L,0x8000L,
5107     0x10000L,0x20000L,0x40000L,0x80000L,
5108     0x100000L,0x200000L,0x400000L,0x800000L,
5109     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5110     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5111   int idx;
5112   
5113   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5114   for(idx = 0; idx < 32; idx++)
5115     if(lit == pw[idx])
5116       return idx+1;
5117     return 0;
5118 }
5119
5120 /*-----------------------------------------------------------------*/
5121 /* continueIfTrue -                                                */
5122 /*-----------------------------------------------------------------*/
5123 static void continueIfTrue (iCode *ic)
5124 {
5125   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5126   if(IC_TRUE(ic))
5127     pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5128   ic->generated = 1;
5129 }
5130
5131 /*-----------------------------------------------------------------*/
5132 /* jmpIfTrue -                                                     */
5133 /*-----------------------------------------------------------------*/
5134 static void jumpIfTrue (iCode *ic)
5135 {
5136   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5137   if(!IC_TRUE(ic))
5138     pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5139   ic->generated = 1;
5140 }
5141
5142 /*-----------------------------------------------------------------*/
5143 /* jmpTrueOrFalse -                                                */
5144 /*-----------------------------------------------------------------*/
5145 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5146 {
5147   // ugly but optimized by peephole
5148   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5149   if(IC_TRUE(ic)){
5150     symbol *nlbl = newiTempLabel(NULL);
5151     pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5152     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5153     pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5154     pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5155   }
5156   else{
5157     pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5158     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5159   }
5160   ic->generated = 1;
5161 }
5162
5163 /*-----------------------------------------------------------------*/
5164 /* genAnd  - code for and                                          */
5165 /*-----------------------------------------------------------------*/
5166 static void genAnd (iCode *ic, iCode *ifx)
5167 {
5168   operand *left, *right, *result;
5169   int size, offset=0;  
5170   unsigned long lit = 0L;
5171   int bytelit = 0;
5172   resolvedIfx rIfx;
5173   
5174   
5175   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5176   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5177   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5178   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5179   
5180   resolveIfx(&rIfx,ifx);
5181   
5182   /* if left is a literal & right is not then exchange them */
5183   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5184     AOP_NEEDSACC(left)) {
5185     operand *tmp = right ;
5186     right = left;
5187     left = tmp;
5188   }
5189   
5190   /* if result = right then exchange them */
5191   if(pic14_sameRegs(AOP(result),AOP(right))){
5192     operand *tmp = right ;
5193     right = left;
5194     left = tmp;
5195   }
5196   
5197   /* if right is bit then exchange them */
5198   if (AOP_TYPE(right) == AOP_CRY &&
5199     AOP_TYPE(left) != AOP_CRY){
5200     operand *tmp = right ;
5201     right = left;
5202     left = tmp;
5203   }
5204   if(AOP_TYPE(right) == AOP_LIT)
5205     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5206   
5207   size = AOP_SIZE(result);
5208   
5209   DEBUGpic14_AopType(__LINE__,left,right,result);
5210   
5211   // if(bit & yy)
5212   // result = bit & yy;
5213   if (AOP_TYPE(left) == AOP_CRY){
5214     // c = bit & literal;
5215     if(AOP_TYPE(right) == AOP_LIT){
5216       if(lit & 1) {
5217         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5218           // no change
5219           goto release;
5220         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5221       } else {
5222         // bit(result) = 0;
5223         if(size && (AOP_TYPE(result) == AOP_CRY)){
5224           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5225           goto release;
5226         }
5227         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5228           jumpIfTrue(ifx);
5229           goto release;
5230         }
5231         pic14_emitcode("clr","c");
5232       }
5233     } else {
5234       if (AOP_TYPE(right) == AOP_CRY){
5235         // c = bit & bit;
5236         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5237         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5238       } else {
5239         // c = bit & val;
5240         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5241         // c = lsb
5242         pic14_emitcode("rrc","a");
5243         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5244       }
5245     }
5246     // bit = c
5247     // val = c
5248     if(size)
5249       pic14_outBitC(result);
5250     // if(bit & ...)
5251     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5252       genIfxJump(ifx, "c");           
5253     goto release ;
5254   }
5255   
5256   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5257   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5258   if((AOP_TYPE(right) == AOP_LIT) &&
5259     (AOP_TYPE(result) == AOP_CRY) &&
5260     (AOP_TYPE(left) != AOP_CRY)){
5261     int posbit = isLiteralBit(lit);
5262     /* left &  2^n */
5263     if(posbit){
5264       posbit--;
5265       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5266       // bit = left & 2^n
5267       if(size)
5268         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5269       // if(left &  2^n)
5270       else{
5271         if(ifx){
5272           int offset = 0;
5273           while (posbit > 7) {
5274             posbit -= 8;
5275             offset++;
5276           }
5277           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5278             newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5279           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5280           
5281           ifx->generated = 1;
5282         }
5283         goto release;
5284       }
5285     } else {
5286       symbol *tlbl = newiTempLabel(NULL);
5287       int sizel = AOP_SIZE(left);
5288       if(size)
5289         pic14_emitcode("setb","c");
5290       while(sizel--){
5291         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5292           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5293           // byte ==  2^n ?
5294           if((posbit = isLiteralBit(bytelit)) != 0)
5295             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5296           else{
5297             if(bytelit != 0x0FFL)
5298               pic14_emitcode("anl","a,%s",
5299               aopGet(AOP(right),offset,FALSE,TRUE));
5300             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5301           }
5302         }
5303         offset++;
5304       }
5305       // bit = left & literal
5306       if(size){
5307         pic14_emitcode("clr","c");
5308         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5309       }
5310       // if(left & literal)
5311       else{
5312         if(ifx)
5313           jmpTrueOrFalse(ifx, tlbl);
5314         goto release ;
5315       }
5316     }
5317     pic14_outBitC(result);
5318     goto release ;
5319   }
5320   
5321   /* if left is same as result */
5322   if(pic14_sameRegs(AOP(result),AOP(left))){
5323     int know_W = -1;
5324     for(;size--; offset++,lit>>=8) {
5325       if(AOP_TYPE(right) == AOP_LIT){
5326         switch(lit & 0xff) {
5327         case 0x00:
5328           /*  and'ing with 0 has clears the result */
5329           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5330           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5331           break;
5332         case 0xff:
5333           /* and'ing with 0xff is a nop when the result and left are the same */
5334           break;
5335           
5336         default:
5337           {
5338             int p = my_powof2( (~lit) & 0xff );
5339             if(p>=0) {
5340               /* only one bit is set in the literal, so use a bcf instruction */
5341               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5342               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5343               
5344             } else {
5345               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5346               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5347               if(know_W != (int)(lit&0xff))
5348                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5349               know_W = lit &0xff;
5350               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5351             }
5352           }    
5353         }
5354       } else {
5355         if (AOP_TYPE(left) == AOP_ACC) {
5356           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5357         } else {        
5358           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5359           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5360           
5361         }
5362       }
5363     }
5364     
5365   } else {
5366     // left & result in different registers
5367     if(AOP_TYPE(result) == AOP_CRY){
5368       // result = bit
5369       // if(size), result in bit
5370       // if(!size && ifx), conditional oper: if(left & right)
5371       symbol *tlbl = newiTempLabel(NULL);
5372       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5373       if(size)
5374         pic14_emitcode("setb","c");
5375       while(sizer--){
5376         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5377         pic14_emitcode("anl","a,%s",
5378           aopGet(AOP(left),offset,FALSE,FALSE));
5379         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5380         offset++;
5381       }
5382       if(size){
5383         CLRC;
5384         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5385         pic14_outBitC(result);
5386       } else if(ifx)
5387         jmpTrueOrFalse(ifx, tlbl);
5388     } else {
5389       for(;(size--);offset++) {
5390         // normal case
5391         // result = left & right
5392         if(AOP_TYPE(right) == AOP_LIT){
5393           int t = (lit >> (offset*8)) & 0x0FFL;
5394           switch(t) { 
5395           case 0x00:
5396             pic14_emitcode("clrf","%s",
5397               aopGet(AOP(result),offset,FALSE,FALSE));
5398             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5399             break;
5400           case 0xff:
5401             if(AOP_TYPE(left) != AOP_ACC) {
5402               pic14_emitcode("movf","%s,w",
5403                 aopGet(AOP(left),offset,FALSE,FALSE));
5404               pic14_emitcode("movwf","%s",
5405                 aopGet(AOP(result),offset,FALSE,FALSE));
5406               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5407             }
5408             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5409             break;
5410           default:
5411             if(AOP_TYPE(left) == AOP_ACC) {
5412               emitpcode(POC_ANDLW, popGetLit(t));
5413             } else {
5414               pic14_emitcode("movlw","0x%x",t);
5415               pic14_emitcode("andwf","%s,w",
5416                 aopGet(AOP(left),offset,FALSE,FALSE));
5417               pic14_emitcode("movwf","%s",
5418                 aopGet(AOP(result),offset,FALSE,FALSE));
5419               
5420               emitpcode(POC_MOVLW, popGetLit(t));
5421               emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5422             }
5423             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5424           }
5425           continue;
5426         }
5427         
5428         if (AOP_TYPE(left) == AOP_ACC) {
5429           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5430           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5431         } else {
5432           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5433           pic14_emitcode("andwf","%s,w",
5434             aopGet(AOP(left),offset,FALSE,FALSE));
5435           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5436           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5437         }
5438         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5439         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5440       }
5441     }
5442   }
5443   
5444 release :
5445   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5446   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5447   freeAsmop(result,NULL,ic,TRUE);     
5448 }
5449
5450 /*-----------------------------------------------------------------*/
5451 /* genOr  - code for or                                            */
5452 /*-----------------------------------------------------------------*/
5453 static void genOr (iCode *ic, iCode *ifx)
5454 {
5455   operand *left, *right, *result;
5456   int size, offset=0;
5457   unsigned long lit = 0L;
5458   
5459   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5460   
5461   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5462   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5463   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5464   
5465   DEBUGpic14_AopType(__LINE__,left,right,result);
5466   
5467   /* if left is a literal & right is not then exchange them */
5468   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5469     AOP_NEEDSACC(left)) {
5470     operand *tmp = right ;
5471     right = left;
5472     left = tmp;
5473   }
5474   
5475   /* if result = right then exchange them */
5476   if(pic14_sameRegs(AOP(result),AOP(right))){
5477     operand *tmp = right ;
5478     right = left;
5479     left = tmp;
5480   }
5481   
5482   /* if right is bit then exchange them */
5483   if (AOP_TYPE(right) == AOP_CRY &&
5484     AOP_TYPE(left) != AOP_CRY){
5485     operand *tmp = right ;
5486     right = left;
5487     left = tmp;
5488   }
5489   
5490   DEBUGpic14_AopType(__LINE__,left,right,result);
5491   
5492   if(AOP_TYPE(right) == AOP_LIT)
5493     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5494   
5495   size = AOP_SIZE(result);
5496   
5497   // if(bit | yy)
5498   // xx = bit | yy;
5499   if (AOP_TYPE(left) == AOP_CRY){
5500     if(AOP_TYPE(right) == AOP_LIT){
5501       // c = bit & literal;
5502       if(lit){
5503         // lit != 0 => result = 1
5504         if(AOP_TYPE(result) == AOP_CRY){
5505           if(size)
5506             emitpcode(POC_BSF, popGet(AOP(result),0));
5507           //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5508           //   AOP(result)->aopu.aop_dir,
5509           //   AOP(result)->aopu.aop_dir);
5510           else if(ifx)
5511             continueIfTrue(ifx);
5512           goto release;
5513         }
5514       } else {
5515         // lit == 0 => result = left
5516         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5517           goto release;
5518         pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5519       }
5520     } else {
5521       if (AOP_TYPE(right) == AOP_CRY){
5522         if(pic14_sameRegs(AOP(result),AOP(left))){
5523           // c = bit | bit;
5524           emitpcode(POC_BCF,   popGet(AOP(result),0));
5525           emitpcode(POC_BTFSC, popGet(AOP(right),0));
5526           emitpcode(POC_BSF,   popGet(AOP(result),0));
5527           
5528           pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5529             AOP(result)->aopu.aop_dir,
5530             AOP(result)->aopu.aop_dir);
5531           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5532             AOP(right)->aopu.aop_dir,
5533             AOP(right)->aopu.aop_dir);
5534           pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5535             AOP(result)->aopu.aop_dir,
5536             AOP(result)->aopu.aop_dir);
5537         } else {
5538           if( AOP_TYPE(result) == AOP_ACC) {
5539             emitpcode(POC_MOVLW, popGetLit(0));
5540             emitpcode(POC_BTFSS, popGet(AOP(right),0));
5541             emitpcode(POC_BTFSC, popGet(AOP(left),0));
5542             emitpcode(POC_MOVLW, popGetLit(1));
5543             
5544           } else {
5545             
5546             emitpcode(POC_BCF,   popGet(AOP(result),0));
5547             emitpcode(POC_BTFSS, popGet(AOP(right),0));
5548             emitpcode(POC_BTFSC, popGet(AOP(left),0));
5549             emitpcode(POC_BSF,   popGet(AOP(result),0));
5550             
5551             pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5552               AOP(result)->aopu.aop_dir,
5553               AOP(result)->aopu.aop_dir);
5554             pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5555               AOP(right)->aopu.aop_dir,
5556               AOP(right)->aopu.aop_dir);
5557             pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5558               AOP(left)->aopu.aop_dir,
5559               AOP(left)->aopu.aop_dir);
5560             pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5561               AOP(result)->aopu.aop_dir,
5562               AOP(result)->aopu.aop_dir);
5563           }
5564         }
5565       } else {
5566         // c = bit | val;
5567         symbol *tlbl = newiTempLabel(NULL);
5568         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5569         
5570         
5571         emitpcode(POC_BCF,   popGet(AOP(result),0));
5572         if( AOP_TYPE(right) == AOP_ACC) {
5573           emitpcode(POC_IORLW, popGetLit(0));
5574           emitSKPNZ;
5575           emitpcode(POC_BTFSC, popGet(AOP(left),0));
5576           emitpcode(POC_BSF,   popGet(AOP(result),0));
5577         }
5578         
5579         
5580         
5581         if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5582           pic14_emitcode(";XXX setb","c");
5583         pic14_emitcode(";XXX jb","%s,%05d_DS_",
5584           AOP(left)->aopu.aop_dir,tlbl->key+100);
5585         pic14_toBoolean(right);
5586         pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5587         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5588           jmpTrueOrFalse(ifx, tlbl);
5589           goto release;
5590         } else {
5591           CLRC;
5592           pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5593         }
5594       }
5595     }
5596     // bit = c
5597     // val = c
5598     if(size)
5599       pic14_outBitC(result);
5600     // if(bit | ...)
5601     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5602       genIfxJump(ifx, "c");           
5603     goto release ;
5604   }
5605   
5606   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5607   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5608   if((AOP_TYPE(right) == AOP_LIT) &&
5609     (AOP_TYPE(result) == AOP_CRY) &&
5610     (AOP_TYPE(left) != AOP_CRY)){
5611     if(lit){
5612       pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5613       // result = 1
5614       if(size)
5615         pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5616       else 
5617         continueIfTrue(ifx);
5618       goto release;
5619     } else {
5620       pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5621       // lit = 0, result = boolean(left)
5622       if(size)
5623         pic14_emitcode(";XXX setb","c");
5624       pic14_toBoolean(right);
5625       if(size){
5626         symbol *tlbl = newiTempLabel(NULL);
5627         pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5628         CLRC;
5629         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5630       } else {
5631         genIfxJump (ifx,"a");
5632         goto release;
5633       }
5634     }
5635     pic14_outBitC(result);
5636     goto release ;
5637   }
5638   
5639   /* if left is same as result */
5640   if(pic14_sameRegs(AOP(result),AOP(left))){
5641     int know_W = -1;
5642     for(;size--; offset++,lit>>=8) {
5643       if(AOP_TYPE(right) == AOP_LIT){
5644         if((lit & 0xff) == 0)
5645           /*  or'ing with 0 has no effect */
5646           continue;
5647         else {
5648           int p = my_powof2(lit & 0xff);
5649           if(p>=0) {
5650             /* only one bit is set in the literal, so use a bsf instruction */
5651             emitpcode(POC_BSF,
5652               newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5653           } else {
5654             if(know_W != (int)(lit & 0xff))
5655               emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5656             know_W = lit & 0xff;
5657             emitpcode(POC_IORWF, popGet(AOP(left),offset));
5658           }
5659           
5660         }
5661       } else {
5662         if (AOP_TYPE(left) == AOP_ACC) {
5663           emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5664           pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5665         } else {        
5666           emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5667           emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5668           
5669           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5670           pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5671           
5672         }
5673       }
5674     }
5675   } else {
5676     // left & result in different registers
5677     if(AOP_TYPE(result) == AOP_CRY){
5678       // result = bit
5679       // if(size), result in bit
5680       // if(!size && ifx), conditional oper: if(left | right)
5681       symbol *tlbl = newiTempLabel(NULL);
5682       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5683       pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5684       
5685       
5686       if(size)
5687         pic14_emitcode(";XXX setb","c");
5688       while(sizer--){
5689         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5690         pic14_emitcode(";XXX orl","a,%s",
5691           aopGet(AOP(left),offset,FALSE,FALSE));
5692         pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5693         offset++;
5694       }
5695       if(size){
5696         CLRC;
5697         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5698         pic14_outBitC(result);
5699       } else if(ifx)
5700         jmpTrueOrFalse(ifx, tlbl);
5701     } else for(;(size--);offset++){
5702       // normal case
5703       // result = left & right
5704       if(AOP_TYPE(right) == AOP_LIT){
5705         int t = (lit >> (offset*8)) & 0x0FFL;
5706         switch(t) { 
5707         case 0x00:
5708           if (AOP_TYPE(left) != AOP_ACC) {
5709             emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5710           }
5711           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5712           
5713           break;
5714         default:
5715           if (AOP_TYPE(left) == AOP_ACC) {
5716             emitpcode(POC_IORLW,  popGetLit(t));
5717           } else {
5718             emitpcode(POC_MOVLW,  popGetLit(t));
5719             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5720           }
5721           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
5722         }
5723         continue;
5724       }
5725       
5726       // faster than result <- left, anl result,right
5727       // and better if result is SFR
5728       if (AOP_TYPE(left) == AOP_ACC) {
5729         emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5730         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5731       } else {
5732         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5733         emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5734         
5735         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5736         pic14_emitcode("iorwf","%s,w",
5737           aopGet(AOP(left),offset,FALSE,FALSE));
5738       }
5739       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5740       pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5741     }
5742   }
5743   
5744 release :
5745   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5746   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5747   freeAsmop(result,NULL,ic,TRUE);     
5748 }
5749
5750 /*-----------------------------------------------------------------*/
5751 /* genXor - code for xclusive or                                   */
5752 /*-----------------------------------------------------------------*/
5753 static void genXor (iCode *ic, iCode *ifx)
5754 {
5755   operand *left, *right, *result;
5756   int size, offset=0;
5757   unsigned long lit = 0L;
5758   
5759   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5760   
5761   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5762   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5763   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5764   
5765   /* if left is a literal & right is not ||
5766   if left needs acc & right does not */
5767   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5768     (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5769     operand *tmp = right ;
5770     right = left;
5771     left = tmp;
5772   }
5773   
5774   /* if result = right then exchange them */
5775   if(pic14_sameRegs(AOP(result),AOP(right))){
5776     operand *tmp = right ;
5777     right = left;
5778     left = tmp;
5779   }
5780   
5781   /* if right is bit then exchange them */
5782   if (AOP_TYPE(right) == AOP_CRY &&
5783     AOP_TYPE(left) != AOP_CRY){
5784     operand *tmp = right ;
5785     right = left;
5786     left = tmp;
5787   }
5788   if(AOP_TYPE(right) == AOP_LIT)
5789     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5790   
5791   size = AOP_SIZE(result);
5792   
5793   // if(bit ^ yy)
5794   // xx = bit ^ yy;
5795   if (AOP_TYPE(left) == AOP_CRY){
5796     if(AOP_TYPE(right) == AOP_LIT){
5797       // c = bit & literal;
5798       if(lit>>1){
5799         // lit>>1  != 0 => result = 1
5800         if(AOP_TYPE(result) == AOP_CRY){
5801           if(size)
5802           {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5803           pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5804           else if(ifx)
5805             continueIfTrue(ifx);
5806           goto release;
5807         }
5808         pic14_emitcode("setb","c");
5809       } else{
5810         // lit == (0 or 1)
5811         if(lit == 0){
5812           // lit == 0, result = left
5813           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5814             goto release;
5815           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5816         } else{
5817           // lit == 1, result = not(left)
5818           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5819             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5820             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5821             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5822             goto release;
5823           } else {
5824             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5825             pic14_emitcode("cpl","c");
5826           }
5827         }
5828       }
5829       
5830     } else {
5831       // right != literal
5832       symbol *tlbl = newiTempLabel(NULL);
5833       if (AOP_TYPE(right) == AOP_CRY){
5834         // c = bit ^ bit;
5835         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5836       }
5837       else{
5838         int sizer = AOP_SIZE(right);
5839         // c = bit ^ val
5840         // if val>>1 != 0, result = 1
5841         pic14_emitcode("setb","c");
5842         while(sizer){
5843           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5844           if(sizer == 1)
5845             // test the msb of the lsb
5846             pic14_emitcode("anl","a,#0xfe");
5847           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5848           sizer--;
5849         }
5850         // val = (0,1)
5851         pic14_emitcode("rrc","a");
5852       }
5853       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5854       pic14_emitcode("cpl","c");
5855       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5856     }
5857     // bit = c
5858     // val = c
5859     if(size)
5860       pic14_outBitC(result);
5861     // if(bit | ...)
5862     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5863       genIfxJump(ifx, "c");           
5864     goto release ;
5865   }
5866   
5867   if(pic14_sameRegs(AOP(result),AOP(left))){
5868     /* if left is same as result */
5869     for(;size--; offset++) {
5870       if(AOP_TYPE(right) == AOP_LIT){
5871         int t  = (lit >> (offset*8)) & 0x0FFL;
5872         if(t == 0x00L)
5873           continue;
5874         else
5875           if (IS_AOP_PREG(left)) {
5876             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5877             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5878             aopPut(AOP(result),"a",offset);
5879           } else {
5880             emitpcode(POC_MOVLW, popGetLit(t));
5881             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5882             pic14_emitcode("xrl","%s,%s",
5883               aopGet(AOP(left),offset,FALSE,TRUE),
5884               aopGet(AOP(right),offset,FALSE,FALSE));
5885           }
5886       } else {
5887         if (AOP_TYPE(left) == AOP_ACC)
5888           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5889         else {
5890           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5891           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5892           /*
5893           if (IS_AOP_PREG(left)) {
5894           pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5895           aopPut(AOP(result),"a",offset);
5896           } else
5897           pic14_emitcode("xrl","%s,a",
5898           aopGet(AOP(left),offset,FALSE,TRUE));
5899           */
5900         }
5901       }
5902     }
5903   } else {
5904     // left & result in different registers
5905     if(AOP_TYPE(result) == AOP_CRY){
5906       // result = bit
5907       // if(size), result in bit
5908       // if(!size && ifx), conditional oper: if(left ^ right)
5909       symbol *tlbl = newiTempLabel(NULL);
5910       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5911       if(size)
5912         pic14_emitcode("setb","c");
5913       while(sizer--){
5914         if((AOP_TYPE(right) == AOP_LIT) &&
5915           (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5916           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5917         } else {
5918           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5919           pic14_emitcode("xrl","a,%s",
5920             aopGet(AOP(left),offset,FALSE,FALSE));
5921         }
5922         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5923         offset++;
5924       }
5925       if(size){
5926         CLRC;
5927         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5928         pic14_outBitC(result);
5929       } else if(ifx)
5930         jmpTrueOrFalse(ifx, tlbl);
5931     } else for(;(size--);offset++){
5932       // normal case
5933       // result = left & right
5934       if(AOP_TYPE(right) == AOP_LIT){
5935         int t = (lit >> (offset*8)) & 0x0FFL;
5936         switch(t) { 
5937         case 0x00:
5938           if (AOP_TYPE(left) != AOP_ACC) {
5939             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5940           }
5941           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5942           pic14_emitcode("movf","%s,w",
5943             aopGet(AOP(left),offset,FALSE,FALSE));
5944           pic14_emitcode("movwf","%s",
5945             aopGet(AOP(result),offset,FALSE,FALSE));
5946           break;
5947         case 0xff:
5948           if (AOP_TYPE(left) == AOP_ACC) {
5949             emitpcode(POC_XORLW, popGetLit(t));
5950           } else {
5951             emitpcode(POC_COMFW,popGet(AOP(left),offset));
5952           }
5953           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5954           break;
5955         default:
5956           if (AOP_TYPE(left) == AOP_ACC) {
5957             emitpcode(POC_XORLW, popGetLit(t));
5958           } else {
5959             emitpcode(POC_MOVLW, popGetLit(t));
5960             emitpcode(POC_XORFW,popGet(AOP(left),offset));
5961           }
5962           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5963           pic14_emitcode("movlw","0x%x",t);
5964           pic14_emitcode("xorwf","%s,w",
5965             aopGet(AOP(left),offset,FALSE,FALSE));
5966           pic14_emitcode("movwf","%s",
5967             aopGet(AOP(result),offset,FALSE,FALSE));
5968           
5969         }
5970         continue;
5971       }
5972       
5973       // faster than result <- left, anl result,right
5974       // and better if result is SFR
5975       if (AOP_TYPE(left) == AOP_ACC) {
5976         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5977         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5978       } else {
5979         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5980         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5981         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5982         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5983       }
5984       if ( AOP_TYPE(result) != AOP_ACC){
5985         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5986         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5987       }
5988     }
5989   }
5990   
5991 release :
5992   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5993   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5994   freeAsmop(result,NULL,ic,TRUE);     
5995 }
5996
5997 /*-----------------------------------------------------------------*/
5998 /* genInline - write the inline code out                           */
5999 /*-----------------------------------------------------------------*/
6000 static void genInline (iCode *ic)
6001 {
6002   char *buffer, *bp, *bp1;
6003   
6004   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6005   
6006   _G.inLine += (!options.asmpeep);
6007   
6008   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6009   strcpy(buffer,IC_INLINE(ic));
6010   
6011   /* emit each line as a code */
6012   while (*bp) {
6013     if (*bp == '\n') {
6014       *bp++ = '\0';
6015       
6016       if(*bp1)
6017         addpCode2pBlock(pb,AssembleLine(bp1));
6018       bp1 = bp;
6019     } else {
6020       if (*bp == ':') {
6021         bp++;
6022         *bp = '\0';
6023         bp++;
6024         pic14_emitcode(bp1,"");
6025         bp1 = bp;
6026       } else
6027         bp++;
6028     }
6029   }
6030   if ((bp1 != bp) && *bp1)
6031     addpCode2pBlock(pb,AssembleLine(bp1));
6032   
6033   Safe_free(buffer);
6034   
6035   _G.inLine -= (!options.asmpeep);
6036 }
6037
6038 /*-----------------------------------------------------------------*/
6039 /* genRRC - rotate right with carry                                */
6040 /*-----------------------------------------------------------------*/
6041 static void genRRC (iCode *ic)
6042 {
6043   operand *left , *result ;
6044   int size, offset = 0, same;
6045   
6046   /* rotate right with carry */
6047   left = IC_LEFT(ic);
6048   result=IC_RESULT(ic);
6049   aopOp (left,ic,FALSE);
6050   aopOp (result,ic,FALSE);
6051   
6052   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6053   
6054   same = pic14_sameRegs(AOP(result),AOP(left));
6055   
6056   size = AOP_SIZE(result);    
6057   
6058   /* get the lsb and put it into the carry */
6059   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6060   
6061   offset = 0 ;
6062   
6063   while(size--) {
6064     
6065     if(same) {
6066       emitpcode(POC_RRF, popGet(AOP(left),offset));
6067     } else {
6068       emitpcode(POC_RRFW, popGet(AOP(left),offset));
6069       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6070     }
6071     
6072     offset++;
6073   }
6074   
6075   freeAsmop(left,NULL,ic,TRUE);
6076   freeAsmop(result,NULL,ic,TRUE);
6077 }
6078
6079 /*-----------------------------------------------------------------*/
6080 /* genRLC - generate code for rotate left with carry               */
6081 /*-----------------------------------------------------------------*/
6082 static void genRLC (iCode *ic)
6083 {    
6084   operand *left , *result ;
6085   int size, offset = 0;
6086   int same;
6087   
6088   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6089   /* rotate right with carry */
6090   left = IC_LEFT(ic);
6091   result=IC_RESULT(ic);
6092   aopOp (left,ic,FALSE);
6093   aopOp (result,ic,FALSE);
6094   
6095   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6096   
6097   same = pic14_sameRegs(AOP(result),AOP(left));
6098   
6099   /* move it to the result */
6100   size = AOP_SIZE(result);    
6101   
6102   /* get the msb and put it into the carry */
6103   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6104   
6105   offset = 0 ;
6106   
6107   while(size--) {
6108     
6109     if(same) {
6110       emitpcode(POC_RLF, popGet(AOP(left),offset));
6111     } else {
6112       emitpcode(POC_RLFW, popGet(AOP(left),offset));
6113       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6114     }
6115     
6116     offset++;
6117   }
6118   
6119   
6120   freeAsmop(left,NULL,ic,TRUE);
6121   freeAsmop(result,NULL,ic,TRUE);
6122 }
6123
6124 /*-----------------------------------------------------------------*/
6125 /* genGetHbit - generates code get highest order bit               */
6126 /*-----------------------------------------------------------------*/
6127 static void genGetHbit (iCode *ic)
6128 {
6129   operand *left, *result;
6130   left = IC_LEFT(ic);
6131   result=IC_RESULT(ic);
6132   aopOp (left,ic,FALSE);
6133   aopOp (result,ic,FALSE);
6134   
6135   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6136   /* get the highest order byte into a */
6137   MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6138   if(AOP_TYPE(result) == AOP_CRY){
6139     pic14_emitcode("rlc","a");
6140     pic14_outBitC(result);
6141   }
6142   else{
6143     pic14_emitcode("rl","a");
6144     pic14_emitcode("anl","a,#0x01");
6145     pic14_outAcc(result);
6146   }
6147   
6148   
6149   freeAsmop(left,NULL,ic,TRUE);
6150   freeAsmop(result,NULL,ic,TRUE);
6151 }
6152
6153 /*-----------------------------------------------------------------*/
6154 /* AccRol - rotate left accumulator by known count                 */
6155 /*-----------------------------------------------------------------*/
6156 static void AccRol (int shCount)
6157 {
6158   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6159   shCount &= 0x0007;              // shCount : 0..7
6160   switch(shCount){
6161   case 0 :
6162     break;
6163   case 1 :
6164     pic14_emitcode("rl","a");
6165     break;
6166   case 2 :
6167     pic14_emitcode("rl","a");
6168     pic14_emitcode("rl","a");
6169     break;
6170   case 3 :
6171     pic14_emitcode("swap","a");
6172     pic14_emitcode("rr","a");
6173     break;
6174   case 4 :
6175     pic14_emitcode("swap","a");
6176     break;
6177   case 5 :
6178     pic14_emitcode("swap","a");
6179     pic14_emitcode("rl","a");
6180     break;
6181   case 6 :
6182     pic14_emitcode("rr","a");
6183     pic14_emitcode("rr","a");
6184     break;
6185   case 7 :
6186     pic14_emitcode("rr","a");
6187     break;
6188   }
6189 }
6190
6191 /*-----------------------------------------------------------------*/
6192 /* AccLsh - left shift accumulator by known count                  */
6193 /*-----------------------------------------------------------------*/
6194 static void AccLsh (int shCount)
6195 {
6196   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6197   if(shCount != 0){
6198     if(shCount == 1)
6199       pic14_emitcode("add","a,acc");
6200     else 
6201       if(shCount == 2) {
6202         pic14_emitcode("add","a,acc");
6203         pic14_emitcode("add","a,acc");
6204       } else {
6205         /* rotate left accumulator */
6206         AccRol(shCount);
6207         /* and kill the lower order bits */
6208         pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6209       }
6210   }
6211 }
6212
6213 /*-----------------------------------------------------------------*/
6214 /* AccRsh - right shift accumulator by known count                 */
6215 /*-----------------------------------------------------------------*/
6216 static void AccRsh (int shCount)
6217 {
6218   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6219   if(shCount != 0){
6220     if(shCount == 1){
6221       CLRC;
6222       pic14_emitcode("rrc","a");
6223     } else {
6224       /* rotate right accumulator */
6225       AccRol(8 - shCount);
6226       /* and kill the higher order bits */
6227       pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6228     }
6229   }
6230 }
6231
6232 #if 0
6233 /*-----------------------------------------------------------------*/
6234 /* AccSRsh - signed right shift accumulator by known count                 */
6235 /*-----------------------------------------------------------------*/
6236 static void AccSRsh (int shCount)
6237 {
6238   symbol *tlbl ;
6239   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6240   if(shCount != 0){
6241     if(shCount == 1){
6242       pic14_emitcode("mov","c,acc.7");
6243       pic14_emitcode("rrc","a");
6244     } else if(shCount == 2){
6245       pic14_emitcode("mov","c,acc.7");
6246       pic14_emitcode("rrc","a");
6247       pic14_emitcode("mov","c,acc.7");
6248       pic14_emitcode("rrc","a");
6249     } else {
6250       tlbl = newiTempLabel(NULL);
6251       /* rotate right accumulator */
6252       AccRol(8 - shCount);
6253       /* and kill the higher order bits */
6254       pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6255       pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6256       pic14_emitcode("orl","a,#0x%02x",
6257         (unsigned char)~SRMask[shCount]);
6258       pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6259     }
6260   }
6261 }
6262 #endif
6263 /*-----------------------------------------------------------------*/
6264 /* shiftR1Left2Result - shift right one byte from left to result   */
6265 /*-----------------------------------------------------------------*/
6266 static void shiftR1Left2ResultSigned (operand *left, int offl,
6267                     operand *result, int offr,
6268                     int shCount)
6269 {
6270   int same;
6271   
6272   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6273   
6274   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6275   
6276   switch(shCount) {
6277   case 1:
6278     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6279     if(same) 
6280       emitpcode(POC_RRF, popGet(AOP(result),offr));
6281     else {
6282       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6283       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6284     }
6285     
6286     break;
6287   case 2:
6288     
6289     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6290     if(same) 
6291       emitpcode(POC_RRF, popGet(AOP(result),offr));
6292     else {
6293       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6294       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6295     }
6296     emitpcode(POC_RLFW, popGet(AOP(result),offr));
6297     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6298     
6299     break;
6300     
6301   case 3:
6302     if(same)
6303       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6304     else {
6305       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6306       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6307     }
6308     
6309     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6310     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6311     emitpcode(POC_ANDLW, popGetLit(0x1f));
6312     
6313     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6314     emitpcode(POC_IORLW, popGetLit(0xe0));
6315     
6316     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6317     break;
6318     
6319   case 4:
6320     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6321     emitpcode(POC_ANDLW,  popGetLit(0x0f));
6322     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6323     emitpcode(POC_IORLW,  popGetLit(0xf0));
6324     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6325     break;
6326   case 5:
6327     if(same) {
6328       emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6329     } else {
6330       emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6331       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6332     }
6333     emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6334     emitpcode(POC_ANDLW,  popGetLit(0x07));
6335     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6336     emitpcode(POC_IORLW,  popGetLit(0xf8));
6337     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6338     break;
6339     
6340   case 6:
6341     if(same) {
6342       emitpcode(POC_MOVLW, popGetLit(0x00));
6343       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6344       emitpcode(POC_MOVLW, popGetLit(0xfe));
6345       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6346       emitpcode(POC_IORLW, popGetLit(0x01));
6347       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6348     } else {
6349       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6350       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6351       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6352       emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6353       emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6354     }
6355     break;
6356     
6357   case 7:
6358     if(same) {
6359       emitpcode(POC_MOVLW, popGetLit(0x00));
6360       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6361       emitpcode(POC_MOVLW, popGetLit(0xff));
6362       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6363     } else {
6364       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6365       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6366       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6367     }
6368     
6369   default:
6370     break;
6371   }
6372 }
6373
6374 /*-----------------------------------------------------------------*/
6375 /* shiftR1Left2Result - shift right one byte from left to result   */
6376 /*-----------------------------------------------------------------*/
6377 static void shiftR1Left2Result (operand *left, int offl,
6378                 operand *result, int offr,
6379                 int shCount, int sign)
6380 {
6381   int same;
6382   
6383   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6384   
6385   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6386   
6387   /* Copy the msb into the carry if signed. */
6388   if(sign) {
6389     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6390     return;
6391   }
6392   
6393   
6394   
6395   switch(shCount) {
6396   case 1:
6397     emitCLRC;
6398     if(same) 
6399       emitpcode(POC_RRF, popGet(AOP(result),offr));
6400     else {
6401       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6402       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6403     }
6404     break;
6405   case 2:
6406     emitCLRC;
6407     if(same) {
6408       emitpcode(POC_RRF, popGet(AOP(result),offr));
6409     } else {
6410       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6411       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6412     }
6413     emitCLRC;
6414     emitpcode(POC_RRF, popGet(AOP(result),offr));
6415     
6416     break;
6417   case 3:
6418     if(same)
6419       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6420     else {
6421       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6422       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6423     }
6424     
6425     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6426     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6427     emitpcode(POC_ANDLW, popGetLit(0x1f));
6428     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6429     break;
6430     
6431   case 4:
6432     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6433     emitpcode(POC_ANDLW, popGetLit(0x0f));
6434     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6435     break;
6436     
6437   case 5:
6438     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6439     emitpcode(POC_ANDLW, popGetLit(0x0f));
6440     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6441     emitCLRC;
6442     emitpcode(POC_RRF, popGet(AOP(result),offr));
6443     
6444     break;
6445   case 6:
6446     
6447     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6448     emitpcode(POC_ANDLW, popGetLit(0x80));
6449     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6450     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6451     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6452     break;
6453     
6454   case 7:
6455     
6456     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6457     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6458     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6459     
6460     break;
6461     
6462   default:
6463     break;
6464   }
6465 }
6466
6467 /*-----------------------------------------------------------------*/
6468 /* shiftL1Left2Result - shift left one byte from left to result    */
6469 /*-----------------------------------------------------------------*/
6470 static void shiftL1Left2Result (operand *left, int offl,
6471                 operand *result, int offr, int shCount)
6472 {
6473   int same;
6474   
6475   //    char *l;
6476   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6477   
6478   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6479   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6480   //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6481   //    MOVA(l);
6482   /* shift left accumulator */
6483   //AccLsh(shCount); // don't comment out just yet...
6484   //    aopPut(AOP(result),"a",offr);
6485   
6486   switch(shCount) {
6487   case 1:
6488     /* Shift left 1 bit position */
6489     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6490     if(same) {
6491       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6492     } else {
6493       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6494       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6495     }
6496     break;
6497   case 2:
6498     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6499     emitpcode(POC_ANDLW,popGetLit(0x7e));
6500     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6501     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6502     break;
6503   case 3:
6504     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6505     emitpcode(POC_ANDLW,popGetLit(0x3e));
6506     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6507     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6508     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6509     break;
6510   case 4:
6511     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6512     emitpcode(POC_ANDLW, popGetLit(0xf0));
6513     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6514     break;
6515   case 5:
6516     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6517     emitpcode(POC_ANDLW, popGetLit(0xf0));
6518     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6519     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6520     break;
6521   case 6:
6522     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6523     emitpcode(POC_ANDLW, popGetLit(0x30));
6524     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6525     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6526     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6527     break;
6528   case 7:
6529     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6530     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6531     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6532     break;
6533     
6534   default:
6535     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6536   }
6537   
6538 }
6539
6540 /*-----------------------------------------------------------------*/
6541 /* movLeft2Result - move byte from left to result                  */
6542 /*-----------------------------------------------------------------*/
6543 static void movLeft2Result (operand *left, int offl,
6544               operand *result, int offr)
6545 {
6546   char *l;
6547   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6548   if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6549     l = aopGet(AOP(left),offl,FALSE,FALSE);
6550     
6551     if (*l == '@' && (IS_AOP_PREG(result))) {
6552       pic14_emitcode("mov","a,%s",l);
6553       aopPut(AOP(result),"a",offr);
6554     } else {
6555       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6556       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6557     }
6558   }
6559 }
6560
6561 /*-----------------------------------------------------------------*/
6562 /* shiftL2Left2Result - shift left two bytes from left to result   */
6563 /*-----------------------------------------------------------------*/
6564 static void shiftL2Left2Result (operand *left, int offl,
6565                 operand *result, int offr, int shCount)
6566 {
6567   
6568   
6569   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6570   
6571   if(pic14_sameRegs(AOP(result), AOP(left))) {
6572     switch(shCount) {
6573     case 0:
6574       break;
6575     case 1:
6576     case 2:
6577     case 3:
6578       
6579       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6580       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6581       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6582       
6583       while(--shCount) {
6584         emitCLRC;
6585         emitpcode(POC_RLF, popGet(AOP(result),offr));
6586         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6587       }
6588       
6589       break;
6590     case 4:
6591     case 5:
6592       emitpcode(POC_MOVLW, popGetLit(0x0f));
6593       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6594       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6595       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6596       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6597       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6598       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6599       if(shCount >=5) {
6600         emitpcode(POC_RLF, popGet(AOP(result),offr));
6601         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6602       }
6603       break;
6604     case 6:
6605       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6606       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6607       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6608       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6609       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6610       emitpcode(POC_ANDLW,popGetLit(0xc0));
6611       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6612       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6613       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6614       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6615       break;
6616     case 7:
6617       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6618       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6619       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6620       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6621       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6622     }
6623     
6624   } else {
6625     switch(shCount) {
6626     case 0:
6627       break;
6628     case 1:
6629     case 2:
6630     case 3:
6631     /* note, use a mov/add for the shift since the mov has a
6632       chance of getting optimized out */
6633       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6634       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6635       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6636       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6637       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6638       
6639       while(--shCount) {
6640         emitCLRC;
6641         emitpcode(POC_RLF, popGet(AOP(result),offr));
6642         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6643       }
6644       break;
6645       
6646     case 4:
6647     case 5:
6648       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6649       emitpcode(POC_ANDLW, popGetLit(0xF0));
6650       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6651       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6652       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6653       emitpcode(POC_ANDLW, popGetLit(0xF0));
6654       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6655       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6656       
6657       
6658       if(shCount == 5) {
6659         emitpcode(POC_RLF, popGet(AOP(result),offr));
6660         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6661       }
6662       break;
6663     case 6:
6664       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6665       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6666       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6667       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6668       
6669       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6670       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6671       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6672       emitpcode(POC_ANDLW,popGetLit(0xc0));
6673       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6674       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6675       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6676       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6677       break;
6678     case 7:
6679       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6680       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6681       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6682       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6683       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6684     }
6685   }
6686   
6687 }
6688 /*-----------------------------------------------------------------*/
6689 /* shiftR2Left2Result - shift right two bytes from left to result  */
6690 /*-----------------------------------------------------------------*/
6691 static void shiftR2Left2Result (operand *left, int offl,
6692                 operand *result, int offr,
6693                 int shCount, int sign)
6694 {
6695   int same=0;
6696   
6697   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6698   same = pic14_sameRegs(AOP(result), AOP(left));
6699   
6700   if(same && ((offl + MSB16) == offr)){
6701     same=1;
6702     /* don't crash result[offr] */
6703     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6704     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6705   }
6706   /* else {
6707   movLeft2Result(left,offl, result, offr);
6708   MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6709   }
6710   */
6711   /* a:x >> shCount (x = lsb(result))*/
6712   /*
6713   if(sign)
6714   AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6715   else {
6716   AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6717   */
6718   switch(shCount) {
6719   case 0:
6720     break;
6721   case 1:
6722   case 2:
6723   case 3:
6724     if(sign)
6725       emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6726     else
6727       emitCLRC;
6728     
6729     if(same) {
6730       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6731       emitpcode(POC_RRF,popGet(AOP(result),offr));
6732     } else {
6733       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6734       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6735       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6736       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6737     }
6738     
6739     while(--shCount) {
6740       if(sign)
6741         emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6742       else
6743         emitCLRC;
6744       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6745       emitpcode(POC_RRF,popGet(AOP(result),offr));
6746     }
6747     break;
6748   case 4:
6749   case 5:
6750     if(same) {
6751       
6752       emitpcode(POC_MOVLW, popGetLit(0xf0));
6753       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6754       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6755       
6756       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6757       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6758       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6759       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6760     } else {
6761       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6762       emitpcode(POC_ANDLW, popGetLit(0x0f));
6763       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6764       
6765       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6766       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6767       emitpcode(POC_ANDLW, popGetLit(0xf0));
6768       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6769       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6770     }
6771     
6772     if(shCount >=5) {
6773       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6774       emitpcode(POC_RRF, popGet(AOP(result),offr));
6775     }
6776     
6777     if(sign) {
6778       emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6779       emitpcode(POC_BTFSC, 
6780         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6781       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6782     }
6783     
6784     break;
6785     
6786   case 6:
6787     if(same) {
6788       
6789       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6790       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6791       
6792       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6793       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6794       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6795       emitpcode(POC_ANDLW,popGetLit(0x03));
6796       if(sign) {
6797         emitpcode(POC_BTFSC, 
6798           newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6799         emitpcode(POC_IORLW,popGetLit(0xfc));
6800       }
6801       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6802       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6803       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6804       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6805     } else {
6806       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6807       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6808       emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6809       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6810       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6811       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6812       emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6813       emitpcode(POC_ANDLW,popGetLit(0x03));
6814       if(sign) {
6815         emitpcode(POC_BTFSC, 
6816           newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6817         emitpcode(POC_IORLW,popGetLit(0xfc));
6818       }
6819       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6820       //emitpcode(POC_RLF,  popGet(AOP(result),offr));
6821       
6822       
6823     }
6824     
6825     break;
6826   case 7:
6827     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6828     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6829     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6830     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6831     if(sign) {
6832       emitSKPNC;
6833       emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6834     } else 
6835       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6836   }
6837 }
6838
6839
6840 /*-----------------------------------------------------------------*/
6841 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6842 /*-----------------------------------------------------------------*/
6843 static void shiftLLeftOrResult (operand *left, int offl,
6844                 operand *result, int offr, int shCount)
6845 {
6846   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6847   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6848   /* shift left accumulator */
6849   AccLsh(shCount);
6850   /* or with result */
6851   pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6852   /* back to result */
6853   aopPut(AOP(result),"a",offr);
6854 }
6855
6856 /*-----------------------------------------------------------------*/
6857 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6858 /*-----------------------------------------------------------------*/
6859 static void shiftRLeftOrResult (operand *left, int offl,
6860                 operand *result, int offr, int shCount)
6861 {
6862   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6863   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6864   /* shift right accumulator */
6865   AccRsh(shCount);
6866   /* or with result */
6867   pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6868   /* back to result */
6869   aopPut(AOP(result),"a",offr);
6870 }
6871
6872 /*-----------------------------------------------------------------*/
6873 /* genlshOne - left shift a one byte quantity by known count       */
6874 /*-----------------------------------------------------------------*/
6875 static void genlshOne (operand *result, operand *left, int shCount)
6876 {       
6877   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6878   shiftL1Left2Result(left, LSB, result, LSB, shCount);
6879 }
6880
6881 /*-----------------------------------------------------------------*/
6882 /* genlshTwo - left shift two bytes by known amount != 0           */
6883 /*-----------------------------------------------------------------*/
6884 static void genlshTwo (operand *result,operand *left, int shCount)
6885 {
6886   int size;
6887   
6888   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6889   size = pic14_getDataSize(result);
6890   
6891   /* if shCount >= 8 */
6892   if (shCount >= 8) {
6893     shCount -= 8 ;
6894     
6895     if (size > 1){
6896       if (shCount)
6897         shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6898       else 
6899         movLeft2Result(left, LSB, result, MSB16);
6900     }
6901     emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6902   }
6903   
6904   /*  1 <= shCount <= 7 */
6905   else {  
6906     if(size == 1)
6907       shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6908     else 
6909       shiftL2Left2Result(left, LSB, result, LSB, shCount);
6910   }
6911 }
6912
6913 /*-----------------------------------------------------------------*/
6914 /* shiftLLong - shift left one long from left to result            */
6915 /* offl = LSB or MSB16                                             */
6916 /*-----------------------------------------------------------------*/
6917 static void shiftLLong (operand *left, operand *result, int offr )
6918 {
6919   char *l;
6920   int size = AOP_SIZE(result);
6921   
6922   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6923   if(size >= LSB+offr){
6924     l = aopGet(AOP(left),LSB,FALSE,FALSE);
6925     MOVA(l);
6926     pic14_emitcode("add","a,acc");
6927     if (pic14_sameRegs(AOP(left),AOP(result)) && 
6928       size >= MSB16+offr && offr != LSB )
6929       pic14_emitcode("xch","a,%s",
6930       aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6931     else      
6932       aopPut(AOP(result),"a",LSB+offr);
6933   }
6934   
6935   if(size >= MSB16+offr){
6936     if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6937       l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6938       MOVA(l);
6939     }
6940     pic14_emitcode("rlc","a");
6941     if (pic14_sameRegs(AOP(left),AOP(result)) && 
6942       size >= MSB24+offr && offr != LSB)
6943       pic14_emitcode("xch","a,%s",
6944       aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6945     else      
6946       aopPut(AOP(result),"a",MSB16+offr);
6947   }
6948   
6949   if(size >= MSB24+offr){
6950     if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6951       l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6952       MOVA(l);
6953     }
6954     pic14_emitcode("rlc","a");
6955     if (pic14_sameRegs(AOP(left),AOP(result)) && 
6956       size >= MSB32+offr && offr != LSB )
6957       pic14_emitcode("xch","a,%s",
6958       aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6959     else      
6960       aopPut(AOP(result),"a",MSB24+offr);
6961   }
6962   
6963   if(size > MSB32+offr){
6964     if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6965       l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6966       MOVA(l);  
6967     }
6968     pic14_emitcode("rlc","a");
6969     aopPut(AOP(result),"a",MSB32+offr);
6970   }
6971   if(offr != LSB)
6972     aopPut(AOP(result),zero,LSB);       
6973 }
6974
6975 /*-----------------------------------------------------------------*/
6976 /* genlshFour - shift four byte by a known amount != 0             */
6977 /*-----------------------------------------------------------------*/
6978 static void genlshFour (operand *result, operand *left, int shCount)
6979 {
6980   int size;
6981   
6982   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6983   size = AOP_SIZE(result);
6984   
6985   /* if shifting more that 3 bytes */
6986   if (shCount >= 24 ) {
6987     shCount -= 24;
6988     if (shCount)
6989     /* lowest order of left goes to the highest
6990     order of the destination */
6991     shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6992     else
6993       movLeft2Result(left, LSB, result, MSB32);
6994     aopPut(AOP(result),zero,LSB);
6995     aopPut(AOP(result),zero,MSB16);
6996     aopPut(AOP(result),zero,MSB32);
6997     return;
6998   }
6999   
7000   /* more than two bytes */
7001   else if ( shCount >= 16 ) {
7002     /* lower order two bytes goes to higher order two bytes */
7003     shCount -= 16;
7004     /* if some more remaining */
7005     if (shCount)
7006       shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7007     else {
7008       movLeft2Result(left, MSB16, result, MSB32);
7009       movLeft2Result(left, LSB, result, MSB24);
7010     }
7011     aopPut(AOP(result),zero,MSB16);
7012     aopPut(AOP(result),zero,LSB);
7013     return;
7014   }    
7015   
7016   /* if more than 1 byte */
7017   else if ( shCount >= 8 ) {
7018     /* lower order three bytes goes to higher order  three bytes */
7019     shCount -= 8;
7020     if(size == 2){
7021       if(shCount)
7022         shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7023       else
7024         movLeft2Result(left, LSB, result, MSB16);
7025     }
7026     else{   /* size = 4 */
7027       if(shCount == 0){
7028         movLeft2Result(left, MSB24, result, MSB32);
7029         movLeft2Result(left, MSB16, result, MSB24);
7030         movLeft2Result(left, LSB, result, MSB16);
7031         aopPut(AOP(result),zero,LSB);
7032       }
7033       else if(shCount == 1)
7034         shiftLLong(left, result, MSB16);
7035       else{
7036         shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7037         shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7038         shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7039         aopPut(AOP(result),zero,LSB);
7040       }
7041     }
7042   }
7043   
7044   /* 1 <= shCount <= 7 */
7045   else if(shCount <= 2){
7046     shiftLLong(left, result, LSB);
7047     if(shCount == 2)
7048       shiftLLong(result, result, LSB);
7049   }
7050   /* 3 <= shCount <= 7, optimize */
7051   else{
7052     shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7053     shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7054     shiftL2Left2Result(left, LSB, result, LSB, shCount);
7055   }
7056 }
7057
7058 /*-----------------------------------------------------------------*/
7059 /* genLeftShiftLiteral - left shifting by known count              */
7060 /*-----------------------------------------------------------------*/
7061 static void genLeftShiftLiteral (operand *left,
7062                  operand *right,
7063                  operand *result,
7064                  iCode *ic)
7065 {    
7066   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7067   int size;
7068   
7069   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7070   freeAsmop(right,NULL,ic,TRUE);
7071   
7072   aopOp(left,ic,FALSE);
7073   aopOp(result,ic,FALSE);
7074   
7075   size = getSize(operandType(result));
7076   
7077 #if VIEW_SIZE
7078   pic14_emitcode("; shift left ","result %d, left %d",size,
7079     AOP_SIZE(left));
7080 #endif
7081   
7082   /* I suppose that the left size >= result size */
7083   if(shCount == 0){
7084     while(size--){
7085       movLeft2Result(left, size, result, size);
7086     }
7087   }
7088   
7089   else if(shCount >= (size * 8))
7090     while(size--)
7091       aopPut(AOP(result),zero,size);
7092     else{
7093       switch (size) {
7094       case 1:
7095         genlshOne (result,left,shCount);
7096         break;
7097         
7098       case 2:
7099       case 3:
7100         genlshTwo (result,left,shCount);
7101         break;
7102         
7103       case 4:
7104         genlshFour (result,left,shCount);
7105         break;
7106       }
7107     }
7108     freeAsmop(left,NULL,ic,TRUE);
7109     freeAsmop(result,NULL,ic,TRUE);
7110 }
7111
7112 /*-----------------------------------------------------------------*
7113 * genMultiAsm - repeat assembly instruction for size of register.
7114 * if endian == 1, then the high byte (i.e base address + size of 
7115 * register) is used first else the low byte is used first;
7116 *-----------------------------------------------------------------*/
7117 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7118 {
7119   
7120   int offset = 0;
7121   
7122   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7123   
7124   if(!reg)
7125     return;
7126   
7127   if(!endian) {
7128     endian = 1;
7129   } else {
7130     endian = -1;
7131     offset = size-1;
7132   }
7133   
7134   while(size--) {
7135     emitpcode(poc,    popGet(AOP(reg),offset));
7136     offset += endian;
7137   }
7138   
7139 }
7140 /*-----------------------------------------------------------------*/
7141 /* genLeftShift - generates code for left shifting                 */
7142 /*-----------------------------------------------------------------*/
7143 static void genLeftShift (iCode *ic)
7144 {
7145   operand *left,*right, *result;
7146   int size, offset;
7147   char *l;
7148   symbol *tlbl , *tlbl1;
7149   pCodeOp *pctemp;
7150   
7151   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7152   
7153   right = IC_RIGHT(ic);
7154   left  = IC_LEFT(ic);
7155   result = IC_RESULT(ic);
7156   
7157   aopOp(right,ic,FALSE);
7158   
7159   /* if the shift count is known then do it 
7160   as efficiently as possible */
7161   if (AOP_TYPE(right) == AOP_LIT) {
7162     genLeftShiftLiteral (left,right,result,ic);
7163     return ;
7164   }
7165   
7166   /* shift count is unknown then we have to form 
7167   a loop get the loop count in B : Note: we take
7168   only the lower order byte since shifting
7169   more that 32 bits make no sense anyway, ( the
7170   largest size of an object can be only 32 bits ) */  
7171   
7172   
7173   aopOp(left,ic,FALSE);
7174   aopOp(result,ic,FALSE);
7175   
7176   /* now move the left to the result if they are not the
7177   same */
7178   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7179     AOP_SIZE(result) > 1) {
7180     
7181     size = AOP_SIZE(result);
7182     offset=0;
7183     while (size--) {
7184       l = aopGet(AOP(left),offset,FALSE,TRUE);
7185       if (*l == '@' && (IS_AOP_PREG(result))) {
7186         
7187         pic14_emitcode("mov","a,%s",l);
7188         aopPut(AOP(result),"a",offset);
7189       } else {
7190         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7191         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7192         //aopPut(AOP(result),l,offset);
7193       }
7194       offset++;
7195     }
7196   }
7197   
7198   size = AOP_SIZE(result);
7199   
7200   /* if it is only one byte then */
7201   if (size == 1) {
7202     if(optimized_for_speed) {
7203       emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7204       emitpcode(POC_ANDLW,  popGetLit(0xf0));
7205       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7206       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7207       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7208       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7209       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7210       emitpcode(POC_RLFW,   popGet(AOP(result),0));
7211       emitpcode(POC_ANDLW,  popGetLit(0xfe));
7212       emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7213       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7214       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7215     } else {
7216       
7217       tlbl = newiTempLabel(NULL);
7218       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7219         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7220         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7221       }
7222       
7223       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7224       emitpcode(POC_RRF,    popGet(AOP(result),0));
7225       emitpLabel(tlbl->key);
7226       emitpcode(POC_RLF,    popGet(AOP(result),0));
7227       emitpcode(POC_ADDLW,  popGetLit(1));
7228       emitSKPC;
7229       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7230     }
7231     goto release ;
7232   }
7233   
7234   if (pic14_sameRegs(AOP(left),AOP(result))) {
7235     
7236     tlbl = newiTempLabel(NULL);
7237     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7238     genMultiAsm(POC_RRF, result, size,1);
7239     emitpLabel(tlbl->key);
7240     genMultiAsm(POC_RLF, result, size,0);
7241     emitpcode(POC_ADDLW,  popGetLit(1));
7242     emitSKPC;
7243     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7244     goto release;
7245   }
7246   
7247   //tlbl = newiTempLabel(NULL);
7248   //offset = 0 ;   
7249   //tlbl1 = newiTempLabel(NULL);
7250   
7251   //reAdjustPreg(AOP(result));    
7252   
7253   //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7254   //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7255   //l = aopGet(AOP(result),offset,FALSE,FALSE);
7256   //MOVA(l);
7257   //pic14_emitcode("add","a,acc");         
7258   //aopPut(AOP(result),"a",offset++);
7259   //while (--size) {
7260   //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7261   //  MOVA(l);
7262   //  pic14_emitcode("rlc","a");         
7263   //  aopPut(AOP(result),"a",offset++);
7264   //}
7265   //reAdjustPreg(AOP(result));
7266   
7267   //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7268   //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7269   
7270   
7271   tlbl = newiTempLabel(NULL);
7272   tlbl1= newiTempLabel(NULL);
7273   
7274   size = AOP_SIZE(result);
7275   offset = 1;
7276   
7277   pctemp = popGetTempReg();  /* grab a temporary working register. */
7278   
7279   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7280   
7281   /* offset should be 0, 1 or 3 */
7282   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7283   emitSKPNZ;
7284   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7285   
7286   emitpcode(POC_MOVWF, pctemp);
7287   
7288   
7289   emitpLabel(tlbl->key);
7290   
7291   emitCLRC;
7292   emitpcode(POC_RLF,  popGet(AOP(result),0));
7293   while(--size)
7294     emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7295   
7296   emitpcode(POC_DECFSZ,  pctemp);
7297   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7298   emitpLabel(tlbl1->key);
7299   
7300   popReleaseTempReg(pctemp);
7301   
7302   
7303 release:
7304   freeAsmop (right,NULL,ic,TRUE);
7305   freeAsmop(left,NULL,ic,TRUE);
7306   freeAsmop(result,NULL,ic,TRUE);
7307 }
7308
7309 /*-----------------------------------------------------------------*/
7310 /* genrshOne - right shift a one byte quantity by known count      */
7311 /*-----------------------------------------------------------------*/
7312 static void genrshOne (operand *result, operand *left,
7313              int shCount, int sign)
7314 {
7315   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7316   shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7317 }
7318
7319 /*-----------------------------------------------------------------*/
7320 /* genrshTwo - right shift two bytes by known amount != 0          */
7321 /*-----------------------------------------------------------------*/
7322 static void genrshTwo (operand *result,operand *left,
7323              int shCount, int sign)
7324 {
7325   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7326   /* if shCount >= 8 */
7327   if (shCount >= 8) {
7328     shCount -= 8 ;
7329     if (shCount)
7330       shiftR1Left2Result(left, MSB16, result, LSB,
7331       shCount, sign);
7332     else
7333       movLeft2Result(left, MSB16, result, LSB);
7334     
7335     emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7336     
7337     if(sign) {
7338       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7339       emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7340     }
7341   }
7342   
7343   /*  1 <= shCount <= 7 */
7344   else
7345     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7346 }
7347
7348 /*-----------------------------------------------------------------*/
7349 /* shiftRLong - shift right one long from left to result           */
7350 /* offl = LSB or MSB16                                             */
7351 /*-----------------------------------------------------------------*/
7352 static void shiftRLong (operand *left, int offl,
7353             operand *result, int sign)
7354 {
7355   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7356   if(!sign)
7357     pic14_emitcode("clr","c");
7358   MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7359   if(sign)
7360     pic14_emitcode("mov","c,acc.7");
7361   pic14_emitcode("rrc","a");
7362   aopPut(AOP(result),"a",MSB32-offl);
7363   if(offl == MSB16)
7364     /* add sign of "a" */
7365     addSign(result, MSB32, sign);
7366   
7367   MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7368   pic14_emitcode("rrc","a");
7369   aopPut(AOP(result),"a",MSB24-offl);
7370   
7371   MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7372   pic14_emitcode("rrc","a");
7373   aopPut(AOP(result),"a",MSB16-offl);
7374   
7375   if(offl == LSB){
7376     MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7377     pic14_emitcode("rrc","a");
7378     aopPut(AOP(result),"a",LSB);
7379   }
7380 }
7381
7382 /*-----------------------------------------------------------------*/
7383 /* genrshFour - shift four byte by a known amount != 0             */
7384 /*-----------------------------------------------------------------*/
7385 static void genrshFour (operand *result, operand *left,
7386             int shCount, int sign)
7387 {
7388   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7389   /* if shifting more that 3 bytes */
7390   if(shCount >= 24 ) {
7391     shCount -= 24;
7392     if(shCount)
7393       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7394     else
7395       movLeft2Result(left, MSB32, result, LSB);
7396     
7397     addSign(result, MSB16, sign);
7398   }
7399   else if(shCount >= 16){
7400     shCount -= 16;
7401     if(shCount)
7402       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7403     else{
7404       movLeft2Result(left, MSB24, result, LSB);
7405       movLeft2Result(left, MSB32, result, MSB16);
7406     }
7407     addSign(result, MSB24, sign);
7408   }
7409   else if(shCount >= 8){
7410     shCount -= 8;
7411     if(shCount == 1)
7412       shiftRLong(left, MSB16, result, sign);
7413     else if(shCount == 0){
7414       movLeft2Result(left, MSB16, result, LSB);
7415       movLeft2Result(left, MSB24, result, MSB16);
7416       movLeft2Result(left, MSB32, result, MSB24);
7417       addSign(result, MSB32, sign);
7418     }
7419     else{
7420       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7421       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7422       /* the last shift is signed */
7423       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7424       addSign(result, MSB32, sign);
7425     }
7426   }
7427   else{   /* 1 <= shCount <= 7 */
7428     if(shCount <= 2){
7429       shiftRLong(left, LSB, result, sign);
7430       if(shCount == 2)
7431         shiftRLong(result, LSB, result, sign);
7432     }
7433     else{
7434       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7435       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7436       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7437     }
7438   }
7439 }
7440
7441 /*-----------------------------------------------------------------*/
7442 /* genRightShiftLiteral - right shifting by known count            */
7443 /*-----------------------------------------------------------------*/
7444 static void genRightShiftLiteral (operand *left,
7445                   operand *right,
7446                   operand *result,
7447                   iCode *ic,
7448                   int sign)
7449 {    
7450   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7451   int lsize,res_size;
7452   
7453   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7454   freeAsmop(right,NULL,ic,TRUE);
7455   
7456   aopOp(left,ic,FALSE);
7457   aopOp(result,ic,FALSE);
7458   
7459 #if VIEW_SIZE
7460   pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7461     AOP_SIZE(left));
7462 #endif
7463   
7464   lsize = pic14_getDataSize(left);
7465   res_size = pic14_getDataSize(result);
7466   /* test the LEFT size !!! */
7467   
7468   /* I suppose that the left size >= result size */
7469   if(shCount == 0){
7470     while(res_size--)
7471       movLeft2Result(left, lsize, result, res_size);
7472   }
7473   
7474   else if(shCount >= (lsize * 8)){
7475     
7476     if(res_size == 1) {
7477       emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7478       if(sign) {
7479         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7480         emitpcode(POC_DECF, popGet(AOP(result),LSB));
7481       }
7482     } else {
7483       
7484       if(sign) {
7485         emitpcode(POC_MOVLW, popGetLit(0));
7486         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7487         emitpcode(POC_MOVLW, popGetLit(0xff));
7488         while(res_size--)
7489           emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7490         
7491       } else {
7492         
7493         while(res_size--)
7494           emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7495       }
7496     }
7497   } else {
7498     
7499     switch (res_size) {
7500     case 1:
7501       genrshOne (result,left,shCount,sign);
7502       break;
7503       
7504     case 2:
7505       genrshTwo (result,left,shCount,sign);
7506       break;
7507       
7508     case 4:
7509       genrshFour (result,left,shCount,sign);
7510       break;
7511     default :
7512       break;
7513     }
7514     
7515   }
7516   
7517   freeAsmop(left,NULL,ic,TRUE);
7518   freeAsmop(result,NULL,ic,TRUE);
7519 }
7520
7521 /*-----------------------------------------------------------------*/
7522 /* genSignedRightShift - right shift of signed number              */
7523 /*-----------------------------------------------------------------*/
7524 static void genSignedRightShift (iCode *ic)
7525 {
7526   operand *right, *left, *result;
7527   int size, offset;
7528   //  char *l;
7529   symbol *tlbl, *tlbl1 ;
7530   pCodeOp *pctemp;
7531   
7532   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7533   
7534   /* we do it the hard way put the shift count in b
7535   and loop thru preserving the sign */
7536   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7537   
7538   right = IC_RIGHT(ic);
7539   left  = IC_LEFT(ic);
7540   result = IC_RESULT(ic);
7541   
7542   aopOp(right,ic,FALSE);  
7543   aopOp(left,ic,FALSE);
7544   aopOp(result,ic,FALSE);
7545   
7546   
7547   if ( AOP_TYPE(right) == AOP_LIT) {
7548     genRightShiftLiteral (left,right,result,ic,1);
7549     return ;
7550   }
7551   /* shift count is unknown then we have to form 
7552   a loop get the loop count in B : Note: we take
7553   only the lower order byte since shifting
7554   more that 32 bits make no sense anyway, ( the
7555   largest size of an object can be only 32 bits ) */  
7556   
7557   //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7558   //pic14_emitcode("inc","b");
7559   //freeAsmop (right,NULL,ic,TRUE);
7560   //aopOp(left,ic,FALSE);
7561   //aopOp(result,ic,FALSE);
7562   
7563   /* now move the left to the result if they are not the
7564   same */
7565   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7566     AOP_SIZE(result) > 1) {
7567     
7568     size = AOP_SIZE(result);
7569     offset=0;
7570     while (size--) { 
7571     /*
7572     l = aopGet(AOP(left),offset,FALSE,TRUE);
7573     if (*l == '@' && IS_AOP_PREG(result)) {
7574     
7575       pic14_emitcode("mov","a,%s",l);
7576       aopPut(AOP(result),"a",offset);
7577       } else
7578       aopPut(AOP(result),l,offset);
7579       */
7580       emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7581       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7582       
7583       offset++;
7584     }
7585   }
7586   
7587   /* mov the highest order bit to OVR */    
7588   tlbl = newiTempLabel(NULL);
7589   tlbl1= newiTempLabel(NULL);
7590   
7591   size = AOP_SIZE(result);
7592   offset = size - 1;
7593   
7594   pctemp = popGetTempReg();  /* grab a temporary working register. */
7595   
7596   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7597   
7598   /* offset should be 0, 1 or 3 */
7599   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7600   emitSKPNZ;
7601   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7602   
7603   emitpcode(POC_MOVWF, pctemp);
7604   
7605   
7606   emitpLabel(tlbl->key);
7607   
7608   emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7609   emitpcode(POC_RRF,   popGet(AOP(result),offset));
7610   
7611   while(--size) {
7612     emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7613   }
7614   
7615   emitpcode(POC_DECFSZ,  pctemp);
7616   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7617   emitpLabel(tlbl1->key);
7618   
7619   popReleaseTempReg(pctemp);
7620 #if 0
7621   size = AOP_SIZE(result);
7622   offset = size - 1;
7623   pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7624   pic14_emitcode("rlc","a");
7625   pic14_emitcode("mov","ov,c");
7626   /* if it is only one byte then */
7627   if (size == 1) {
7628     l = aopGet(AOP(left),0,FALSE,FALSE);
7629     MOVA(l);
7630     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7631     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7632     pic14_emitcode("mov","c,ov");
7633     pic14_emitcode("rrc","a");
7634     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7635     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7636     aopPut(AOP(result),"a",0);
7637     goto release ;
7638   }
7639   
7640   reAdjustPreg(AOP(result));
7641   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7642   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7643   pic14_emitcode("mov","c,ov");
7644   while (size--) {
7645     l = aopGet(AOP(result),offset,FALSE,FALSE);
7646     MOVA(l);
7647     pic14_emitcode("rrc","a");         
7648     aopPut(AOP(result),"a",offset--);
7649   }
7650   reAdjustPreg(AOP(result));
7651   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7652   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7653   
7654 release:
7655 #endif
7656   
7657   freeAsmop(left,NULL,ic,TRUE);
7658   freeAsmop(result,NULL,ic,TRUE);
7659   freeAsmop(right,NULL,ic,TRUE);
7660 }
7661
7662 /*-----------------------------------------------------------------*/
7663 /* genRightShift - generate code for right shifting                */
7664 /*-----------------------------------------------------------------*/
7665 static void genRightShift (iCode *ic)
7666 {
7667   operand *right, *left, *result;
7668   sym_link *retype ;
7669   int size, offset;
7670   char *l;
7671   symbol *tlbl, *tlbl1 ;
7672   
7673   /* if signed then we do it the hard way preserve the
7674   sign bit moving it inwards */
7675   retype = getSpec(operandType(IC_RESULT(ic)));
7676   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7677   
7678   if (!SPEC_USIGN(retype)) {
7679     genSignedRightShift (ic);
7680     return ;
7681   }
7682   
7683   /* signed & unsigned types are treated the same : i.e. the
7684   signed is NOT propagated inwards : quoting from the
7685   ANSI - standard : "for E1 >> E2, is equivalent to division
7686   by 2**E2 if unsigned or if it has a non-negative value,
7687   otherwise the result is implementation defined ", MY definition
7688   is that the sign does not get propagated */
7689   
7690   right = IC_RIGHT(ic);
7691   left  = IC_LEFT(ic);
7692   result = IC_RESULT(ic);
7693   
7694   aopOp(right,ic,FALSE);
7695   
7696   /* if the shift count is known then do it 
7697   as efficiently as possible */
7698   if (AOP_TYPE(right) == AOP_LIT) {
7699     genRightShiftLiteral (left,right,result,ic, 0);
7700     return ;
7701   }
7702   
7703   /* shift count is unknown then we have to form 
7704   a loop get the loop count in B : Note: we take
7705   only the lower order byte since shifting
7706   more that 32 bits make no sense anyway, ( the
7707   largest size of an object can be only 32 bits ) */  
7708   
7709   pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7710   pic14_emitcode("inc","b");
7711   aopOp(left,ic,FALSE);
7712   aopOp(result,ic,FALSE);
7713   
7714   /* now move the left to the result if they are not the
7715   same */
7716   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7717     AOP_SIZE(result) > 1) {
7718     
7719     size = AOP_SIZE(result);
7720     offset=0;
7721     while (size--) {
7722       l = aopGet(AOP(left),offset,FALSE,TRUE);
7723       if (*l == '@' && IS_AOP_PREG(result)) {
7724         
7725         pic14_emitcode("mov","a,%s",l);
7726         aopPut(AOP(result),"a",offset);
7727       } else
7728         aopPut(AOP(result),l,offset);
7729       offset++;
7730     }
7731   }
7732   
7733   tlbl = newiTempLabel(NULL);
7734   tlbl1= newiTempLabel(NULL);
7735   size = AOP_SIZE(result);
7736   offset = size - 1;
7737   
7738   /* if it is only one byte then */
7739   if (size == 1) {
7740     
7741     tlbl = newiTempLabel(NULL);
7742     if (!pic14_sameRegs(AOP(left),AOP(result))) {
7743       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7744       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7745     }
7746     
7747     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7748     emitpcode(POC_RLF,    popGet(AOP(result),0));
7749     emitpLabel(tlbl->key);
7750     emitpcode(POC_RRF,    popGet(AOP(result),0));
7751     emitpcode(POC_ADDLW,  popGetLit(1));
7752     emitSKPC;
7753     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7754     
7755     goto release ;
7756   }
7757   
7758   reAdjustPreg(AOP(result));
7759   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7760   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7761   CLRC;
7762   while (size--) {
7763     l = aopGet(AOP(result),offset,FALSE,FALSE);
7764     MOVA(l);
7765     pic14_emitcode("rrc","a");         
7766     aopPut(AOP(result),"a",offset--);
7767   }
7768   reAdjustPreg(AOP(result));
7769   
7770   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7771   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7772   
7773 release:
7774   freeAsmop(left,NULL,ic,TRUE);
7775   freeAsmop (right,NULL,ic,TRUE);
7776   freeAsmop(result,NULL,ic,TRUE);
7777 }
7778
7779 /*-----------------------------------------------------------------*/
7780 /* genUnpackBits - generates code for unpacking bits               */
7781 /*-----------------------------------------------------------------*/
7782 static void genUnpackBits (operand *result, char *rname, int ptype)
7783 {    
7784   int shCnt ;
7785   int rlen = 0 ;
7786   sym_link *etype;
7787   int offset = 0 ;
7788   
7789   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7790   etype = getSpec(operandType(result));
7791   
7792   /* read the first byte  */
7793   switch (ptype) {
7794     
7795   case POINTER:
7796   case IPOINTER:
7797     pic14_emitcode("mov","a,@%s",rname);
7798     break;
7799     
7800   case PPOINTER:
7801     pic14_emitcode("movx","a,@%s",rname);
7802     break;
7803     
7804   case FPOINTER:
7805     pic14_emitcode("movx","a,@dptr");
7806     break;
7807     
7808   case CPOINTER:
7809     pic14_emitcode("clr","a");
7810     pic14_emitcode("movc","a","@a+dptr");
7811     break;
7812     
7813   case GPOINTER:
7814     pic14_emitcode("lcall","__gptrget");
7815     break;
7816   }
7817   
7818   /* if we have bitdisplacement then it fits   */
7819   /* into this byte completely or if length is */
7820   /* less than a byte                          */
7821   if ((shCnt = SPEC_BSTR(etype)) || 
7822     (SPEC_BLEN(etype) <= 8))  {
7823     
7824     /* shift right acc */
7825     AccRsh(shCnt);
7826     
7827     pic14_emitcode("anl","a,#0x%02x",
7828       ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7829     aopPut(AOP(result),"a",offset);
7830     return ;
7831   }
7832   
7833   /* bit field did not fit in a byte  */
7834   rlen = SPEC_BLEN(etype) - 8;
7835   aopPut(AOP(result),"a",offset++);
7836   
7837   while (1)  {
7838     
7839     switch (ptype) {
7840     case POINTER:
7841     case IPOINTER:
7842       pic14_emitcode("inc","%s",rname);
7843       pic14_emitcode("mov","a,@%s",rname);
7844       break;
7845       
7846     case PPOINTER:
7847       pic14_emitcode("inc","%s",rname);
7848       pic14_emitcode("movx","a,@%s",rname);
7849       break;
7850       
7851     case FPOINTER:
7852       pic14_emitcode("inc","dptr");
7853       pic14_emitcode("movx","a,@dptr");
7854       break;
7855       
7856     case CPOINTER:
7857       pic14_emitcode("clr","a");
7858       pic14_emitcode("inc","dptr");
7859       pic14_emitcode("movc","a","@a+dptr");
7860       break;
7861       
7862     case GPOINTER:
7863       pic14_emitcode("inc","dptr");
7864       pic14_emitcode("lcall","__gptrget");
7865       break;
7866     }
7867     
7868     rlen -= 8;            
7869     /* if we are done */
7870     if ( rlen <= 0 )
7871       break ;
7872     
7873     aopPut(AOP(result),"a",offset++);
7874     
7875   }
7876   
7877   if (rlen) {
7878     pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7879     aopPut(AOP(result),"a",offset);        
7880   }
7881   
7882   return ;
7883 }
7884
7885 #if 0
7886 /*-----------------------------------------------------------------*/
7887 /* genDataPointerGet - generates code when ptr offset is known     */
7888 /*-----------------------------------------------------------------*/
7889 static void genDataPointerGet (operand *left, 
7890                  operand *result, 
7891                  iCode *ic)
7892 {
7893   int size , offset = 0;
7894   
7895   
7896   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7897   
7898   
7899   /* optimization - most of the time, left and result are the same
7900   * address, but different types. for the pic code, we could omit
7901   * the following
7902   */
7903   
7904   aopOp(result,ic,TRUE);
7905   
7906   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7907   
7908   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7909   
7910   size = AOP_SIZE(result);
7911   
7912   while (size--) {
7913     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7914     offset++;
7915   }
7916   
7917   freeAsmop(left,NULL,ic,TRUE);
7918   freeAsmop(result,NULL,ic,TRUE);
7919 }
7920 #endif
7921 /*-----------------------------------------------------------------*/
7922 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7923 /*-----------------------------------------------------------------*/
7924 static void genNearPointerGet (operand *left, 
7925                  operand *result, 
7926                  iCode *ic)
7927 {
7928   asmop *aop = NULL;
7929   //regs *preg = NULL ;
7930   char *rname ;
7931   sym_link *rtype, *retype;
7932   sym_link *ltype = operandType(left);    
7933   //char buffer[80];
7934   
7935   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7936   
7937   rtype = operandType(result);
7938   retype= getSpec(rtype);
7939   
7940   aopOp(left,ic,FALSE);
7941   
7942   /* if left is rematerialisable and
7943   result is not bit variable type and
7944   the left is pointer to data space i.e
7945   lower 128 bytes of space */
7946   if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
7947     !IS_BITVAR(retype)         &&
7948     DCL_TYPE(ltype) == POINTER) {
7949     //genDataPointerGet (left,result,ic);
7950     return ;
7951   }
7952   
7953   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7954   
7955   /* if the value is already in a pointer register
7956   then don't need anything more */
7957   if (!AOP_INPREG(AOP(left))) {
7958     /* otherwise get a free pointer register */
7959     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7960     /*
7961     aop = newAsmop(0);
7962     preg = getFreePtr(ic,&aop,FALSE);
7963     pic14_emitcode("mov","%s,%s",
7964     preg->name,
7965     aopGet(AOP(left),0,FALSE,TRUE));
7966     rname = preg->name ;
7967     */
7968     rname ="BAD";
7969   } else
7970     rname = aopGet(AOP(left),0,FALSE,FALSE);
7971   
7972   aopOp (result,ic,FALSE);
7973   
7974   /* if bitfield then unpack the bits */
7975   if (IS_BITFIELD(retype)) 
7976     genUnpackBits (result,rname,POINTER);
7977   else {
7978     /* we have can just get the values */
7979     int size = AOP_SIZE(result);
7980     int offset = 0 ;  
7981     
7982     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7983     
7984     emitpcode(POC_MOVFW,popGet(AOP(left),0));
7985     emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7986     while(size--) {
7987       emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7988       emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
7989       if(size)
7990         emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7991     }
7992     /*
7993     while (size--) {
7994     if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7995
7996       pic14_emitcode("mov","a,@%s",rname);
7997       aopPut(AOP(result),"a",offset);
7998       } else {
7999       sprintf(buffer,"@%s",rname);
8000       aopPut(AOP(result),buffer,offset);
8001       }
8002       offset++ ;
8003       if (size)
8004       pic14_emitcode("inc","%s",rname);
8005     }
8006     */
8007   }
8008   
8009   /* now some housekeeping stuff */
8010   if (aop) {
8011     /* we had to allocate for this iCode */
8012     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8013     freeAsmop(NULL,aop,ic,TRUE);
8014   } else { 
8015   /* we did not allocate which means left
8016      already in a pointer register, then
8017      if size > 0 && this could be used again
8018      we have to point it back to where it 
8019     belongs */
8020     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8021     if (AOP_SIZE(result) > 1 &&
8022       !OP_SYMBOL(left)->remat &&
8023       ( OP_SYMBOL(left)->liveTo > ic->seq ||
8024       ic->depth )) {
8025       int size = AOP_SIZE(result) - 1;
8026       while (size--)
8027         pic14_emitcode("dec","%s",rname);
8028     }
8029   }
8030   
8031   /* done */
8032   freeAsmop(left,NULL,ic,TRUE);
8033   freeAsmop(result,NULL,ic,TRUE);
8034   
8035 }
8036
8037 /*-----------------------------------------------------------------*/
8038 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8039 /*-----------------------------------------------------------------*/
8040 static void genPagedPointerGet (operand *left, 
8041                 operand *result, 
8042                 iCode *ic)
8043 {
8044   asmop *aop = NULL;
8045   regs *preg = NULL ;
8046   char *rname ;
8047   sym_link *rtype, *retype;    
8048   
8049   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8050   
8051   rtype = operandType(result);
8052   retype= getSpec(rtype);
8053   
8054   aopOp(left,ic,FALSE);
8055   
8056   /* if the value is already in a pointer register
8057   then don't need anything more */
8058   if (!AOP_INPREG(AOP(left))) {
8059     /* otherwise get a free pointer register */
8060     aop = newAsmop(0);
8061     preg = getFreePtr(ic,&aop,FALSE);
8062     pic14_emitcode("mov","%s,%s",
8063       preg->name,
8064       aopGet(AOP(left),0,FALSE,TRUE));
8065     rname = preg->name ;
8066   } else
8067     rname = aopGet(AOP(left),0,FALSE,FALSE);
8068   
8069   freeAsmop(left,NULL,ic,TRUE);
8070   aopOp (result,ic,FALSE);
8071   
8072   /* if bitfield then unpack the bits */
8073   if (IS_BITFIELD(retype)) 
8074     genUnpackBits (result,rname,PPOINTER);
8075   else {
8076     /* we have can just get the values */
8077     int size = AOP_SIZE(result);
8078     int offset = 0 ;  
8079     
8080     while (size--) {
8081       
8082       pic14_emitcode("movx","a,@%s",rname);
8083       aopPut(AOP(result),"a",offset);
8084       
8085       offset++ ;
8086       
8087       if (size)
8088         pic14_emitcode("inc","%s",rname);
8089     }
8090   }
8091   
8092   /* now some housekeeping stuff */
8093   if (aop) {
8094     /* we had to allocate for this iCode */
8095     freeAsmop(NULL,aop,ic,TRUE);
8096   } else { 
8097   /* we did not allocate which means left
8098      already in a pointer register, then
8099      if size > 0 && this could be used again
8100      we have to point it back to where it 
8101     belongs */
8102     if (AOP_SIZE(result) > 1 &&
8103       !OP_SYMBOL(left)->remat &&
8104       ( OP_SYMBOL(left)->liveTo > ic->seq ||
8105       ic->depth )) {
8106       int size = AOP_SIZE(result) - 1;
8107       while (size--)
8108         pic14_emitcode("dec","%s",rname);
8109     }
8110   }
8111   
8112   /* done */
8113   freeAsmop(result,NULL,ic,TRUE);
8114   
8115   
8116 }
8117
8118 /*-----------------------------------------------------------------*/
8119 /* genFarPointerGet - gget value from far space                    */
8120 /*-----------------------------------------------------------------*/
8121 static void genFarPointerGet (operand *left,
8122                 operand *result, iCode *ic)
8123 {
8124   int size, offset ;
8125   sym_link *retype = getSpec(operandType(result));
8126   
8127   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8128   
8129   aopOp(left,ic,FALSE);
8130   
8131   /* if the operand is already in dptr 
8132   then we do nothing else we move the value to dptr */
8133   if (AOP_TYPE(left) != AOP_STR) {
8134     /* if this is remateriazable */
8135     if (AOP_TYPE(left) == AOP_IMMD)
8136       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8137     else { /* we need to get it byte by byte */
8138       pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8139       pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8140       if (options.model == MODEL_FLAT24)
8141       {
8142         pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8143       }
8144     }
8145   }
8146   /* so dptr know contains the address */
8147   freeAsmop(left,NULL,ic,TRUE);
8148   aopOp(result,ic,FALSE);
8149   
8150   /* if bit then unpack */
8151   if (IS_BITFIELD(retype)) 
8152     genUnpackBits(result,"dptr",FPOINTER);
8153   else {
8154     size = AOP_SIZE(result);
8155     offset = 0 ;
8156     
8157     while (size--) {
8158       pic14_emitcode("movx","a,@dptr");
8159       aopPut(AOP(result),"a",offset++);
8160       if (size)
8161         pic14_emitcode("inc","dptr");
8162     }
8163   }
8164   
8165   freeAsmop(result,NULL,ic,TRUE);
8166 }
8167 #if 0
8168 /*-----------------------------------------------------------------*/
8169 /* genCodePointerGet - get value from code space                  */
8170 /*-----------------------------------------------------------------*/
8171 static void genCodePointerGet (operand *left,
8172                  operand *result, iCode *ic)
8173 {
8174   int size, offset ;
8175   sym_link *retype = getSpec(operandType(result));
8176   
8177   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8178   
8179   aopOp(left,ic,FALSE);
8180   
8181   /* if the operand is already in dptr 
8182   then we do nothing else we move the value to dptr */
8183   if (AOP_TYPE(left) != AOP_STR) {
8184     /* if this is remateriazable */
8185     if (AOP_TYPE(left) == AOP_IMMD)
8186       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8187     else { /* we need to get it byte by byte */
8188       pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8189       pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8190       if (options.model == MODEL_FLAT24)
8191       {
8192         pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8193       }
8194     }
8195   }
8196   /* so dptr know contains the address */
8197   freeAsmop(left,NULL,ic,TRUE);
8198   aopOp(result,ic,FALSE);
8199   
8200   /* if bit then unpack */
8201   if (IS_BITFIELD(retype)) 
8202     genUnpackBits(result,"dptr",CPOINTER);
8203   else {
8204     size = AOP_SIZE(result);
8205     offset = 0 ;
8206     
8207     while (size--) {
8208       pic14_emitcode("clr","a");
8209       pic14_emitcode("movc","a,@a+dptr");
8210       aopPut(AOP(result),"a",offset++);
8211       if (size)
8212         pic14_emitcode("inc","dptr");
8213     }
8214   }
8215   
8216   freeAsmop(result,NULL,ic,TRUE);
8217 }
8218 #endif
8219 /*-----------------------------------------------------------------*/
8220 /* genGenPointerGet - gget value from generic pointer space        */
8221 /*-----------------------------------------------------------------*/
8222 static void genGenPointerGet (operand *left,
8223                 operand *result, iCode *ic)
8224 {
8225   int size, offset ;
8226   sym_link *retype = getSpec(operandType(result));
8227   
8228   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8229   aopOp(left,ic,FALSE);
8230   aopOp(result,ic,FALSE);
8231   
8232   
8233   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8234   
8235   /* if the operand is already in dptr 
8236   then we do nothing else we move the value to dptr */
8237   //  if (AOP_TYPE(left) != AOP_STR) {
8238   /* if this is remateriazable */
8239   if (AOP_TYPE(left) == AOP_IMMD) {
8240     pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8241     pic14_emitcode("mov","b,#%d",pointerCode(retype));
8242   }
8243   else { /* we need to get it byte by byte */
8244     
8245     emitpcode(POC_MOVFW,popGet(AOP(left),0));
8246     emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8247     
8248     size = AOP_SIZE(result);
8249     offset = 0 ;
8250     
8251     while(size--) {
8252       emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8253       emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8254       if(size)
8255         emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8256     }
8257     goto release;
8258   }
8259   //}
8260   /* so dptr know contains the address */
8261   
8262   /* if bit then unpack */
8263   //if (IS_BITFIELD(retype)) 
8264   //  genUnpackBits(result,"dptr",GPOINTER);
8265   
8266 release:
8267   freeAsmop(left,NULL,ic,TRUE);
8268   freeAsmop(result,NULL,ic,TRUE);
8269   
8270 }
8271
8272 /*-----------------------------------------------------------------*/
8273 /* genConstPointerGet - get value from const generic pointer space */
8274 /*-----------------------------------------------------------------*/
8275 static void genConstPointerGet (operand *left,
8276                 operand *result, iCode *ic)
8277 {
8278   //sym_link *retype = getSpec(operandType(result));
8279   symbol *albl = newiTempLabel(NULL);
8280   symbol *blbl = newiTempLabel(NULL);
8281   PIC_OPCODE poc;
8282   pCodeOp *pcop;
8283   
8284   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8285   aopOp(left,ic,FALSE);
8286   aopOp(result,ic,FALSE);
8287   
8288   
8289   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8290   
8291   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8292   
8293   emitpcode(POC_CALL,popGetLabel(albl->key));
8294   pcop = popGetLabel(blbl->key);
8295   emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8296   emitpcode(POC_GOTO,pcop);
8297   emitpLabel(albl->key);
8298   
8299   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8300   
8301   emitpcode(poc,popGet(AOP(left),1));
8302   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8303   emitpcode(poc,popGet(AOP(left),0));
8304   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8305   
8306   emitpLabel(blbl->key);
8307   
8308   emitpcode(POC_MOVWF,popGet(AOP(result),0));
8309   
8310   
8311   freeAsmop(left,NULL,ic,TRUE);
8312   freeAsmop(result,NULL,ic,TRUE);
8313   
8314 }
8315 /*-----------------------------------------------------------------*/
8316 /* genPointerGet - generate code for pointer get                   */
8317 /*-----------------------------------------------------------------*/
8318 static void genPointerGet (iCode *ic)
8319 {
8320   operand *left, *result ;
8321   sym_link *type, *etype;
8322   int p_type;
8323   
8324   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8325   
8326   left = IC_LEFT(ic);
8327   result = IC_RESULT(ic) ;
8328   
8329   /* depending on the type of pointer we need to
8330   move it to the correct pointer register */
8331   type = operandType(left);
8332   etype = getSpec(type);
8333   
8334   if (IS_PTR_CONST(type))
8335     DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8336   
8337   /* if left is of type of pointer then it is simple */
8338   if (IS_PTR(type) && !IS_FUNC(type->next)) 
8339     p_type = DCL_TYPE(type);
8340   else {
8341     /* we have to go by the storage class */
8342     p_type = PTR_TYPE(SPEC_OCLS(etype));
8343     
8344     DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8345     
8346     if (SPEC_OCLS(etype)->codesp ) {
8347       DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8348       //p_type = CPOINTER ; 
8349     }
8350     else
8351       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8352         DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8353       /*p_type = FPOINTER ;*/ 
8354       else
8355         if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8356           DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8357         /*        p_type = PPOINTER; */
8358         else
8359           if (SPEC_OCLS(etype) == idata )
8360             DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8361           /*      p_type = IPOINTER; */
8362           else
8363             DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8364           /*      p_type = POINTER ; */
8365   }
8366   
8367   /* now that we have the pointer type we assign
8368   the pointer values */
8369   switch (p_type) {
8370     
8371   case POINTER: 
8372   case IPOINTER:
8373     genNearPointerGet (left,result,ic);
8374     break;
8375     
8376   case PPOINTER:
8377     genPagedPointerGet(left,result,ic);
8378     break;
8379     
8380   case FPOINTER:
8381     genFarPointerGet (left,result,ic);
8382     break;
8383     
8384   case CPOINTER:
8385     genConstPointerGet (left,result,ic);
8386     //pic14_emitcodePointerGet (left,result,ic);
8387     break;
8388     
8389   case GPOINTER:
8390     if (IS_PTR_CONST(type))
8391       genConstPointerGet (left,result,ic);
8392     else
8393       genGenPointerGet (left,result,ic);
8394     break;
8395   }
8396   
8397 }
8398
8399 /*-----------------------------------------------------------------*/
8400 /* genPackBits - generates code for packed bit storage             */
8401 /*-----------------------------------------------------------------*/
8402 static void genPackBits (sym_link    *etype ,
8403              operand *right ,
8404              char *rname, int p_type)
8405 {
8406   int shCount = 0 ;
8407   int offset = 0  ;
8408   int rLen = 0 ;
8409   int blen, bstr ;   
8410   char *l ;
8411   
8412   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8413   blen = SPEC_BLEN(etype);
8414   bstr = SPEC_BSTR(etype);
8415   
8416   l = aopGet(AOP(right),offset++,FALSE,FALSE);
8417   MOVA(l);   
8418   
8419   /* if the bit lenth is less than or    */
8420   /* it exactly fits a byte then         */
8421   if (SPEC_BLEN(etype) <= 8 )  {
8422     shCount = SPEC_BSTR(etype) ;
8423     
8424     /* shift left acc */
8425     AccLsh(shCount);
8426     
8427     if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8428       
8429       
8430       switch (p_type) {
8431       case POINTER:
8432         pic14_emitcode ("mov","b,a");
8433         pic14_emitcode("mov","a,@%s",rname);
8434         break;
8435         
8436       case FPOINTER:
8437         pic14_emitcode ("mov","b,a");
8438         pic14_emitcode("movx","a,@dptr");
8439         break;
8440         
8441       case GPOINTER:
8442         pic14_emitcode ("push","b");
8443         pic14_emitcode ("push","acc");
8444         pic14_emitcode ("lcall","__gptrget");
8445         pic14_emitcode ("pop","b");
8446         break;
8447       }
8448       
8449       pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8450         ((unsigned char)(0xFF << (blen+bstr)) | 
8451         (unsigned char)(0xFF >> (8-bstr)) ) );
8452       pic14_emitcode ("orl","a,b");
8453       if (p_type == GPOINTER)
8454         pic14_emitcode("pop","b");
8455     }
8456   }
8457   
8458   switch (p_type) {
8459   case POINTER:
8460     pic14_emitcode("mov","@%s,a",rname);
8461     break;
8462     
8463   case FPOINTER:
8464     pic14_emitcode("movx","@dptr,a");
8465     break;
8466     
8467   case GPOINTER:
8468     DEBUGpic14_emitcode(";lcall","__gptrput");
8469     break;
8470   }
8471   
8472   /* if we r done */
8473   if ( SPEC_BLEN(etype) <= 8 )
8474     return ;
8475   
8476   pic14_emitcode("inc","%s",rname);
8477   rLen = SPEC_BLEN(etype) ;     
8478   
8479   /* now generate for lengths greater than one byte */
8480   while (1) {
8481     
8482     l = aopGet(AOP(right),offset++,FALSE,TRUE);
8483     
8484     rLen -= 8 ;
8485     if (rLen <= 0 )
8486       break ;
8487     
8488     switch (p_type) {
8489     case POINTER:
8490       if (*l == '@') {
8491         MOVA(l);
8492         pic14_emitcode("mov","@%s,a",rname);
8493       } else
8494         pic14_emitcode("mov","@%s,%s",rname,l);
8495       break;
8496       
8497     case FPOINTER:
8498       MOVA(l);
8499       pic14_emitcode("movx","@dptr,a");
8500       break;
8501       
8502     case GPOINTER:
8503       MOVA(l);
8504       DEBUGpic14_emitcode(";lcall","__gptrput");
8505       break;  
8506     }   
8507     pic14_emitcode ("inc","%s",rname);
8508   }
8509   
8510   MOVA(l);
8511   
8512   /* last last was not complete */
8513   if (rLen)   {
8514     /* save the byte & read byte */
8515     switch (p_type) {
8516     case POINTER:
8517       pic14_emitcode ("mov","b,a");
8518       pic14_emitcode("mov","a,@%s",rname);
8519       break;
8520       
8521     case FPOINTER:
8522       pic14_emitcode ("mov","b,a");
8523       pic14_emitcode("movx","a,@dptr");
8524       break;
8525       
8526     case GPOINTER:
8527       pic14_emitcode ("push","b");
8528       pic14_emitcode ("push","acc");
8529       pic14_emitcode ("lcall","__gptrget");
8530       pic14_emitcode ("pop","b");
8531       break;
8532     }
8533     
8534     pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8535     pic14_emitcode ("orl","a,b");
8536   }
8537   
8538   if (p_type == GPOINTER)
8539     pic14_emitcode("pop","b");
8540   
8541   switch (p_type) {
8542     
8543   case POINTER:
8544     pic14_emitcode("mov","@%s,a",rname);
8545     break;
8546     
8547   case FPOINTER:
8548     pic14_emitcode("movx","@dptr,a");
8549     break;
8550     
8551   case GPOINTER:
8552     DEBUGpic14_emitcode(";lcall","__gptrput");
8553     break;      
8554   }
8555 }
8556 /*-----------------------------------------------------------------*/
8557 /* genDataPointerSet - remat pointer to data space                 */
8558 /*-----------------------------------------------------------------*/
8559 static void genDataPointerSet(operand *right,
8560                 operand *result,
8561                 iCode *ic)
8562 {
8563   int size, offset = 0 ;
8564   char *l, buffer[256];
8565   
8566   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8567   aopOp(right,ic,FALSE);
8568   
8569   l = aopGet(AOP(result),0,FALSE,TRUE);
8570   size = AOP_SIZE(right);
8571   /*
8572   if ( AOP_TYPE(result) == AOP_PCODE) {
8573   fprintf(stderr,"genDataPointerSet   %s, %d\n",
8574   AOP(result)->aopu.pcop->name,
8575   PCOI(AOP(result)->aopu.pcop)->offset);
8576   }
8577   */
8578   
8579   // tsd, was l+1 - the underline `_' prefix was being stripped
8580   while (size--) {
8581     if (offset) {
8582       sprintf(buffer,"(%s + %d)",l,offset);
8583       fprintf(stderr,"oops  %s\n",buffer);
8584     } else
8585       sprintf(buffer,"%s",l);
8586     
8587     if (AOP_TYPE(right) == AOP_LIT) {
8588       unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8589       lit = lit >> (8*offset);
8590       if(lit&0xff) {
8591         pic14_emitcode("movlw","%d",lit);
8592         pic14_emitcode("movwf","%s",buffer);
8593         
8594         emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8595         //emitpcode(POC_MOVWF, popRegFromString(buffer));
8596         emitpcode(POC_MOVWF, popGet(AOP(result),0));
8597         
8598       } else {
8599         pic14_emitcode("clrf","%s",buffer);
8600         //emitpcode(POC_CLRF, popRegFromString(buffer));
8601         emitpcode(POC_CLRF, popGet(AOP(result),0));
8602       }
8603     }else {
8604       pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8605       pic14_emitcode("movwf","%s",buffer);
8606       
8607       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8608       //emitpcode(POC_MOVWF, popRegFromString(buffer));
8609       emitpcode(POC_MOVWF, popGet(AOP(result),0));
8610       
8611     }
8612     
8613     offset++;
8614   }
8615   
8616   freeAsmop(right,NULL,ic,TRUE);
8617   freeAsmop(result,NULL,ic,TRUE);
8618 }
8619
8620 /*-----------------------------------------------------------------*/
8621 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8622 /*-----------------------------------------------------------------*/
8623 static void genNearPointerSet (operand *right,
8624                  operand *result, 
8625                  iCode *ic)
8626 {
8627   asmop *aop = NULL;
8628   char *l;
8629   sym_link *retype;
8630   sym_link *ptype = operandType(result);
8631   
8632   
8633   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8634   retype= getSpec(operandType(right));
8635   
8636   aopOp(result,ic,FALSE);
8637   
8638   
8639   /* if the result is rematerializable &
8640   in data space & not a bit variable */
8641   //if (AOP_TYPE(result) == AOP_IMMD &&
8642   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8643     DCL_TYPE(ptype) == POINTER   &&
8644     !IS_BITFIELD(retype)) {
8645     genDataPointerSet (right,result,ic);
8646     freeAsmop(result,NULL,ic,TRUE);
8647     return;
8648   }
8649   
8650   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8651   aopOp(right,ic,FALSE);
8652   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8653   
8654   /* if the value is already in a pointer register
8655   then don't need anything more */
8656   if (!AOP_INPREG(AOP(result))) {
8657     /* otherwise get a free pointer register */
8658     //aop = newAsmop(0);
8659     //preg = getFreePtr(ic,&aop,FALSE);
8660     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8661     //pic14_emitcode("mov","%s,%s",
8662     //         preg->name,
8663     //         aopGet(AOP(result),0,FALSE,TRUE));
8664     //rname = preg->name ;
8665     //pic14_emitcode("movwf","fsr");
8666     emitpcode(POC_MOVFW, popGet(AOP(result),0));
8667     emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8668     emitpcode(POC_MOVFW, popGet(AOP(right),0));
8669     emitpcode(POC_MOVWF, popCopyReg(&pc_indf));
8670     goto release;
8671     
8672   }// else
8673   //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8674   
8675   
8676   /* if bitfield then unpack the bits */
8677   if (IS_BITFIELD(retype)) {
8678     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8679       "The programmer is obviously confused");
8680     //genPackBits (retype,right,rname,POINTER);
8681     exit(1);
8682   }
8683   else {
8684     /* we have can just get the values */
8685     int size = AOP_SIZE(right);
8686     int offset = 0 ;    
8687     
8688     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8689     while (size--) {
8690       l = aopGet(AOP(right),offset,FALSE,TRUE);
8691       if (*l == '@' ) {
8692         //MOVA(l);
8693         //pic14_emitcode("mov","@%s,a",rname);
8694         pic14_emitcode("movf","indf,w ;1");
8695       } else {
8696         
8697         if (AOP_TYPE(right) == AOP_LIT) {
8698           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8699           if(lit) {
8700             pic14_emitcode("movlw","%s",l);
8701             pic14_emitcode("movwf","indf ;2");
8702           } else 
8703             pic14_emitcode("clrf","indf");
8704         }else {
8705           pic14_emitcode("movf","%s,w",l);
8706           pic14_emitcode("movwf","indf ;2");
8707         }
8708         //pic14_emitcode("mov","@%s,%s",rname,l);
8709       }
8710       if (size)
8711         pic14_emitcode("incf","fsr,f ;3");
8712       //pic14_emitcode("inc","%s",rname);
8713       offset++;
8714     }
8715   }
8716   
8717   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8718   /* now some housekeeping stuff */
8719   if (aop) {
8720     /* we had to allocate for this iCode */
8721     freeAsmop(NULL,aop,ic,TRUE);
8722   } else { 
8723   /* we did not allocate which means left
8724   already in a pointer register, then
8725   if size > 0 && this could be used again
8726   we have to point it back to where it 
8727     belongs */
8728     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8729     if (AOP_SIZE(right) > 1 &&
8730       !OP_SYMBOL(result)->remat &&
8731       ( OP_SYMBOL(result)->liveTo > ic->seq ||
8732       ic->depth )) {
8733       int size = AOP_SIZE(right) - 1;
8734       while (size--)
8735         pic14_emitcode("decf","fsr,f");
8736       //pic14_emitcode("dec","%s",rname);
8737     }
8738   }
8739   
8740   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8741   /* done */
8742 release:
8743   freeAsmop(right,NULL,ic,TRUE);
8744   freeAsmop(result,NULL,ic,TRUE);
8745 }
8746
8747 /*-----------------------------------------------------------------*/
8748 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8749 /*-----------------------------------------------------------------*/
8750 static void genPagedPointerSet (operand *right,
8751                 operand *result, 
8752                 iCode *ic)
8753 {
8754   asmop *aop = NULL;
8755   regs *preg = NULL ;
8756   char *rname , *l;
8757   sym_link *retype;
8758   
8759   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8760   
8761   retype= getSpec(operandType(right));
8762   
8763   aopOp(result,ic,FALSE);
8764   
8765   /* if the value is already in a pointer register
8766   then don't need anything more */
8767   if (!AOP_INPREG(AOP(result))) {
8768     /* otherwise get a free pointer register */
8769     aop = newAsmop(0);
8770     preg = getFreePtr(ic,&aop,FALSE);
8771     pic14_emitcode("mov","%s,%s",
8772       preg->name,
8773       aopGet(AOP(result),0,FALSE,TRUE));
8774     rname = preg->name ;
8775   } else
8776     rname = aopGet(AOP(result),0,FALSE,FALSE);
8777   
8778   freeAsmop(result,NULL,ic,TRUE);
8779   aopOp (right,ic,FALSE);
8780   
8781   /* if bitfield then unpack the bits */
8782   if (IS_BITFIELD(retype)) 
8783     genPackBits (retype,right,rname,PPOINTER);
8784   else {
8785     /* we have can just get the values */
8786     int size = AOP_SIZE(right);
8787     int offset = 0 ;  
8788     
8789     while (size--) {
8790       l = aopGet(AOP(right),offset,FALSE,TRUE);
8791       
8792       MOVA(l);
8793       pic14_emitcode("movx","@%s,a",rname);
8794       
8795       if (size)
8796         pic14_emitcode("inc","%s",rname);
8797       
8798       offset++;
8799     }
8800   }
8801   
8802   /* now some housekeeping stuff */
8803   if (aop) {
8804     /* we had to allocate for this iCode */
8805     freeAsmop(NULL,aop,ic,TRUE);
8806   } else { 
8807   /* we did not allocate which means left
8808      already in a pointer register, then
8809      if size > 0 && this could be used again
8810      we have to point it back to where it 
8811     belongs */
8812     if (AOP_SIZE(right) > 1 &&
8813       !OP_SYMBOL(result)->remat &&
8814       ( OP_SYMBOL(result)->liveTo > ic->seq ||
8815       ic->depth )) {
8816       int size = AOP_SIZE(right) - 1;
8817       while (size--)
8818         pic14_emitcode("dec","%s",rname);
8819     }
8820   }
8821   
8822   /* done */
8823   freeAsmop(right,NULL,ic,TRUE);
8824   
8825   
8826 }
8827
8828 /*-----------------------------------------------------------------*/
8829 /* genFarPointerSet - set value from far space                     */
8830 /*-----------------------------------------------------------------*/
8831 static void genFarPointerSet (operand *right,
8832                 operand *result, iCode *ic)
8833 {
8834   int size, offset ;
8835   sym_link *retype = getSpec(operandType(right));
8836   
8837   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8838   aopOp(result,ic,FALSE);
8839   
8840   /* if the operand is already in dptr 
8841   then we do nothing else we move the value to dptr */
8842   if (AOP_TYPE(result) != AOP_STR) {
8843     /* if this is remateriazable */
8844     if (AOP_TYPE(result) == AOP_IMMD)
8845       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8846     else { /* we need to get it byte by byte */
8847       pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8848       pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8849       if (options.model == MODEL_FLAT24)
8850       {
8851         pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8852       }
8853     }
8854   }
8855   /* so dptr know contains the address */
8856   freeAsmop(result,NULL,ic,TRUE);
8857   aopOp(right,ic,FALSE);
8858   
8859   /* if bit then unpack */
8860   if (IS_BITFIELD(retype)) 
8861     genPackBits(retype,right,"dptr",FPOINTER);
8862   else {
8863     size = AOP_SIZE(right);
8864     offset = 0 ;
8865     
8866     while (size--) {
8867       char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8868       MOVA(l);
8869       pic14_emitcode("movx","@dptr,a");
8870       if (size)
8871         pic14_emitcode("inc","dptr");
8872     }
8873   }
8874   
8875   freeAsmop(right,NULL,ic,TRUE);
8876 }
8877
8878 /*-----------------------------------------------------------------*/
8879 /* genGenPointerSet - set value from generic pointer space         */
8880 /*-----------------------------------------------------------------*/
8881 static void genGenPointerSet (operand *right,
8882                 operand *result, iCode *ic)
8883 {
8884   int size, offset ;
8885   sym_link *retype = getSpec(operandType(right));
8886   
8887   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8888   
8889   aopOp(result,ic,FALSE);
8890   aopOp(right,ic,FALSE);
8891   size = AOP_SIZE(right);
8892   
8893   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8894   
8895   /* if the operand is already in dptr 
8896   then we do nothing else we move the value to dptr */
8897   if (AOP_TYPE(result) != AOP_STR) {
8898     /* if this is remateriazable */
8899     if (AOP_TYPE(result) == AOP_IMMD) {
8900       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8901       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8902     }
8903     else { /* we need to get it byte by byte */
8904       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8905       size = AOP_SIZE(right);
8906       offset = 0 ;
8907       
8908       /* hack hack! see if this the FSR. If so don't load W */
8909       if(AOP_TYPE(right) != AOP_ACC) {
8910         
8911         
8912         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8913         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8914         
8915         if(AOP_SIZE(result) > 1) {
8916           emitpcode(POC_BCF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8917           emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8918           emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8919           
8920         }
8921         
8922         //if(size==2)
8923         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8924         //if(size==4) {
8925         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8926         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8927         //}
8928         
8929         while(size--) {
8930           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
8931           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8932           
8933           if(size)
8934             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8935         }
8936         
8937         
8938         goto release;
8939       } 
8940       
8941       if(aopIdx(AOP(result),0) != 4) {
8942         
8943         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8944         goto release;
8945       }
8946       
8947       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8948       goto release;
8949       
8950     }
8951   }
8952   /* so dptr know contains the address */
8953   
8954   
8955   /* if bit then unpack */
8956   if (IS_BITFIELD(retype)) 
8957     genPackBits(retype,right,"dptr",GPOINTER);
8958   else {
8959     size = AOP_SIZE(right);
8960     offset = 0 ;
8961     
8962     DEBUGpic14_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
8963     
8964     while (size--) {
8965       
8966       emitpcode(POC_MOVFW,popGet(AOP(result),offset));
8967       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8968       
8969       if (AOP_TYPE(right) == AOP_LIT) 
8970         emitpcode(POC_MOVLW, popGet(AOP(right),offset));
8971       else
8972         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8973       
8974       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8975       
8976       offset++;
8977     }
8978   }
8979   
8980 release:
8981   freeAsmop(right,NULL,ic,TRUE);
8982   freeAsmop(result,NULL,ic,TRUE);
8983 }
8984
8985 /*-----------------------------------------------------------------*/
8986 /* genPointerSet - stores the value into a pointer location        */
8987 /*-----------------------------------------------------------------*/
8988 static void genPointerSet (iCode *ic)
8989 {    
8990   operand *right, *result ;
8991   sym_link *type, *etype;
8992   int p_type;
8993   
8994   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8995   
8996   right = IC_RIGHT(ic);
8997   result = IC_RESULT(ic) ;
8998   
8999   /* depending on the type of pointer we need to
9000   move it to the correct pointer register */
9001   type = operandType(result);
9002   etype = getSpec(type);
9003   /* if left is of type of pointer then it is simple */
9004   if (IS_PTR(type) && !IS_FUNC(type->next)) {
9005     p_type = DCL_TYPE(type);
9006   }
9007   else {
9008     /* we have to go by the storage class */
9009     p_type = PTR_TYPE(SPEC_OCLS(etype));
9010     
9011     /*  if (SPEC_OCLS(etype)->codesp ) { */
9012     /*      p_type = CPOINTER ;  */
9013     /*  } */
9014     /*  else */
9015     /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9016     /*    p_type = FPOINTER ; */
9017     /*      else */
9018     /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9019     /*        p_type = PPOINTER ; */
9020     /*    else */
9021     /*        if (SPEC_OCLS(etype) == idata ) */
9022     /*      p_type = IPOINTER ; */
9023     /*        else */
9024     /*      p_type = POINTER ; */
9025   }
9026   
9027   /* now that we have the pointer type we assign
9028   the pointer values */
9029   switch (p_type) {
9030     
9031   case POINTER:
9032   case IPOINTER:
9033     genNearPointerSet (right,result,ic);
9034     break;
9035     
9036   case PPOINTER:
9037     genPagedPointerSet (right,result,ic);
9038     break;
9039     
9040   case FPOINTER:
9041     genFarPointerSet (right,result,ic);
9042     break;
9043     
9044   case GPOINTER:
9045     genGenPointerSet (right,result,ic);
9046     break;
9047     
9048   default:
9049     werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9050       "genPointerSet: illegal pointer type");
9051   }
9052 }
9053
9054 /*-----------------------------------------------------------------*/
9055 /* genIfx - generate code for Ifx statement                        */
9056 /*-----------------------------------------------------------------*/
9057 static void genIfx (iCode *ic, iCode *popIc)
9058 {
9059   operand *cond = IC_COND(ic);
9060   int isbit =0;
9061   
9062   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9063   
9064   aopOp(cond,ic,FALSE);
9065   
9066   /* get the value into acc */
9067   if (AOP_TYPE(cond) != AOP_CRY)
9068     pic14_toBoolean(cond);
9069   else
9070     isbit = 1;
9071   /* the result is now in the accumulator */
9072   freeAsmop(cond,NULL,ic,TRUE);
9073   
9074   /* if there was something to be popped then do it */
9075   if (popIc)
9076     genIpop(popIc);
9077   
9078   /* if the condition is  a bit variable */
9079   if (isbit && IS_ITEMP(cond) && 
9080     SPIL_LOC(cond)) {
9081     genIfxJump(ic,SPIL_LOC(cond)->rname);
9082     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9083   }
9084   else {
9085     if (isbit && !IS_ITEMP(cond))
9086       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9087     else
9088       genIfxJump(ic,"a");
9089   }
9090   ic->generated = 1;
9091   
9092 }
9093
9094 /*-----------------------------------------------------------------*/
9095 /* genAddrOf - generates code for address of                       */
9096 /*-----------------------------------------------------------------*/
9097 static void genAddrOf (iCode *ic)
9098 {
9099   operand *right, *result, *left;
9100   int size, offset ;
9101   
9102   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9103   
9104   
9105   //aopOp(IC_RESULT(ic),ic,FALSE);
9106   
9107   aopOp((left=IC_LEFT(ic)),ic,FALSE);
9108   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9109   aopOp((result=IC_RESULT(ic)),ic,TRUE);
9110   
9111   DEBUGpic14_AopType(__LINE__,left,right,result);
9112   
9113   size = AOP_SIZE(IC_RESULT(ic));
9114   offset = 0;
9115   
9116   while (size--) {
9117     /* fixing bug #863624, reported from (errolv) */
9118     emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9119     emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9120     
9121 #if 0
9122     emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9123     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9124 #endif
9125     offset++;
9126   }
9127   
9128   freeAsmop(left,NULL,ic,FALSE);
9129   freeAsmop(result,NULL,ic,TRUE);
9130   
9131 }
9132
9133 #if 0
9134 /*-----------------------------------------------------------------*/
9135 /* genFarFarAssign - assignment when both are in far space         */
9136 /*-----------------------------------------------------------------*/
9137 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9138 {
9139   int size = AOP_SIZE(right);
9140   int offset = 0;
9141   char *l ;
9142   /* first push the right side on to the stack */
9143   while (size--) {
9144     l = aopGet(AOP(right),offset++,FALSE,FALSE);
9145     MOVA(l);
9146     pic14_emitcode ("push","acc");
9147   }
9148   
9149   freeAsmop(right,NULL,ic,FALSE);
9150   /* now assign DPTR to result */
9151   aopOp(result,ic,FALSE);
9152   size = AOP_SIZE(result);
9153   while (size--) {
9154     pic14_emitcode ("pop","acc");
9155     aopPut(AOP(result),"a",--offset);
9156   }
9157   freeAsmop(result,NULL,ic,FALSE);
9158   
9159 }
9160 #endif
9161
9162 /*-----------------------------------------------------------------*/
9163 /* genAssign - generate code for assignment                        */
9164 /*-----------------------------------------------------------------*/
9165 static void genAssign (iCode *ic)
9166 {
9167   operand *result, *right;
9168   int size, offset,know_W;
9169   unsigned long lit = 0L;
9170   
9171   result = IC_RESULT(ic);
9172   right  = IC_RIGHT(ic) ;
9173   
9174   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9175   
9176   /* if they are the same */
9177   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9178     return ;
9179   
9180   aopOp(right,ic,FALSE);
9181   aopOp(result,ic,TRUE);
9182   
9183   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9184   
9185   /* if they are the same registers */
9186   if (pic14_sameRegs(AOP(right),AOP(result)))
9187     goto release;
9188   
9189   /* if the result is a bit */
9190   if (AOP_TYPE(result) == AOP_CRY) {
9191     
9192   /* if the right size is a literal then
9193     we know what the value is */
9194     if (AOP_TYPE(right) == AOP_LIT) {
9195       
9196       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9197         popGet(AOP(result),0));
9198       
9199       if (((int) operandLitValue(right))) 
9200         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9201         AOP(result)->aopu.aop_dir,
9202         AOP(result)->aopu.aop_dir);
9203       else
9204         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9205         AOP(result)->aopu.aop_dir,
9206         AOP(result)->aopu.aop_dir);
9207       goto release;
9208     }
9209     
9210     /* the right is also a bit variable */
9211     if (AOP_TYPE(right) == AOP_CRY) {
9212       emitpcode(POC_BCF,    popGet(AOP(result),0));
9213       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9214       emitpcode(POC_BSF,    popGet(AOP(result),0));
9215       
9216       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9217         AOP(result)->aopu.aop_dir,
9218         AOP(result)->aopu.aop_dir);
9219       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9220         AOP(right)->aopu.aop_dir,
9221         AOP(right)->aopu.aop_dir);
9222       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9223         AOP(result)->aopu.aop_dir,
9224         AOP(result)->aopu.aop_dir);
9225       goto release ;
9226     }
9227     
9228     /* we need to or */
9229     emitpcode(POC_BCF,    popGet(AOP(result),0));
9230     pic14_toBoolean(right);
9231     emitSKPZ;
9232     emitpcode(POC_BSF,    popGet(AOP(result),0));
9233     //aopPut(AOP(result),"a",0);
9234     goto release ;
9235   }
9236   
9237   /* bit variables done */
9238   /* general case */
9239   size = AOP_SIZE(result);
9240   offset = 0 ;
9241   if(AOP_TYPE(right) == AOP_LIT)
9242     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9243   
9244   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9245     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9246     if(aopIdx(AOP(result),0) == 4) {
9247       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9248       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9249       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9250       goto release;
9251     } else
9252       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9253   }
9254   
9255   know_W=-1;
9256   while (size--) {
9257     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9258     if(AOP_TYPE(right) == AOP_LIT) {
9259       if(lit&0xff) {
9260         if(know_W != (int)(lit&0xff))
9261           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9262         know_W = lit&0xff;
9263         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9264       } else
9265         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9266       
9267       lit >>= 8;
9268       
9269     } else if (AOP_TYPE(right) == AOP_CRY) {
9270       emitpcode(POC_CLRF, popGet(AOP(result),offset));
9271       if(offset == 0) {
9272         emitpcode(POC_BTFSS, popGet(AOP(right),0));
9273         emitpcode(POC_INCF, popGet(AOP(result),0));
9274       }
9275     } else {
9276       mov2w (AOP(right), offset);
9277       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9278     }
9279     
9280     offset++;
9281   }
9282   
9283   
9284 release:
9285   freeAsmop (right,NULL,ic,FALSE);
9286   freeAsmop (result,NULL,ic,TRUE);
9287 }   
9288
9289 /*-----------------------------------------------------------------*/
9290 /* genJumpTab - genrates code for jump table                       */
9291 /*-----------------------------------------------------------------*/
9292 static void genJumpTab (iCode *ic)
9293 {
9294   symbol *jtab;
9295   char *l;
9296   
9297   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9298   
9299   aopOp(IC_JTCOND(ic),ic,FALSE);
9300   /* get the condition into accumulator */
9301   l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9302   MOVA(l);
9303   /* multiply by three */
9304   pic14_emitcode("add","a,acc");
9305   pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9306   
9307   jtab = newiTempLabel(NULL);
9308   pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9309   pic14_emitcode("jmp","@a+dptr");
9310   pic14_emitcode("","%05d_DS_:",jtab->key+100);
9311   
9312   emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
9313   emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
9314   emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9315   emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9316   emitSKPNC;
9317   emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9318   emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9319   emitpLabel(jtab->key);
9320   
9321   freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9322   
9323   /* now generate the jump labels */
9324   for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9325   jtab = setNextItem(IC_JTLABELS(ic))) {
9326     pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9327     emitpcode(POC_GOTO,popGetLabel(jtab->key));
9328     
9329   }
9330   
9331 }
9332
9333 /*-----------------------------------------------------------------*/
9334 /* genMixedOperation - gen code for operators between mixed types  */
9335 /*-----------------------------------------------------------------*/
9336 /*
9337 TSD - Written for the PIC port - but this unfortunately is buggy.
9338 This routine is good in that it is able to efficiently promote 
9339 types to different (larger) sizes. Unfortunately, the temporary
9340 variables that are optimized out by this routine are sometimes
9341 used in other places. So until I know how to really parse the 
9342 iCode tree, I'm going to not be using this routine :(.
9343 */
9344 static int genMixedOperation (iCode *ic)
9345 {
9346 #if 0
9347   operand *result = IC_RESULT(ic);
9348   sym_link *ctype = operandType(IC_LEFT(ic));
9349   operand *right = IC_RIGHT(ic);
9350   int ret = 0;
9351   int big,small;
9352   int offset;
9353   
9354   iCode *nextic;
9355   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9356   
9357   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9358   
9359   nextic = ic->next;
9360   if(!nextic)
9361     return 0;
9362   
9363   nextright = IC_RIGHT(nextic);
9364   nextleft  = IC_LEFT(nextic);
9365   nextresult = IC_RESULT(nextic);
9366   
9367   aopOp(right,ic,FALSE);
9368   aopOp(result,ic,FALSE);
9369   aopOp(nextright,  nextic, FALSE);
9370   aopOp(nextleft,   nextic, FALSE);
9371   aopOp(nextresult, nextic, FALSE);
9372   
9373   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9374     
9375     operand *t = right;
9376     right = nextright;
9377     nextright = t; 
9378     
9379     pic14_emitcode(";remove right +","");
9380     
9381   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9382   /*
9383   operand *t = right;
9384   right = nextleft;
9385   nextleft = t; 
9386     */
9387     pic14_emitcode(";remove left +","");
9388   } else
9389     return 0;
9390   
9391   big = AOP_SIZE(nextleft);
9392   small = AOP_SIZE(nextright);
9393   
9394   switch(nextic->op) {
9395     
9396   case '+':
9397     pic14_emitcode(";optimize a +","");
9398     /* if unsigned or not an integral type */
9399     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9400       pic14_emitcode(";add a bit to something","");
9401     } else {
9402       
9403       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9404       
9405       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9406         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9407         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9408       } else
9409         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9410       
9411       offset = 0;
9412       while(--big) {
9413         
9414         offset++;
9415         
9416         if(--small) {
9417           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9418             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9419             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9420           }
9421           
9422           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9423           emitSKPNC;
9424           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9425             AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9426             AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9427           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9428           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9429           
9430         } else {
9431           pic14_emitcode("rlf","known_zero,w");
9432           
9433           /*
9434           if right is signed
9435           btfsc  right,7
9436           addlw ff
9437           */
9438           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9439             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9440             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9441           } else {
9442             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9443           }
9444         }
9445       }
9446       ret = 1;
9447     }
9448   }
9449   ret = 1;
9450   
9451 release:
9452   freeAsmop(right,NULL,ic,TRUE);
9453   freeAsmop(result,NULL,ic,TRUE);
9454   freeAsmop(nextright,NULL,ic,TRUE);
9455   freeAsmop(nextleft,NULL,ic,TRUE);
9456   if(ret)
9457     nextic->generated = 1;
9458   
9459   return ret;
9460 #else
9461   return 0;
9462 #endif
9463 }
9464 /*-----------------------------------------------------------------*/
9465 /* genCast - gen code for casting                                  */
9466 /*-----------------------------------------------------------------*/
9467 static void genCast (iCode *ic)
9468 {
9469   operand *result = IC_RESULT(ic);
9470   sym_link *ctype = operandType(IC_LEFT(ic));
9471   sym_link *rtype = operandType(IC_RIGHT(ic));
9472   operand *right = IC_RIGHT(ic);
9473   int size, offset ;
9474   
9475   DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9476   /* if they are equivalent then do nothing */
9477   if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9478     return ;
9479   
9480   aopOp(right,ic,FALSE) ;
9481   aopOp(result,ic,FALSE);
9482   
9483   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9484   
9485   /* if the result is a bit */
9486   if (AOP_TYPE(result) == AOP_CRY) {
9487   /* if the right size is a literal then
9488     we know what the value is */
9489     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9490     if (AOP_TYPE(right) == AOP_LIT) {
9491       
9492       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9493         popGet(AOP(result),0));
9494       
9495       if (((int) operandLitValue(right))) 
9496         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9497         AOP(result)->aopu.aop_dir,
9498         AOP(result)->aopu.aop_dir);
9499       else
9500         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9501         AOP(result)->aopu.aop_dir,
9502         AOP(result)->aopu.aop_dir);
9503       
9504       goto release;
9505     }
9506     
9507     /* the right is also a bit variable */
9508     if (AOP_TYPE(right) == AOP_CRY) {
9509       
9510       emitCLRC;
9511       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9512       
9513       pic14_emitcode("clrc","");
9514       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9515         AOP(right)->aopu.aop_dir,
9516         AOP(right)->aopu.aop_dir);
9517       aopPut(AOP(result),"c",0);
9518       goto release ;
9519     }
9520     
9521     /* we need to or */
9522     if (AOP_TYPE(right) == AOP_REG) {
9523       emitpcode(POC_BCF,    popGet(AOP(result),0));
9524       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9525       emitpcode(POC_BSF,    popGet(AOP(result),0));
9526     }
9527     pic14_toBoolean(right);
9528     aopPut(AOP(result),"a",0);
9529     goto release ;
9530   }
9531   
9532   if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9533     int offset = 1;
9534     size = AOP_SIZE(result);
9535     
9536     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9537     
9538     emitpcode(POC_CLRF,   popGet(AOP(result),0));
9539     emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9540     emitpcode(POC_INCF,   popGet(AOP(result),0));
9541     
9542     while (size--)
9543       emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9544     
9545     goto release;
9546   }
9547   
9548   /* if they are the same size : or less */
9549   if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9550     
9551     /* if they are in the same place */
9552     if (pic14_sameRegs(AOP(right),AOP(result)))
9553       goto release;
9554     
9555     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9556     if (IS_PTR_CONST(rtype))
9557       DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9558     if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9559       DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9560     
9561     if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9562       emitpcode(POC_MOVLW, popGet(AOP(right),0));
9563       emitpcode(POC_MOVWF, popGet(AOP(result),0));
9564       emitpcode(POC_MOVLW, popGet(AOP(right),1));
9565       emitpcode(POC_MOVWF, popGet(AOP(result),1));
9566       if(AOP_SIZE(result) <2)
9567         fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9568       
9569     } else {
9570       
9571       /* if they in different places then copy */
9572       size = AOP_SIZE(result);
9573       offset = 0 ;
9574       while (size--) {
9575         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9576         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9577         
9578         //aopPut(AOP(result),
9579         // aopGet(AOP(right),offset,FALSE,FALSE),
9580         // offset);
9581         
9582         offset++;
9583       }
9584     }
9585     goto release;
9586   }
9587   
9588   
9589   /* if the result is of type pointer */
9590   if (IS_PTR(ctype)) {
9591     
9592     int p_type;
9593     sym_link *type = operandType(right);
9594     sym_link *etype = getSpec(type);
9595     DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9596     
9597     /* pointer to generic pointer */
9598     if (IS_GENPTR(ctype)) {
9599       char *l = zero;
9600       
9601       if (IS_PTR(type)) 
9602         p_type = DCL_TYPE(type);
9603       else {
9604         /* we have to go by the storage class */
9605         p_type = PTR_TYPE(SPEC_OCLS(etype));
9606         
9607         /*    if (SPEC_OCLS(etype)->codesp )  */
9608         /*        p_type = CPOINTER ;  */
9609         /*    else */
9610         /*        if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9611         /*      p_type = FPOINTER ; */
9612         /*        else */
9613         /*      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9614         /*          p_type = PPOINTER; */
9615         /*      else */
9616         /*          if (SPEC_OCLS(etype) == idata ) */
9617         /*        p_type = IPOINTER ; */
9618         /*          else */
9619         /*        p_type = POINTER ; */
9620       }
9621       
9622       /* the first two bytes are known */
9623       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9624       size = GPTRSIZE - 1; 
9625       offset = 0 ;
9626       while (size--) {
9627         if(offset < AOP_SIZE(right)) {
9628           DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9629           if ((AOP_TYPE(right) == AOP_PCODE) && 
9630             AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9631             emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9632             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9633           } else { 
9634             aopPut(AOP(result),
9635               aopGet(AOP(right),offset,FALSE,FALSE),
9636               offset);
9637           }
9638         } else 
9639           emitpcode(POC_CLRF,popGet(AOP(result),offset));
9640         offset++;
9641       }
9642       /* the last byte depending on type */
9643       switch (p_type) {
9644       case IPOINTER:
9645       case POINTER:
9646         emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9647         break;
9648       case FPOINTER:
9649         pic14_emitcode(";BUG!? ","%d",__LINE__);
9650         l = one;
9651         break;
9652       case CPOINTER:
9653         pic14_emitcode(";BUG!? ","%d",__LINE__);
9654         l = "#0x02";
9655         break;        
9656       case PPOINTER:
9657         pic14_emitcode(";BUG!? ","%d",__LINE__);
9658         l = "#0x03";
9659         break;
9660         
9661       default:
9662         /* this should never happen */
9663         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9664           "got unknown pointer type");
9665         exit(1);
9666       }
9667       //aopPut(AOP(result),l, GPTRSIZE - 1);      
9668       goto release ;
9669     }
9670     
9671     /* just copy the pointers */
9672     size = AOP_SIZE(result);
9673     offset = 0 ;
9674     while (size--) {
9675       aopPut(AOP(result),
9676         aopGet(AOP(right),offset,FALSE,FALSE),
9677         offset);
9678       offset++;
9679     }
9680     goto release ;
9681   }
9682   
9683   
9684   
9685   /* so we now know that the size of destination is greater
9686   than the size of the source.
9687   Now, if the next iCode is an operator then we might be
9688   able to optimize the operation without performing a cast.
9689   */
9690   if(genMixedOperation(ic))
9691     goto release;
9692   
9693   DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9694   
9695   /* we move to result for the size of source */
9696   size = AOP_SIZE(right);
9697   offset = 0 ;
9698   while (size--) {
9699     emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9700     emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9701     offset++;
9702   }
9703   
9704   /* now depending on the sign of the destination */
9705   size = AOP_SIZE(result) - AOP_SIZE(right);
9706   /* if unsigned or not an integral type */
9707   if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9708     while (size--)
9709       emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9710   } else {
9711     /* we need to extend the sign :{ */
9712     
9713     if(size == 1) {
9714       /* Save one instruction of casting char to int */
9715       emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9716       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9717       emitpcode(POC_DECF,   popGet(AOP(result),offset));
9718     } else {
9719       emitpcodeNULLop(POC_CLRW);
9720       
9721       if(offset)
9722         emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9723       else
9724         emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9725       
9726       emitpcode(POC_MOVLW,   popGetLit(0xff));
9727       
9728       while (size--)
9729         emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9730     }
9731   }
9732   
9733 release:
9734   freeAsmop(right,NULL,ic,TRUE);
9735   freeAsmop(result,NULL,ic,TRUE);
9736   
9737 }
9738
9739 /*-----------------------------------------------------------------*/
9740 /* genDjnz - generate decrement & jump if not zero instrucion      */
9741 /*-----------------------------------------------------------------*/
9742 static int genDjnz (iCode *ic, iCode *ifx)
9743 {
9744   symbol *lbl, *lbl1;
9745   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9746   
9747   if (!ifx)
9748     return 0;
9749   
9750     /* if the if condition has a false label
9751   then we cannot save */
9752   if (IC_FALSE(ifx))
9753     return 0;
9754   
9755     /* if the minus is not of the form 
9756   a = a - 1 */
9757   if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9758     !IS_OP_LITERAL(IC_RIGHT(ic)))
9759     return 0;
9760   
9761   if (operandLitValue(IC_RIGHT(ic)) != 1)
9762     return 0;
9763   
9764     /* if the size of this greater than one then no
9765   saving */
9766   if (getSize(operandType(IC_RESULT(ic))) > 1)
9767     return 0;
9768   
9769   /* otherwise we can save BIG */
9770   lbl = newiTempLabel(NULL);
9771   lbl1= newiTempLabel(NULL);
9772   
9773   aopOp(IC_RESULT(ic),ic,FALSE);
9774   
9775   if (IS_AOP_PREG(IC_RESULT(ic))) {
9776     pic14_emitcode("dec","%s",
9777       aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9778     pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9779     pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9780   } else {  
9781     
9782     
9783     emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9784     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9785     
9786     pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9787     pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9788     
9789   }
9790   /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9791   /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9792   /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9793   /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9794   
9795   
9796   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9797   ifx->generated = 1;
9798   return 1;
9799 }
9800
9801 /*-----------------------------------------------------------------*/
9802 /* genReceive - generate code for a receive iCode                  */
9803 /*-----------------------------------------------------------------*/
9804 static void genReceive (iCode *ic)
9805 {
9806   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9807   
9808   if (isOperandInFarSpace(IC_RESULT(ic)) &&
9809     ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9810     IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9811     
9812     int size = getSize(operandType(IC_RESULT(ic)));
9813     int offset =  fReturnSizePic - size;
9814     while (size--) {
9815       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9816         fReturn[fReturnSizePic - offset - 1] : "acc"));
9817       offset++;
9818     }
9819     aopOp(IC_RESULT(ic),ic,FALSE);
9820     size = AOP_SIZE(IC_RESULT(ic));
9821     offset = 0;
9822     while (size--) {
9823       pic14_emitcode ("pop","acc");
9824       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9825     }
9826     
9827   } else {
9828     _G.accInUse++;
9829     aopOp(IC_RESULT(ic),ic,FALSE);
9830     _G.accInUse--;
9831     assignResultValue(IC_RESULT(ic));
9832   }
9833   
9834   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9835 }
9836
9837 /*-----------------------------------------------------------------*/
9838 /* genDummyRead - generate code for dummy read of volatiles        */
9839 /*-----------------------------------------------------------------*/
9840 static void
9841 genDummyRead (iCode * ic)
9842 {
9843   pic14_emitcode ("; genDummyRead","");
9844   pic14_emitcode ("; not implemented","");
9845   
9846   ic = ic;
9847 }
9848
9849 /*-----------------------------------------------------------------*/
9850 /* genpic14Code - generate code for pic14 based controllers        */
9851 /*-----------------------------------------------------------------*/
9852 /*
9853 * At this point, ralloc.c has gone through the iCode and attempted
9854 * to optimize in a way suitable for a PIC. Now we've got to generate
9855 * PIC instructions that correspond to the iCode.
9856 *
9857 * Once the instructions are generated, we'll pass through both the
9858 * peep hole optimizer and the pCode optimizer.
9859 *-----------------------------------------------------------------*/
9860
9861 void genpic14Code (iCode *lic)
9862 {
9863   iCode *ic;
9864   int cln = 0;
9865   
9866   lineHead = lineCurr = NULL;
9867   
9868   pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9869   addpBlock(pb);
9870   
9871   /* if debug information required */
9872   if (options.debug && currFunc) { 
9873     if (currFunc) {
9874       debugFile->writeFunction (currFunc, lic);
9875     }
9876   }
9877   
9878   
9879   for (ic = lic ; ic ; ic = ic->next ) {
9880     
9881     DEBUGpic14_emitcode(";ic","");
9882     if ( cln != ic->lineno ) {
9883       if ( options.debug ) {
9884         debugFile->writeCLine (ic);
9885       }
9886       /*
9887       pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9888       pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9889       printCLine(ic->filename, ic->lineno));
9890       */
9891       if (!options.noCcodeInAsm) {
9892         addpCode2pBlock(pb,
9893           newpCodeCSource(ic->lineno, 
9894           ic->filename, 
9895           printCLine(ic->filename, ic->lineno)));
9896       }
9897       
9898       cln = ic->lineno ;
9899     }
9900     
9901     // if you want printILine too, look at ../mcs51/gen.c, i don't understand this :)
9902     
9903     /* if the result is marked as
9904     spilt and rematerializable or code for
9905     this has already been generated then
9906     do nothing */
9907     if (resultRemat(ic) || ic->generated ) 
9908       continue ;
9909     
9910     /* depending on the operation */
9911     switch (ic->op) {
9912     case '!' :
9913       genNot(ic);
9914       break;
9915       
9916     case '~' :
9917       genCpl(ic);
9918       break;
9919       
9920     case UNARYMINUS:
9921       genUminus (ic);
9922       break;
9923       
9924     case IPUSH:
9925       genIpush (ic);
9926       break;
9927       
9928     case IPOP:
9929     /* IPOP happens only when trying to restore a 
9930     spilt live range, if there is an ifx statement
9931     following this pop then the if statement might
9932     be using some of the registers being popped which
9933     would destory the contents of the register so
9934       we need to check for this condition and handle it */
9935       if (ic->next            && 
9936         ic->next->op == IFX &&
9937         regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9938         genIfx (ic->next,ic);
9939       else
9940         genIpop (ic);
9941       break; 
9942       
9943     case CALL:
9944       genCall (ic);
9945       break;
9946       
9947     case PCALL:
9948       genPcall (ic);
9949       break;
9950       
9951     case FUNCTION:
9952       genFunction (ic);
9953       break;
9954       
9955     case ENDFUNCTION:
9956       genEndFunction (ic);
9957       break;
9958       
9959     case RETURN:
9960       genRet (ic);
9961       break;
9962       
9963     case LABEL:
9964       genLabel (ic);
9965       break;
9966       
9967     case GOTO:
9968       genGoto (ic);
9969       break;
9970       
9971     case '+' :
9972       genPlus (ic) ;
9973       break;
9974       
9975     case '-' :
9976       if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9977         genMinus (ic);
9978       break;
9979       
9980     case '*' :
9981       genMult (ic);
9982       break;
9983       
9984     case '/' :
9985       genDiv (ic) ;
9986       break;
9987       
9988     case '%' :
9989       genMod (ic);
9990       break;
9991       
9992     case '>' :
9993       genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
9994       break;
9995       
9996     case '<' :
9997       genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9998       break;
9999       
10000     case LE_OP:
10001     case GE_OP:
10002     case NE_OP:
10003       
10004     /* note these two are xlated by algebraic equivalence
10005       during parsing SDCC.y */
10006       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10007         "got '>=' or '<=' shouldn't have come here");
10008       break;  
10009       
10010     case EQ_OP:
10011       genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10012       break;      
10013       
10014     case AND_OP:
10015       genAndOp (ic);
10016       break;
10017       
10018     case OR_OP:
10019       genOrOp (ic);
10020       break;
10021       
10022     case '^' :
10023       genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10024       break;
10025       
10026     case '|' :
10027       genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10028       break;
10029       
10030     case BITWISEAND:
10031       genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10032       break;
10033       
10034     case INLINEASM:
10035       genInline (ic);
10036       break;
10037       
10038     case RRC:
10039       genRRC (ic);
10040       break;
10041       
10042     case RLC:
10043       genRLC (ic);
10044       break;
10045       
10046     case GETHBIT:
10047       genGetHbit (ic);
10048       break;
10049       
10050     case LEFT_OP:
10051       genLeftShift (ic);
10052       break;
10053       
10054     case RIGHT_OP:
10055       genRightShift (ic);
10056       break;
10057       
10058     case GET_VALUE_AT_ADDRESS:
10059       genPointerGet(ic);
10060       break;
10061       
10062     case '=' :
10063       if (POINTER_SET(ic))
10064         genPointerSet(ic);
10065       else
10066         genAssign(ic);
10067       break;
10068       
10069     case IFX:
10070       genIfx (ic,NULL);
10071       break;
10072       
10073     case ADDRESS_OF:
10074       genAddrOf (ic);
10075       break;
10076       
10077     case JUMPTABLE:
10078       genJumpTab (ic);
10079       break;
10080       
10081     case CAST:
10082       genCast (ic);
10083       break;
10084       
10085     case RECEIVE:
10086       genReceive(ic);
10087       break;
10088       
10089     case SEND:
10090       addSet(&_G.sendSet,ic);
10091       break;
10092       
10093     case DUMMY_READ_VOLATILE:
10094       genDummyRead (ic);
10095       break;
10096       
10097     default :
10098       ic = ic;
10099     }
10100   }
10101   
10102   
10103   /* now we are ready to call the
10104   peep hole optimizer */
10105   if (!options.nopeep) {
10106     peepHole (&lineHead);
10107   }
10108   /* now do the actual printing */
10109   printLine (lineHead,codeOutFile);
10110   
10111 #ifdef PCODE_DEBUG
10112   DFPRINTF((stderr,"printing pBlock\n\n"));
10113   printpBlock(stdout,pb);
10114 #endif
10115   
10116   return;
10117 }