44f440f804fefd3343d2a1309caec93660e22577
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
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);
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
220   if(pcop)
221     addpCode2pBlock(pb,newpCode(poc,pcop));
222   else
223     DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
224 }
225
226 void emitpcodeNULLop(PIC_OPCODE poc)
227 {
228
229   addpCode2pBlock(pb,newpCode(poc,NULL));
230
231 }
232
233 /*-----------------------------------------------------------------*/
234 /* pic14_emitcode - writes the code into a file : for now it is simple    */
235 /*-----------------------------------------------------------------*/
236 void pic14_emitcode (char *inst,char *fmt, ...)
237 {
238     va_list ap;
239     char lb[INITIAL_INLINEASM];  
240     char *lbp = lb;
241
242     va_start(ap,fmt);   
243
244     if (inst && *inst) {
245         if (fmt && *fmt)
246             sprintf(lb,"%s\t",inst);
247         else
248             sprintf(lb,"%s",inst);
249         vsprintf(lb+(strlen(lb)),fmt,ap);
250     }  else
251         vsprintf(lb,fmt,ap);
252
253     while (isspace(*lbp)) lbp++;
254
255     if (lbp && *lbp) 
256         lineCurr = (lineCurr ?
257                     connectLine(lineCurr,newLineNode(lb)) :
258                     (lineHead = newLineNode(lb)));
259     lineCurr->isInline = _G.inLine;
260     lineCurr->isDebug  = _G.debugLine;
261
262     if(debug_verbose)
263       addpCode2pBlock(pb,newpCodeCharP(lb));
264
265     va_end(ap);
266 }
267
268
269 /*-----------------------------------------------------------------*/
270 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
271 /*-----------------------------------------------------------------*/
272 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
273 {
274     bool r0iu = FALSE , r1iu = FALSE;
275     bool r0ou = FALSE , r1ou = FALSE;
276
277     /* the logic: if r0 & r1 used in the instruction
278     then we are in trouble otherwise */
279
280     /* first check if r0 & r1 are used by this
281     instruction, in which case we are in trouble */
282     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
283         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
284     {
285         goto endOfWorld;      
286     }
287
288     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
289     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
290
291     /* if no usage of r0 then return it */
292     if (!r0iu && !r0ou) {
293         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
294         (*aopp)->type = AOP_R0;
295         
296         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
297     }
298
299     /* if no usage of r1 then return it */
300     if (!r1iu && !r1ou) {
301         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
302         (*aopp)->type = AOP_R1;
303
304         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
305     }    
306
307     /* now we know they both have usage */
308     /* if r0 not used in this instruction */
309     if (!r0iu) {
310         /* push it if not already pushed */
311         if (!_G.r0Pushed) {
312           //pic14_emitcode ("push","%s",
313           //          pic14_regWithIdx(R0_IDX)->dname);
314             _G.r0Pushed++ ;
315         }
316         
317         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
318         (*aopp)->type = AOP_R0;
319
320         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
321     }
322
323     /* if r1 not used then */
324
325     if (!r1iu) {
326         /* push it if not already pushed */
327         if (!_G.r1Pushed) {
328           //pic14_emitcode ("push","%s",
329           //          pic14_regWithIdx(R1_IDX)->dname);
330             _G.r1Pushed++ ;
331         }
332         
333         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
334         (*aopp)->type = AOP_R1;
335         return pic14_regWithIdx(R1_IDX);
336     }
337
338 endOfWorld :
339     /* I said end of world but not quite end of world yet */
340     /* if this is a result then we can push it on the stack*/
341     if (result) {
342         (*aopp)->type = AOP_STK;    
343         return NULL;
344     }
345
346     /* other wise this is true end of the world */
347     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
348            "getFreePtr should never reach here");
349     exit(0);
350 }
351
352 /*-----------------------------------------------------------------*/
353 /* newAsmop - creates a new asmOp                                  */
354 /*-----------------------------------------------------------------*/
355 asmop *newAsmop (short type)
356 {
357     asmop *aop;
358
359     aop = Safe_calloc(1,sizeof(asmop));
360     aop->type = type;
361     return aop;
362 }
363
364 static void genSetDPTR(int n)
365 {
366     if (!n)
367     {
368         pic14_emitcode(";", "Select standard DPTR");
369         pic14_emitcode("mov", "dps, #0x00");
370     }
371     else
372     {
373         pic14_emitcode(";", "Select alternate DPTR");
374         pic14_emitcode("mov", "dps, #0x01");
375     }
376 }
377
378 /*-----------------------------------------------------------------*/
379 /* resolveIfx - converts an iCode ifx into a form more useful for  */
380 /*              generating code                                    */
381 /*-----------------------------------------------------------------*/
382 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
383 {
384   if(!resIfx) 
385     return;
386
387   //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
388
389   resIfx->condition = 1;    /* assume that the ifx is true */
390   resIfx->generated = 0;    /* indicate that the ifx has not been used */
391
392   if(!ifx) {
393     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
394 /*
395     DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
396                         __FUNCTION__,__LINE__,resIfx->lbl->key);
397 */
398   } else {
399     if(IC_TRUE(ifx)) {
400       resIfx->lbl = IC_TRUE(ifx);
401     } else {
402       resIfx->lbl = IC_FALSE(ifx);
403       resIfx->condition = 0;
404     }
405 /*
406     if(IC_TRUE(ifx)) 
407       DEBUGpic14_emitcode("; ***","ifx true is non-null");
408     if(IC_FALSE(ifx)) 
409       DEBUGpic14_emitcode("; ***","ifx false is non-null");
410 */
411   }
412
413   //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
414
415 }
416 /*-----------------------------------------------------------------*/
417 /* pointerCode - returns the code for a pointer type               */
418 /*-----------------------------------------------------------------*/
419 static int pointerCode (sym_link *etype)
420 {
421
422     return PTR_TYPE(SPEC_OCLS(etype));
423
424 }
425
426 /*-----------------------------------------------------------------*/
427 /* aopForSym - for a true symbol                                   */
428 /*-----------------------------------------------------------------*/
429 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
430 {
431     asmop *aop;
432     memmap *space= SPEC_OCLS(sym->etype);
433
434     DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
435     /* if already has one */
436     if (sym->aop)
437         return sym->aop;
438
439     /* assign depending on the storage class */
440     /* if it is on the stack or indirectly addressable */
441     /* space we need to assign either r0 or r1 to it   */    
442     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
443         sym->aop = aop = newAsmop(0);
444         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
445         aop->size = getSize(sym->type);
446
447         /* now assign the address of the variable to 
448         the pointer register */
449         if (aop->type != AOP_STK) {
450
451             if (sym->onStack) {
452                     if ( _G.accInUse )
453                         pic14_emitcode("push","acc");
454
455                     pic14_emitcode("mov","a,_bp");
456                     pic14_emitcode("add","a,#0x%02x",
457                              ((sym->stack < 0) ?
458                               ((char)(sym->stack - _G.nRegsSaved )) :
459                               ((char)sym->stack)) & 0xff);
460                     pic14_emitcode("mov","%s,a",
461                              aop->aopu.aop_ptr->name);
462
463                     if ( _G.accInUse )
464                         pic14_emitcode("pop","acc");
465             } else
466                 pic14_emitcode("mov","%s,#%s",
467                          aop->aopu.aop_ptr->name,
468                          sym->rname);
469             aop->paged = space->paged;
470         } else
471             aop->aopu.aop_stk = sym->stack;
472         return aop;
473     }
474     
475     if (sym->onStack && options.stack10bit)
476     {
477         /* It's on the 10 bit stack, which is located in
478          * far data space.
479          */
480          
481       //DEBUGpic14_emitcode(";","%d",__LINE__);
482
483         if ( _G.accInUse )
484                 pic14_emitcode("push","acc");
485
486         pic14_emitcode("mov","a,_bp");
487         pic14_emitcode("add","a,#0x%02x",
488                  ((sym->stack < 0) ?
489                    ((char)(sym->stack - _G.nRegsSaved )) :
490                    ((char)sym->stack)) & 0xff);
491         
492         genSetDPTR(1);
493         pic14_emitcode ("mov","dpx1,#0x40");
494         pic14_emitcode ("mov","dph1,#0x00");
495         pic14_emitcode ("mov","dpl1, a");
496         genSetDPTR(0);
497         
498         if ( _G.accInUse )
499             pic14_emitcode("pop","acc");
500             
501         sym->aop = aop = newAsmop(AOP_DPTR2);
502         aop->size = getSize(sym->type); 
503         return aop;
504     }
505
506     //DEBUGpic14_emitcode(";","%d",__LINE__);
507     /* if in bit space */
508     if (IN_BITSPACE(space)) {
509         sym->aop = aop = newAsmop (AOP_CRY);
510         aop->aopu.aop_dir = sym->rname ;
511         aop->size = getSize(sym->type);
512         //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
513         return aop;
514     }
515     /* if it is in direct space */
516     if (IN_DIRSPACE(space)) {
517         sym->aop = aop = newAsmop (AOP_DIR);
518         aop->aopu.aop_dir = sym->rname ;
519         aop->size = getSize(sym->type);
520         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
521         return aop;
522     }
523
524     /* special case for a function */
525     if (IS_FUNC(sym->type)) {   
526         sym->aop = aop = newAsmop(AOP_IMMD);    
527         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
528         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
529         strcpy(aop->aopu.aop_immd,sym->rname);
530         aop->size = FPTRSIZE; 
531         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
532         return aop;
533     }
534
535
536     /* only remaining is far space */
537     /* in which case DPTR gets the address */
538     sym->aop = aop = newAsmop(AOP_PCODE);
539
540     aop->aopu.pcop = popGetImmd(sym->rname,0,0);
541     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
542     PCOI(aop->aopu.pcop)->index = 0;
543
544     DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
545                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
546
547     allocDirReg (IC_LEFT(ic));
548
549     aop->size = FPTRSIZE; 
550 /*
551     DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
552     sym->aop = aop = newAsmop(AOP_DPTR);
553     pic14_emitcode ("mov","dptr,#%s", sym->rname);
554     aop->size = getSize(sym->type);
555
556     DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
557 */
558
559     /* if it is in code space */
560     if (IN_CODESPACE(space))
561         aop->code = 1;
562
563     return aop;     
564 }
565
566 /*-----------------------------------------------------------------*/
567 /* aopForRemat - rematerialzes an object                           */
568 /*-----------------------------------------------------------------*/
569 static asmop *aopForRemat (operand *op) // x symbol *sym)
570 {
571   symbol *sym = OP_SYMBOL(op);
572   iCode *ic = NULL;
573   asmop *aop = newAsmop(AOP_PCODE);
574   int val = 0;
575   int offset = 0;
576
577   ic = sym->rematiCode;
578
579   DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
580   if(IS_OP_POINTER(op)) {
581     DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
582   }
583   for (;;) {
584     if (ic->op == '+') {
585       val += (int) operandLitValue(IC_RIGHT(ic));
586     } else if (ic->op == '-') {
587       val -= (int) operandLitValue(IC_RIGHT(ic));
588     } else
589       break;
590         
591     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
592   }
593
594   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
595   aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
596   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
597   PCOI(aop->aopu.pcop)->index = val;
598
599   DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
600                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
601                       val, IS_PTR_CONST(operandType(op)));
602
603   //    DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
604
605   allocDirReg (IC_LEFT(ic));
606
607   return aop;        
608 }
609
610 int aopIdx (asmop *aop, int offset)
611 {
612   if(!aop)
613     return -1;
614
615   if(aop->type !=  AOP_REG)
616     return -2;
617         
618   return aop->aopu.aop_reg[offset]->rIdx;
619
620 }
621 /*-----------------------------------------------------------------*/
622 /* regsInCommon - two operands have some registers in common       */
623 /*-----------------------------------------------------------------*/
624 static bool regsInCommon (operand *op1, operand *op2)
625 {
626     symbol *sym1, *sym2;
627     int i;
628
629     /* if they have registers in common */
630     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
631         return FALSE ;
632
633     sym1 = OP_SYMBOL(op1);
634     sym2 = OP_SYMBOL(op2);
635
636     if (sym1->nRegs == 0 || sym2->nRegs == 0)
637         return FALSE ;
638
639     for (i = 0 ; i < sym1->nRegs ; i++) {
640         int j;
641         if (!sym1->regs[i])
642             continue ;
643
644         for (j = 0 ; j < sym2->nRegs ;j++ ) {
645             if (!sym2->regs[j])
646                 continue ;
647
648             if (sym2->regs[j] == sym1->regs[i])
649                 return TRUE ;
650         }
651     }
652
653     return FALSE ;
654 }
655
656 /*-----------------------------------------------------------------*/
657 /* operandsEqu - equivalent                                        */
658 /*-----------------------------------------------------------------*/
659 static bool operandsEqu ( operand *op1, operand *op2)
660 {
661     symbol *sym1, *sym2;
662
663     /* if they not symbols */
664     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
665         return FALSE;
666
667     sym1 = OP_SYMBOL(op1);
668     sym2 = OP_SYMBOL(op2);
669
670     /* if both are itemps & one is spilt
671        and the other is not then false */
672     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
673         sym1->isspilt != sym2->isspilt )
674         return FALSE ;
675
676     /* if they are the same */
677     if (sym1 == sym2)
678         return TRUE ;
679
680     if (strcmp(sym1->rname,sym2->rname) == 0)
681         return TRUE;
682
683
684     /* if left is a tmp & right is not */
685     if (IS_ITEMP(op1)  && 
686         !IS_ITEMP(op2) &&
687         sym1->isspilt  &&
688         (sym1->usl.spillLoc == sym2))
689         return TRUE;
690
691     if (IS_ITEMP(op2)  && 
692         !IS_ITEMP(op1) &&
693         sym2->isspilt  &&
694         sym1->level > 0 &&
695         (sym2->usl.spillLoc == sym1))
696         return TRUE ;
697
698     return FALSE ;
699 }
700
701 /*-----------------------------------------------------------------*/
702 /* pic14_sameRegs - two asmops have the same registers                   */
703 /*-----------------------------------------------------------------*/
704 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
705 {
706     int i;
707
708     if (aop1 == aop2)
709         return TRUE ;
710
711     if (aop1->type != AOP_REG ||
712         aop2->type != AOP_REG )
713         return FALSE ;
714
715     if (aop1->size != aop2->size )
716         return FALSE ;
717
718     for (i = 0 ; i < aop1->size ; i++ )
719         if (aop1->aopu.aop_reg[i] !=
720             aop2->aopu.aop_reg[i] )
721             return FALSE ;
722
723     return TRUE ;
724 }
725
726 /*-----------------------------------------------------------------*/
727 /* aopOp - allocates an asmop for an operand  :                    */
728 /*-----------------------------------------------------------------*/
729 void aopOp (operand *op, iCode *ic, bool result)
730 {
731     asmop *aop;
732     symbol *sym;
733     int i;
734
735     if (!op)
736         return ;
737
738     //    DEBUGpic14_emitcode(";","%d",__LINE__);
739     /* if this a literal */
740     if (IS_OP_LITERAL(op)) {
741         op->aop = aop = newAsmop(AOP_LIT);
742         aop->aopu.aop_lit = op->operand.valOperand;
743         aop->size = getSize(operandType(op));
744         return;
745     }
746
747     {
748       sym_link *type = operandType(op);
749       if(IS_PTR_CONST(type))
750         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
751     }
752
753     /* if already has a asmop then continue */
754     if (op->aop)
755         return ;
756
757     /* if the underlying symbol has a aop */
758     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
759       DEBUGpic14_emitcode(";","%d",__LINE__);
760         op->aop = OP_SYMBOL(op)->aop;
761         return;
762     }
763
764     /* if this is a true symbol */
765     if (IS_TRUE_SYMOP(op)) {    
766       //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
767       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
768       return ;
769     }
770
771     /* this is a temporary : this has
772     only four choices :
773     a) register
774     b) spillocation
775     c) rematerialize 
776     d) conditional   
777     e) can be a return use only */
778
779     sym = OP_SYMBOL(op);
780
781
782     /* if the type is a conditional */
783     if (sym->regType == REG_CND) {
784         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
785         aop->size = 0;
786         return;
787     }
788
789     /* if it is spilt then two situations
790     a) is rematerialize 
791     b) has a spill location */
792     if (sym->isspilt || sym->nRegs == 0) {
793
794       DEBUGpic14_emitcode(";","%d",__LINE__);
795         /* rematerialize it NOW */
796         if (sym->remat) {
797
798             sym->aop = op->aop = aop =
799                                       aopForRemat (op);
800             aop->size = getSize(sym->type);
801             //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
802             return;
803         }
804
805         if (sym->accuse) {
806             int i;
807             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
808             aop->size = getSize(sym->type);
809             for ( i = 0 ; i < 2 ; i++ )
810                 aop->aopu.aop_str[i] = accUse[i];
811             DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
812             return;  
813         }
814
815         if (sym->ruonly ) {
816           /*
817           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
818           aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
819           //allocDirReg (IC_LEFT(ic));
820           aop->size = getSize(sym->type);
821           */
822
823           unsigned i;
824
825           aop = op->aop = sym->aop = newAsmop(AOP_STR);
826           aop->size = getSize(sym->type);
827           for ( i = 0 ; i < fReturnSizePic ; i++ )
828             aop->aopu.aop_str[i] = fReturn[i];
829
830           DEBUGpic14_emitcode(";","%d",__LINE__);
831           return;
832         }
833
834         /* else spill location  */
835         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
836             /* force a new aop if sizes differ */
837             sym->usl.spillLoc->aop = NULL;
838         }
839         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
840                             __FUNCTION__,__LINE__,
841                             sym->usl.spillLoc->rname,
842                             sym->rname, sym->usl.spillLoc->offset);
843
844         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
845         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
846         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
847                                           getSize(sym->type), 
848                                           sym->usl.spillLoc->offset);
849         aop->size = getSize(sym->type);
850
851         return;
852     }
853
854     {
855       sym_link *type = operandType(op);
856       if(IS_PTR_CONST(type)) 
857         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
858     }
859
860     /* must be in a register */
861     DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
862     sym->aop = op->aop = aop = newAsmop(AOP_REG);
863     aop->size = sym->nRegs;
864     for ( i = 0 ; i < sym->nRegs ;i++)
865         aop->aopu.aop_reg[i] = sym->regs[i];
866 }
867
868 /*-----------------------------------------------------------------*/
869 /* freeAsmop - free up the asmop given to an operand               */
870 /*----------------------------------------------------------------*/
871 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
872 {   
873     asmop *aop ;
874
875     if (!op)
876         aop = aaop;
877     else 
878         aop = op->aop;
879
880     if (!aop)
881         return ;
882
883     if (aop->freed)
884         goto dealloc; 
885
886     aop->freed = 1;
887
888     /* depending on the asmop type only three cases need work AOP_RO
889        , AOP_R1 && AOP_STK */
890 #if 0
891     switch (aop->type) {
892         case AOP_R0 :
893             if (_G.r0Pushed ) {
894                 if (pop) {
895                     pic14_emitcode ("pop","ar0");     
896                     _G.r0Pushed--;
897                 }
898             }
899             bitVectUnSetBit(ic->rUsed,R0_IDX);
900             break;
901
902         case AOP_R1 :
903             if (_G.r1Pushed ) {
904                 if (pop) {
905                     pic14_emitcode ("pop","ar1");
906                     _G.r1Pushed--;
907                 }
908             }
909             bitVectUnSetBit(ic->rUsed,R1_IDX);          
910             break;
911
912         case AOP_STK :
913         {
914             int sz = aop->size;    
915             int stk = aop->aopu.aop_stk + aop->size;
916             bitVectUnSetBit(ic->rUsed,R0_IDX);
917             bitVectUnSetBit(ic->rUsed,R1_IDX);          
918
919             getFreePtr(ic,&aop,FALSE);
920             
921             if (options.stack10bit)
922             {
923                 /* I'm not sure what to do here yet... */
924                 /* #STUB */
925                 fprintf(stderr, 
926                         "*** Warning: probably generating bad code for "
927                         "10 bit stack mode.\n");
928             }
929             
930             if (stk) {
931                 pic14_emitcode ("mov","a,_bp");
932                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
933                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
934             } else {
935                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
936             }
937
938             while (sz--) {
939                 pic14_emitcode("pop","acc");
940                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
941                 if (!sz) break;
942                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
943             }
944             op->aop = aop;
945             freeAsmop(op,NULL,ic,TRUE);
946             if (_G.r0Pushed) {
947                 pic14_emitcode("pop","ar0");
948                 _G.r0Pushed--;
949             }
950
951             if (_G.r1Pushed) {
952                 pic14_emitcode("pop","ar1");
953                 _G.r1Pushed--;
954             }       
955         }
956     }
957 #endif
958
959 dealloc:
960     /* all other cases just dealloc */
961     if (op ) {
962         op->aop = NULL;
963         if (IS_SYMOP(op)) {
964             OP_SYMBOL(op)->aop = NULL;    
965             /* if the symbol has a spill */
966             if (SPIL_LOC(op))
967                 SPIL_LOC(op)->aop = NULL;
968         }
969     }
970 }
971
972 /*-----------------------------------------------------------------*/
973 /* aopGet - for fetching value of the aop                          */
974 /*-----------------------------------------------------------------*/
975 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
976 {
977     char *s = buffer ;
978     char *rs;
979
980     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
981     /* offset is greater than
982     size then zero */
983     if (offset > (aop->size - 1) &&
984         aop->type != AOP_LIT)
985         return zero;
986
987     /* depending on type */
988     switch (aop->type) {
989         
990     case AOP_R0:
991     case AOP_R1:
992         DEBUGpic14_emitcode(";","%d",__LINE__);
993         /* if we need to increment it */       
994         while (offset > aop->coff) {        
995             pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
996             aop->coff++;
997         }
998         
999         while (offset < aop->coff) {
1000             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1001             aop->coff--;
1002         }
1003         
1004         aop->coff = offset ;
1005         if (aop->paged) {
1006             pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1007             return (dname ? "acc" : "a");
1008         }       
1009         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1010         rs = Safe_calloc(1,strlen(s)+1);
1011         strcpy(rs,s);   
1012         return rs;
1013         
1014     case AOP_DPTR:
1015     case AOP_DPTR2:
1016         DEBUGpic14_emitcode(";","%d",__LINE__);
1017     if (aop->type == AOP_DPTR2)
1018     {
1019         genSetDPTR(1);
1020     }
1021     
1022         while (offset > aop->coff) {
1023             pic14_emitcode ("inc","dptr");
1024             aop->coff++;
1025         }
1026         
1027         while (offset < aop->coff) {        
1028             pic14_emitcode("lcall","__decdptr");
1029             aop->coff--;
1030         }
1031         
1032         aop->coff = offset;
1033         if (aop->code) {
1034             pic14_emitcode("clr","a");
1035             pic14_emitcode("movc","a,@a+dptr");
1036         }
1037     else {
1038             pic14_emitcode("movx","a,@dptr");
1039     }
1040             
1041     if (aop->type == AOP_DPTR2)
1042     {
1043         genSetDPTR(0);
1044     }
1045             
1046     return (dname ? "acc" : "a");
1047         
1048         
1049     case AOP_IMMD:
1050         if (bit16) 
1051             sprintf (s,"%s",aop->aopu.aop_immd);
1052         else
1053             if (offset) 
1054                 sprintf(s,"(%s >> %d)",
1055                         aop->aopu.aop_immd,
1056                         offset*8);
1057             else
1058                 sprintf(s,"%s",
1059                         aop->aopu.aop_immd);
1060         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1061         rs = Safe_calloc(1,strlen(s)+1);
1062         strcpy(rs,s);   
1063         return rs;
1064         
1065     case AOP_DIR:
1066       if (offset) {
1067         sprintf(s,"(%s + %d)",
1068                 aop->aopu.aop_dir,
1069                 offset);
1070         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1071       } else
1072             sprintf(s,"%s",aop->aopu.aop_dir);
1073         rs = Safe_calloc(1,strlen(s)+1);
1074         strcpy(rs,s);   
1075         return rs;
1076         
1077     case AOP_REG:
1078       //if (dname) 
1079       //    return aop->aopu.aop_reg[offset]->dname;
1080       //else
1081             return aop->aopu.aop_reg[offset]->name;
1082         
1083     case AOP_CRY:
1084       //pic14_emitcode(";","%d",__LINE__);
1085       return aop->aopu.aop_dir;
1086         
1087     case AOP_ACC:
1088         DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1089         return "AOP_accumulator_bug";
1090
1091     case AOP_LIT:
1092         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1093         rs = Safe_calloc(1,strlen(s)+1);
1094         strcpy(rs,s);   
1095         return rs;
1096         
1097     case AOP_STR:
1098         aop->coff = offset ;
1099         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1100             dname)
1101             return "acc";
1102         DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1103         
1104         return aop->aopu.aop_str[offset];
1105         
1106     case AOP_PCODE:
1107       {
1108         pCodeOp *pcop = aop->aopu.pcop;
1109         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1110         if(pcop->name) {
1111           DEBUGpic14_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1112           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1113           sprintf(s,"%s", pcop->name);
1114         } else
1115           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1116
1117       }
1118       rs = Safe_calloc(1,strlen(s)+1);
1119       strcpy(rs,s);   
1120       return rs;
1121
1122     }
1123
1124     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1125            "aopget got unsupported aop->type");
1126     exit(0);
1127 }
1128
1129
1130 /*-----------------------------------------------------------------*/
1131 /* popGetTempReg - create a new temporary pCodeOp                  */
1132 /*-----------------------------------------------------------------*/
1133 pCodeOp *popGetTempReg(void)
1134 {
1135
1136   pCodeOp *pcop;
1137
1138   pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1139   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1140     PCOR(pcop)->r->wasUsed=1;
1141     PCOR(pcop)->r->isFree=0;
1142   }
1143
1144   return pcop;
1145 }
1146
1147 /*-----------------------------------------------------------------*/
1148 /* popGetTempReg - create a new temporary pCodeOp                  */
1149 /*-----------------------------------------------------------------*/
1150 void popReleaseTempReg(pCodeOp *pcop)
1151 {
1152
1153   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1154     PCOR(pcop)->r->isFree = 1;
1155
1156 }
1157 /*-----------------------------------------------------------------*/
1158 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1159 /*-----------------------------------------------------------------*/
1160 pCodeOp *popGetLabel(unsigned int key)
1161 {
1162
1163   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1164
1165   if(key>max_key)
1166     max_key = key;
1167
1168   return newpCodeOpLabel(NULL,key+100+labelOffset);
1169 }
1170
1171 /*-----------------------------------------------------------------*/
1172 /* popCopyReg - copy a pcode operator                              */
1173 /*-----------------------------------------------------------------*/
1174 pCodeOp *popCopyReg(pCodeOpReg *pc)
1175 {
1176   pCodeOpReg *pcor;
1177
1178   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1179   pcor->pcop.type = pc->pcop.type;
1180   if(pc->pcop.name) {
1181     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1182       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1183   } else
1184     pcor->pcop.name = NULL;
1185
1186   pcor->r = pc->r;
1187   pcor->rIdx = pc->rIdx;
1188   pcor->r->wasUsed=1;
1189
1190   //DEBUGpic14_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1191
1192   return PCOP(pcor);
1193 }
1194 /*-----------------------------------------------------------------*/
1195 /* popGet - asm operator to pcode operator conversion              */
1196 /*-----------------------------------------------------------------*/
1197 pCodeOp *popGetLit(unsigned int lit)
1198 {
1199
1200   return newpCodeOpLit(lit);
1201 }
1202
1203
1204 /*-----------------------------------------------------------------*/
1205 /* popGetImmd - asm operator to pcode immediate conversion         */
1206 /*-----------------------------------------------------------------*/
1207 pCodeOp *popGetImmd(char *name, unsigned int offset, int index)
1208 {
1209
1210   return newpCodeOpImmd(name, offset,index, 0);
1211 }
1212
1213
1214 /*-----------------------------------------------------------------*/
1215 /* popGet - asm operator to pcode operator conversion              */
1216 /*-----------------------------------------------------------------*/
1217 pCodeOp *popGetWithString(char *str)
1218 {
1219   pCodeOp *pcop;
1220
1221
1222   if(!str) {
1223     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1224     exit (1);
1225   }
1226
1227   pcop = newpCodeOp(str,PO_STR);
1228
1229   return pcop;
1230 }
1231
1232 /*-----------------------------------------------------------------*/
1233 /* popRegFromString -                                              */
1234 /*-----------------------------------------------------------------*/
1235 pCodeOp *popRegFromString(char *str, int size, int offset)
1236 {
1237
1238   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1239   pcop->type = PO_DIR;
1240
1241   DEBUGpic14_emitcode(";","%d",__LINE__);
1242
1243   if(!str)
1244     str = "BAD_STRING";
1245
1246   pcop->name = Safe_calloc(1,strlen(str)+1);
1247   strcpy(pcop->name,str);
1248
1249   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1250
1251   PCOR(pcop)->r = dirregWithName(pcop->name);
1252   if(PCOR(pcop)->r == NULL) {
1253     //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1254     PCOR(pcop)->r = allocRegByName (pcop->name,size);
1255     DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1256   } else {
1257     DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1258   }
1259   PCOR(pcop)->instance = offset;
1260
1261   return pcop;
1262 }
1263
1264 pCodeOp *popRegFromIdx(int rIdx)
1265 {
1266   pCodeOp *pcop;
1267
1268   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1269                        __FUNCTION__,__LINE__,rIdx);
1270
1271   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1272
1273   PCOR(pcop)->rIdx = rIdx;
1274   PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1275   PCOR(pcop)->r->isFree = 0;
1276   PCOR(pcop)->r->wasUsed = 1;
1277
1278   pcop->type = PCOR(pcop)->r->pc_type;
1279
1280
1281   return pcop;
1282 }
1283 /*-----------------------------------------------------------------*/
1284 /* popGet - asm operator to pcode operator conversion              */
1285 /*-----------------------------------------------------------------*/
1286 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1287 {
1288   //char *s = buffer ;
1289     //char *rs;
1290
1291     pCodeOp *pcop;
1292
1293     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1294     /* offset is greater than
1295     size then zero */
1296
1297     if (offset > (aop->size - 1) &&
1298         aop->type != AOP_LIT)
1299       return NULL;  //zero;
1300
1301     /* depending on type */
1302     switch (aop->type) {
1303         
1304     case AOP_R0:
1305     case AOP_R1:
1306     case AOP_DPTR:
1307     case AOP_DPTR2:
1308     case AOP_ACC:
1309         DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1310         return NULL;
1311         
1312     case AOP_IMMD:
1313       DEBUGpic14_emitcode(";","%d",__LINE__);
1314       return popGetImmd(aop->aopu.aop_immd,offset,0);
1315
1316     case AOP_DIR:
1317       return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1318 #if 0
1319         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1320         pcop->type = PO_DIR;
1321
1322         /*
1323         if (offset)
1324             sprintf(s,"(%s + %d)",
1325                     aop->aopu.aop_dir,
1326                     offset);
1327         else
1328             sprintf(s,"%s",aop->aopu.aop_dir);
1329         pcop->name = Safe_calloc(1,strlen(s)+1);
1330         strcpy(pcop->name,s);   
1331         */
1332         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1333         strcpy(pcop->name,aop->aopu.aop_dir);   
1334         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1335         if(PCOR(pcop)->r == NULL) {
1336           //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1337           PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1338           DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1339         } else {
1340           DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1341         }
1342         PCOR(pcop)->instance = offset;
1343
1344         return pcop;
1345 #endif
1346         
1347     case AOP_REG:
1348       {
1349         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1350
1351         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1352         PCOR(pcop)->rIdx = rIdx;
1353         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1354         PCOR(pcop)->r->wasUsed=1;
1355         PCOR(pcop)->r->isFree=0;
1356
1357         PCOR(pcop)->instance = offset;
1358         pcop->type = PCOR(pcop)->r->pc_type;
1359         //rs = aop->aopu.aop_reg[offset]->name;
1360         //DEBUGpic14_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1361         return pcop;
1362       }
1363
1364     case AOP_CRY:
1365       pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1366       PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1367       //if(PCOR(pcop)->r == NULL)
1368       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1369       return pcop;
1370         
1371     case AOP_LIT:
1372       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1373
1374     case AOP_STR:
1375       DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1376       return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1377       /*
1378       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1379       PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1380       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1381       pcop->type = PCOR(pcop)->r->pc_type;
1382       pcop->name = PCOR(pcop)->r->name;
1383
1384       return pcop;
1385       */
1386
1387     case AOP_PCODE:
1388       DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s) %d %s",pCodeOpType(aop->aopu.pcop),
1389                           __LINE__, 
1390                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1391       pcop = pCodeOpCopy(aop->aopu.pcop);
1392       PCOI(pcop)->offset = offset;
1393       return pcop;
1394     }
1395
1396     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1397            "popGet got unsupported aop->type");
1398     exit(0);
1399 }
1400 /*-----------------------------------------------------------------*/
1401 /* aopPut - puts a string for a aop                                */
1402 /*-----------------------------------------------------------------*/
1403 void aopPut (asmop *aop, char *s, int offset)
1404 {
1405     char *d = buffer ;
1406     symbol *lbl ;
1407
1408     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1409
1410     if (aop->size && offset > ( aop->size - 1)) {
1411         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1412                "aopPut got offset > aop->size");
1413         exit(0);
1414     }
1415
1416     /* will assign value to value */
1417     /* depending on where it is ofcourse */
1418     switch (aop->type) {
1419     case AOP_DIR:
1420       if (offset) {
1421         sprintf(d,"(%s + %d)",
1422                 aop->aopu.aop_dir,offset);
1423         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1424
1425       } else
1426             sprintf(d,"%s",aop->aopu.aop_dir);
1427         
1428         if (strcmp(d,s)) {
1429           DEBUGpic14_emitcode(";","%d",__LINE__);
1430           if(strcmp(s,"W"))
1431             pic14_emitcode("movf","%s,w",s);
1432           pic14_emitcode("movwf","%s",d);
1433
1434           if(strcmp(s,"W")) {
1435             pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1436             if(offset >= aop->size) {
1437               emitpcode(POC_CLRF,popGet(aop,offset));
1438               break;
1439             } else
1440               emitpcode(POC_MOVLW,popGetImmd(s,offset,0));
1441           }
1442
1443           emitpcode(POC_MOVWF,popGet(aop,offset));
1444
1445
1446         }
1447         break;
1448         
1449     case AOP_REG:
1450       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1451         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1452           /*
1453             if (*s == '@'           ||
1454                 strcmp(s,"r0") == 0 ||
1455                 strcmp(s,"r1") == 0 ||
1456                 strcmp(s,"r2") == 0 ||
1457                 strcmp(s,"r3") == 0 ||
1458                 strcmp(s,"r4") == 0 ||
1459                 strcmp(s,"r5") == 0 ||
1460                 strcmp(s,"r6") == 0 || 
1461                 strcmp(s,"r7") == 0 )
1462                 pic14_emitcode("mov","%s,%s  ; %d",
1463                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1464             else
1465           */
1466
1467           if(strcmp(s,"W")==0 )
1468             pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1469
1470           pic14_emitcode("movwf","%s",
1471                    aop->aopu.aop_reg[offset]->name);
1472
1473           if(strcmp(s,zero)==0) {
1474             emitpcode(POC_CLRF,popGet(aop,offset));
1475
1476           } else if(strcmp(s,"W")==0) {
1477             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1478             pcop->type = PO_GPR_REGISTER;
1479
1480             PCOR(pcop)->rIdx = -1;
1481             PCOR(pcop)->r = NULL;
1482
1483             DEBUGpic14_emitcode(";","%d",__LINE__);
1484             pcop->name = Safe_strdup(s);
1485             emitpcode(POC_MOVFW,pcop);
1486             emitpcode(POC_MOVWF,popGet(aop,offset));
1487           } else if(strcmp(s,one)==0) {
1488             emitpcode(POC_CLRF,popGet(aop,offset));
1489             emitpcode(POC_INCF,popGet(aop,offset));
1490           } else {
1491             emitpcode(POC_MOVWF,popGet(aop,offset));
1492           }
1493         }
1494         break;
1495         
1496     case AOP_DPTR:
1497     case AOP_DPTR2:
1498     
1499     if (aop->type == AOP_DPTR2)
1500     {
1501         genSetDPTR(1);
1502     }
1503     
1504         if (aop->code) {
1505             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1506                    "aopPut writting to code space");
1507             exit(0);
1508         }
1509         
1510         while (offset > aop->coff) {
1511             aop->coff++;
1512             pic14_emitcode ("inc","dptr");
1513         }
1514         
1515         while (offset < aop->coff) {
1516             aop->coff-- ;
1517             pic14_emitcode("lcall","__decdptr");
1518         }
1519         
1520         aop->coff = offset;
1521         
1522         /* if not in accumulater */
1523         MOVA(s);        
1524         
1525         pic14_emitcode ("movx","@dptr,a");
1526         
1527     if (aop->type == AOP_DPTR2)
1528     {
1529         genSetDPTR(0);
1530     }
1531         break;
1532         
1533     case AOP_R0:
1534     case AOP_R1:
1535         while (offset > aop->coff) {
1536             aop->coff++;
1537             pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1538         }
1539         while (offset < aop->coff) {
1540             aop->coff-- ;
1541             pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1542         }
1543         aop->coff = offset;
1544         
1545         if (aop->paged) {
1546             MOVA(s);           
1547             pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1548             
1549         } else
1550             if (*s == '@') {
1551                 MOVA(s);
1552                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1553             } else
1554                 if (strcmp(s,"r0") == 0 ||
1555                     strcmp(s,"r1") == 0 ||
1556                     strcmp(s,"r2") == 0 ||
1557                     strcmp(s,"r3") == 0 ||
1558                     strcmp(s,"r4") == 0 ||
1559                     strcmp(s,"r5") == 0 ||
1560                     strcmp(s,"r6") == 0 || 
1561                     strcmp(s,"r7") == 0 ) {
1562                     char buffer[10];
1563                     sprintf(buffer,"a%s",s);
1564                     pic14_emitcode("mov","@%s,%s",
1565                              aop->aopu.aop_ptr->name,buffer);
1566                 } else
1567                     pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1568         
1569         break;
1570         
1571     case AOP_STK:
1572         if (strcmp(s,"a") == 0)
1573             pic14_emitcode("push","acc");
1574         else
1575             pic14_emitcode("push","%s",s);
1576         
1577         break;
1578         
1579     case AOP_CRY:
1580         /* if bit variable */
1581         if (!aop->aopu.aop_dir) {
1582             pic14_emitcode("clr","a");
1583             pic14_emitcode("rlc","a");
1584         } else {
1585             if (s == zero) 
1586                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1587             else
1588                 if (s == one)
1589                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1590                 else
1591                     if (!strcmp(s,"c"))
1592                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1593                     else {
1594                         lbl = newiTempLabel(NULL);
1595                         
1596                         if (strcmp(s,"a")) {
1597                             MOVA(s);
1598                         }
1599                         pic14_emitcode("clr","c");
1600                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1601                         pic14_emitcode("cpl","c");
1602                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1603                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1604                     }
1605         }
1606         break;
1607         
1608     case AOP_STR:
1609         aop->coff = offset;
1610         if (strcmp(aop->aopu.aop_str[offset],s))
1611             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1612         break;
1613         
1614     case AOP_ACC:
1615         aop->coff = offset;
1616         if (!offset && (strcmp(s,"acc") == 0))
1617             break;
1618         
1619         if (strcmp(aop->aopu.aop_str[offset],s))
1620             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1621         break;
1622
1623     default :
1624         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1625                "aopPut got unsupported aop->type");
1626         exit(0);    
1627     }    
1628
1629 }
1630
1631 /*-----------------------------------------------------------------*/
1632 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1633 /*-----------------------------------------------------------------*/
1634 void mov2w (asmop *aop, int offset)
1635 {
1636
1637   if(!aop)
1638     return;
1639
1640   DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1641
1642   if ( aop->type == AOP_PCODE ||
1643        aop->type == AOP_LIT )
1644     emitpcode(POC_MOVLW,popGet(aop,offset));
1645   else
1646     emitpcode(POC_MOVFW,popGet(aop,offset));
1647
1648 }
1649
1650 /*-----------------------------------------------------------------*/
1651 /* reAdjustPreg - points a register back to where it should        */
1652 /*-----------------------------------------------------------------*/
1653 static void reAdjustPreg (asmop *aop)
1654 {
1655     int size ;
1656
1657     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1658     aop->coff = 0;
1659     if ((size = aop->size) <= 1)
1660         return ;
1661     size-- ;
1662     switch (aop->type) {
1663         case AOP_R0 :
1664         case AOP_R1 :
1665             while (size--)
1666                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1667             break;          
1668         case AOP_DPTR :
1669         case AOP_DPTR2:
1670             if (aop->type == AOP_DPTR2)
1671             {
1672                 genSetDPTR(1);
1673             } 
1674             while (size--)
1675             {
1676                 pic14_emitcode("lcall","__decdptr");
1677             }
1678                 
1679             if (aop->type == AOP_DPTR2)
1680             {
1681                 genSetDPTR(0);
1682             }                
1683             break;  
1684
1685     }   
1686
1687 }
1688
1689 /*-----------------------------------------------------------------*/
1690 /* genNotFloat - generates not for float operations              */
1691 /*-----------------------------------------------------------------*/
1692 static void genNotFloat (operand *op, operand *res)
1693 {
1694     int size, offset;
1695     char *l;
1696     symbol *tlbl ;
1697
1698     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1699     /* we will put 127 in the first byte of 
1700     the result */
1701     aopPut(AOP(res),"#127",0);
1702     size = AOP_SIZE(op) - 1;
1703     offset = 1;
1704
1705     l = aopGet(op->aop,offset++,FALSE,FALSE);
1706     MOVA(l);    
1707
1708     while(size--) {
1709         pic14_emitcode("orl","a,%s",
1710                  aopGet(op->aop,
1711                         offset++,FALSE,FALSE));
1712     }
1713     tlbl = newiTempLabel(NULL);
1714
1715     tlbl = newiTempLabel(NULL);
1716     aopPut(res->aop,one,1);
1717     pic14_emitcode("jz","%05d_DS_",(tlbl->key+100));
1718     aopPut(res->aop,zero,1);
1719     pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
1720
1721     size = res->aop->size - 2;
1722     offset = 2;    
1723     /* put zeros in the rest */
1724     while (size--) 
1725         aopPut(res->aop,zero,offset++);
1726 }
1727
1728 #if 0
1729 /*-----------------------------------------------------------------*/
1730 /* opIsGptr: returns non-zero if the passed operand is             */   
1731 /* a generic pointer type.                                         */
1732 /*-----------------------------------------------------------------*/ 
1733 static int opIsGptr(operand *op)
1734 {
1735     sym_link *type = operandType(op);
1736     
1737     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1738     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1739     {
1740         return 1;
1741     }
1742     return 0;        
1743 }
1744 #endif
1745
1746 /*-----------------------------------------------------------------*/
1747 /* pic14_getDataSize - get the operand data size                         */
1748 /*-----------------------------------------------------------------*/
1749 int pic14_getDataSize(operand *op)
1750 {
1751     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1752
1753
1754     return AOP_SIZE(op);
1755
1756     // tsd- in the pic port, the genptr size is 1, so this code here
1757     // fails. ( in the 8051 port, the size was 4).
1758 #if 0
1759     int size;
1760     size = AOP_SIZE(op);
1761     if (size == GPTRSIZE)
1762     {
1763         sym_link *type = operandType(op);
1764         if (IS_GENPTR(type))
1765         {
1766             /* generic pointer; arithmetic operations
1767              * should ignore the high byte (pointer type).
1768              */
1769             size--;
1770     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1771         }
1772     }
1773     return size;
1774 #endif
1775 }
1776
1777 /*-----------------------------------------------------------------*/
1778 /* pic14_outAcc - output Acc                                             */
1779 /*-----------------------------------------------------------------*/
1780 void pic14_outAcc(operand *result)
1781 {
1782   int size,offset;
1783   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1784   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1785
1786
1787   size = pic14_getDataSize(result);
1788   if(size){
1789     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1790     size--;
1791     offset = 1;
1792     /* unsigned or positive */
1793     while(size--)
1794       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1795   }
1796
1797 }
1798
1799 /*-----------------------------------------------------------------*/
1800 /* pic14_outBitC - output a bit C                                        */
1801 /*-----------------------------------------------------------------*/
1802 void pic14_outBitC(operand *result)
1803 {
1804
1805     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1806     /* if the result is bit */
1807     if (AOP_TYPE(result) == AOP_CRY) 
1808         aopPut(AOP(result),"c",0);
1809     else {
1810         pic14_emitcode("clr","a  ; %d", __LINE__);
1811         pic14_emitcode("rlc","a");
1812         pic14_outAcc(result);
1813     }
1814 }
1815
1816 /*-----------------------------------------------------------------*/
1817 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1818 /*-----------------------------------------------------------------*/
1819 void pic14_toBoolean(operand *oper)
1820 {
1821     int size = AOP_SIZE(oper) - 1;
1822     int offset = 1;
1823
1824     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1825
1826     if ( AOP_TYPE(oper) != AOP_ACC) {
1827       emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1828     }
1829     while (size--) {
1830       emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1831     }
1832 }
1833
1834
1835 /*-----------------------------------------------------------------*/
1836 /* genNot - generate code for ! operation                          */
1837 /*-----------------------------------------------------------------*/
1838 static void genNot (iCode *ic)
1839 {
1840   symbol *tlbl;
1841   sym_link *optype = operandType(IC_LEFT(ic));
1842   int size;
1843
1844   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1845   /* assign asmOps to operand & result */
1846   aopOp (IC_LEFT(ic),ic,FALSE);
1847   aopOp (IC_RESULT(ic),ic,TRUE);
1848
1849   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1850   /* if in bit space then a special case */
1851   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1852     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1853       emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1854       emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1855     } else {
1856       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1857       emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1858       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1859     }
1860     goto release;
1861   }
1862
1863   /* if type float then do float */
1864   if (IS_FLOAT(optype)) {
1865     genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1866     goto release;
1867   }
1868
1869   size = AOP_SIZE(IC_RESULT(ic));
1870   if(size == 1) {
1871     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1872     emitpcode(POC_ANDLW,popGetLit(1));
1873     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1874     goto release;
1875   }
1876   pic14_toBoolean(IC_LEFT(ic));
1877
1878   tlbl = newiTempLabel(NULL);
1879   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1880   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1881   pic14_outBitC(IC_RESULT(ic));
1882
1883  release:    
1884   /* release the aops */
1885   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1886   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1887 }
1888
1889
1890 /*-----------------------------------------------------------------*/
1891 /* genCpl - generate code for complement                           */
1892 /*-----------------------------------------------------------------*/
1893 static void genCpl (iCode *ic)
1894 {
1895     int offset = 0;
1896     int size ;
1897
1898
1899     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1900     /* assign asmOps to operand & result */
1901     aopOp (IC_LEFT(ic),ic,FALSE);
1902     aopOp (IC_RESULT(ic),ic,TRUE);
1903
1904     /* if both are in bit space then 
1905     a special case */
1906     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1907         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1908
1909         pic14_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1910         pic14_emitcode("cpl","c"); 
1911         pic14_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1912         goto release; 
1913     } 
1914
1915     size = AOP_SIZE(IC_RESULT(ic));
1916     while (size--) {
1917         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1918         MOVA(l);       
1919         pic14_emitcode("cpl","a");
1920         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1921     }
1922
1923
1924 release:
1925     /* release the aops */
1926     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1927     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1928 }
1929
1930 /*-----------------------------------------------------------------*/
1931 /* genUminusFloat - unary minus for floating points                */
1932 /*-----------------------------------------------------------------*/
1933 static void genUminusFloat(operand *op,operand *result)
1934 {
1935     int size ,offset =0 ;
1936     char *l;
1937
1938     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1939     /* for this we just need to flip the 
1940     first it then copy the rest in place */
1941     size = AOP_SIZE(op) - 1;
1942     l = aopGet(AOP(op),3,FALSE,FALSE);
1943
1944     MOVA(l);    
1945
1946     pic14_emitcode("cpl","acc.7");
1947     aopPut(AOP(result),"a",3);    
1948
1949     while(size--) {
1950         aopPut(AOP(result),
1951                aopGet(AOP(op),offset,FALSE,FALSE),
1952                offset);
1953         offset++;
1954     }          
1955 }
1956
1957 /*-----------------------------------------------------------------*/
1958 /* genUminus - unary minus code generation                         */
1959 /*-----------------------------------------------------------------*/
1960 static void genUminus (iCode *ic)
1961 {
1962   int size, i;
1963   sym_link *optype, *rtype;
1964
1965
1966   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1967   /* assign asmops */
1968   aopOp(IC_LEFT(ic),ic,FALSE);
1969   aopOp(IC_RESULT(ic),ic,TRUE);
1970
1971   /* if both in bit space then special
1972      case */
1973   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1974       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1975
1976     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1977     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1978     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1979
1980     goto release; 
1981   } 
1982
1983   optype = operandType(IC_LEFT(ic));
1984   rtype = operandType(IC_RESULT(ic));
1985
1986   /* if float then do float stuff */
1987   if (IS_FLOAT(optype)) {
1988     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1989     goto release;
1990   }
1991
1992   /* otherwise subtract from zero by taking the 2's complement */
1993   size = AOP_SIZE(IC_LEFT(ic));
1994
1995   for(i=0; i<size; i++) {
1996     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1997       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1998     else {
1999       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2000       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2001     }
2002   }
2003
2004   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2005   for(i=1; i<size; i++) {
2006     emitSKPNZ;
2007     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2008   }
2009
2010  release:
2011   /* release the aops */
2012   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2013   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2014 }
2015
2016 /*-----------------------------------------------------------------*/
2017 /* saveRegisters - will look for a call and save the registers     */
2018 /*-----------------------------------------------------------------*/
2019 static void saveRegisters(iCode *lic) 
2020 {
2021     int i;
2022     iCode *ic;
2023     bitVect *rsave;
2024     sym_link *dtype;
2025
2026     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2027     /* look for call */
2028     for (ic = lic ; ic ; ic = ic->next) 
2029         if (ic->op == CALL || ic->op == PCALL)
2030             break;
2031
2032     if (!ic) {
2033         fprintf(stderr,"found parameter push with no function call\n");
2034         return ;
2035     }
2036
2037     /* if the registers have been saved already then
2038     do nothing */
2039     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2040         return ;
2041
2042     /* find the registers in use at this time 
2043     and push them away to safety */
2044     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2045                           ic->rUsed);
2046
2047     ic->regsSaved = 1;
2048     if (options.useXstack) {
2049         if (bitVectBitValue(rsave,R0_IDX))
2050             pic14_emitcode("mov","b,r0");
2051         pic14_emitcode("mov","r0,%s",spname);
2052         for (i = 0 ; i < pic14_nRegs ; i++) {
2053             if (bitVectBitValue(rsave,i)) {
2054                 if (i == R0_IDX)
2055                     pic14_emitcode("mov","a,b");
2056                 else
2057                     pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2058                 pic14_emitcode("movx","@r0,a");
2059                 pic14_emitcode("inc","r0");
2060             }
2061         }
2062         pic14_emitcode("mov","%s,r0",spname);
2063         if (bitVectBitValue(rsave,R0_IDX))
2064             pic14_emitcode("mov","r0,b");           
2065     }// else
2066     //for (i = 0 ; i < pic14_nRegs ; i++) {
2067     //    if (bitVectBitValue(rsave,i))
2068     //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2069     //}
2070
2071     dtype = operandType(IC_LEFT(ic));
2072     if (currFunc && dtype && 
2073         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2074         IFFUNC_ISISR(currFunc->type) &&
2075         !ic->bankSaved) 
2076
2077         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2078
2079 }
2080 /*-----------------------------------------------------------------*/
2081 /* unsaveRegisters - pop the pushed registers                      */
2082 /*-----------------------------------------------------------------*/
2083 static void unsaveRegisters (iCode *ic)
2084 {
2085     int i;
2086     bitVect *rsave;
2087
2088     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2089     /* find the registers in use at this time 
2090     and push them away to safety */
2091     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2092                           ic->rUsed);
2093     
2094     if (options.useXstack) {
2095         pic14_emitcode("mov","r0,%s",spname);   
2096         for (i =  pic14_nRegs ; i >= 0 ; i--) {
2097             if (bitVectBitValue(rsave,i)) {
2098                 pic14_emitcode("dec","r0");
2099                 pic14_emitcode("movx","a,@r0");
2100                 if (i == R0_IDX)
2101                     pic14_emitcode("mov","b,a");
2102                 else
2103                     pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2104             }       
2105
2106         }
2107         pic14_emitcode("mov","%s,r0",spname);
2108         if (bitVectBitValue(rsave,R0_IDX))
2109             pic14_emitcode("mov","r0,b");
2110     } //else
2111     //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2112     //    if (bitVectBitValue(rsave,i))
2113     //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2114     //}
2115
2116 }  
2117
2118
2119 /*-----------------------------------------------------------------*/
2120 /* pushSide -                                                      */
2121 /*-----------------------------------------------------------------*/
2122 static void pushSide(operand * oper, int size)
2123 {
2124 #if 0
2125         int offset = 0;
2126     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2127         while (size--) {
2128                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2129                 if (AOP_TYPE(oper) != AOP_REG &&
2130                     AOP_TYPE(oper) != AOP_DIR &&
2131                     strcmp(l,"a") ) {
2132                         pic14_emitcode("mov","a,%s",l);
2133                         pic14_emitcode("push","acc");
2134                 } else
2135                         pic14_emitcode("push","%s",l);
2136         }
2137 #endif
2138 }
2139
2140 /*-----------------------------------------------------------------*/
2141 /* assignResultValue -                                             */
2142 /*-----------------------------------------------------------------*/
2143 static void assignResultValue(operand * oper)
2144 {
2145   int size = AOP_SIZE(oper);
2146
2147   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2148
2149   DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2150
2151   if(!GpsuedoStkPtr) {
2152     /* The last byte in the assignment is in W */
2153     size--;
2154     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2155     GpsuedoStkPtr++;
2156   }
2157
2158   while (size--) {
2159     emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + Gstack_base_addr));
2160     GpsuedoStkPtr++;
2161     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2162   }
2163 }
2164
2165
2166 /*-----------------------------------------------------------------*/
2167 /* genIpush - genrate code for pushing this gets a little complex  */
2168 /*-----------------------------------------------------------------*/
2169 static void genIpush (iCode *ic)
2170 {
2171
2172   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2173 #if 0
2174     int size, offset = 0 ;
2175     char *l;
2176
2177
2178     /* if this is not a parm push : ie. it is spill push 
2179     and spill push is always done on the local stack */
2180     if (!ic->parmPush) {
2181
2182         /* and the item is spilt then do nothing */
2183         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2184             return ;
2185
2186         aopOp(IC_LEFT(ic),ic,FALSE);
2187         size = AOP_SIZE(IC_LEFT(ic));
2188         /* push it on the stack */
2189         while(size--) {
2190             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2191             if (*l == '#') {
2192                 MOVA(l);
2193                 l = "acc";
2194             }
2195             pic14_emitcode("push","%s",l);
2196         }
2197         return ;        
2198     }
2199
2200     /* this is a paramter push: in this case we call
2201     the routine to find the call and save those
2202     registers that need to be saved */   
2203     saveRegisters(ic);
2204
2205     /* then do the push */
2206     aopOp(IC_LEFT(ic),ic,FALSE);
2207
2208
2209         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2210     size = AOP_SIZE(IC_LEFT(ic));
2211
2212     while (size--) {
2213         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2214         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2215             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2216             strcmp(l,"a") ) {
2217             pic14_emitcode("mov","a,%s",l);
2218             pic14_emitcode("push","acc");
2219         } else
2220             pic14_emitcode("push","%s",l);
2221     }       
2222
2223     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2224 #endif
2225 }
2226
2227 /*-----------------------------------------------------------------*/
2228 /* genIpop - recover the registers: can happen only for spilling   */
2229 /*-----------------------------------------------------------------*/
2230 static void genIpop (iCode *ic)
2231 {
2232   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2233 #if 0
2234     int size,offset ;
2235
2236
2237     /* if the temp was not pushed then */
2238     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2239         return ;
2240
2241     aopOp(IC_LEFT(ic),ic,FALSE);
2242     size = AOP_SIZE(IC_LEFT(ic));
2243     offset = (size-1);
2244     while (size--) 
2245         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2246                                    FALSE,TRUE));
2247
2248     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2249 #endif
2250 }
2251
2252 /*-----------------------------------------------------------------*/
2253 /* unsaverbank - restores the resgister bank from stack            */
2254 /*-----------------------------------------------------------------*/
2255 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2256 {
2257   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2258 #if 0
2259     int i;
2260     asmop *aop ;
2261     regs *r = NULL;
2262
2263     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2264     if (popPsw) {
2265         if (options.useXstack) {
2266             aop = newAsmop(0);
2267             r = getFreePtr(ic,&aop,FALSE);
2268             
2269             
2270             pic14_emitcode("mov","%s,_spx",r->name);
2271             pic14_emitcode("movx","a,@%s",r->name);
2272             pic14_emitcode("mov","psw,a");
2273             pic14_emitcode("dec","%s",r->name);
2274             
2275         }else
2276             pic14_emitcode ("pop","psw");
2277     }
2278
2279     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2280         if (options.useXstack) {       
2281             pic14_emitcode("movx","a,@%s",r->name);
2282             //pic14_emitcode("mov","(%s+%d),a",
2283             //       regspic14[i].base,8*bank+regspic14[i].offset);
2284             pic14_emitcode("dec","%s",r->name);
2285
2286         } else 
2287           pic14_emitcode("pop",""); //"(%s+%d)",
2288         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2289     }
2290
2291     if (options.useXstack) {
2292
2293         pic14_emitcode("mov","_spx,%s",r->name);
2294         freeAsmop(NULL,aop,ic,TRUE);
2295
2296     }
2297 #endif 
2298 }
2299
2300 /*-----------------------------------------------------------------*/
2301 /* saverbank - saves an entire register bank on the stack          */
2302 /*-----------------------------------------------------------------*/
2303 static void saverbank (int bank, iCode *ic, bool pushPsw)
2304 {
2305   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2306 #if 0
2307     int i;
2308     asmop *aop ;
2309     regs *r = NULL;
2310
2311     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2312     if (options.useXstack) {
2313
2314         aop = newAsmop(0);
2315         r = getFreePtr(ic,&aop,FALSE);  
2316         pic14_emitcode("mov","%s,_spx",r->name);
2317
2318     }
2319
2320     for (i = 0 ; i < pic14_nRegs ;i++) {
2321         if (options.useXstack) {
2322             pic14_emitcode("inc","%s",r->name);
2323             //pic14_emitcode("mov","a,(%s+%d)",
2324             //         regspic14[i].base,8*bank+regspic14[i].offset);
2325             pic14_emitcode("movx","@%s,a",r->name);           
2326         } else 
2327           pic14_emitcode("push","");// "(%s+%d)",
2328                      //regspic14[i].base,8*bank+regspic14[i].offset);
2329     }
2330     
2331     if (pushPsw) {
2332         if (options.useXstack) {
2333             pic14_emitcode("mov","a,psw");
2334             pic14_emitcode("movx","@%s,a",r->name);     
2335             pic14_emitcode("inc","%s",r->name);
2336             pic14_emitcode("mov","_spx,%s",r->name);       
2337             freeAsmop (NULL,aop,ic,TRUE);
2338             
2339         } else
2340             pic14_emitcode("push","psw");
2341         
2342         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2343     }
2344     ic->bankSaved = 1;
2345 #endif
2346 }
2347
2348 /*-----------------------------------------------------------------*/
2349 /* genCall - generates a call statement                            */
2350 /*-----------------------------------------------------------------*/
2351 static void genCall (iCode *ic)
2352 {
2353   sym_link *dtype;   
2354
2355   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2356
2357   /* if caller saves & we have not saved then */
2358   if (!ic->regsSaved)
2359     saveRegisters(ic);
2360
2361   /* if we are calling a function that is not using
2362      the same register bank then we need to save the
2363      destination registers on the stack */
2364   dtype = operandType(IC_LEFT(ic));
2365   if (currFunc && dtype && 
2366       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2367       IFFUNC_ISISR(currFunc->type) &&
2368       !ic->bankSaved) 
2369
2370     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2371
2372   /* if send set is not empty the assign */
2373   if (_G.sendSet) {
2374     iCode *sic;
2375     /* For the Pic port, there is no data stack.
2376      * So parameters passed to functions are stored
2377      * in registers. (The pCode optimizer will get
2378      * rid of most of these :).
2379      */
2380     int psuedoStkPtr=-1; 
2381     int firstTimeThruLoop = 1;
2382
2383     _G.sendSet = reverseSet(_G.sendSet);
2384
2385     /* First figure how many parameters are getting passed */
2386     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2387          sic = setNextItem(_G.sendSet)) {
2388
2389       aopOp(IC_LEFT(sic),sic,FALSE);
2390       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2391       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2392     }
2393
2394     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2395          sic = setNextItem(_G.sendSet)) {
2396       int size, offset = 0;
2397
2398       aopOp(IC_LEFT(sic),sic,FALSE);
2399       size = AOP_SIZE(IC_LEFT(sic));
2400
2401       while (size--) {
2402         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2403                              AopType(AOP_TYPE(IC_LEFT(sic))));
2404
2405         if(!firstTimeThruLoop) {
2406           /* If this is not the first time we've been through the loop
2407            * then we need to save the parameter in a temporary
2408            * register. The last byte of the last parameter is
2409            * passed in W. */
2410           emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + Gstack_base_addr));
2411
2412         }
2413         firstTimeThruLoop=0;
2414
2415         //if (strcmp(l,fReturn[offset])) {
2416         mov2w (AOP(IC_LEFT(sic)),  offset);
2417 /*
2418         if ( ((AOP(IC_LEFT(sic))->type) == AOP_PCODE) ||
2419              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2420           emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),offset));
2421         else
2422           emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),offset));
2423 */
2424         //}
2425         offset++;
2426       }
2427       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2428     }
2429     _G.sendSet = NULL;
2430   }
2431   /* make the call */
2432   emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2433                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2434                                       OP_SYMBOL(IC_LEFT(ic))->name));
2435
2436   GpsuedoStkPtr=0;
2437   /* if we need assign a result value */
2438   if ((IS_ITEMP(IC_RESULT(ic)) && 
2439        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2440         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2441       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2442
2443     _G.accInUse++;
2444     aopOp(IC_RESULT(ic),ic,FALSE);
2445     _G.accInUse--;
2446
2447     assignResultValue(IC_RESULT(ic));
2448
2449     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2450                          AopType(AOP_TYPE(IC_RESULT(ic))));
2451                 
2452     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2453   }
2454
2455   /* adjust the stack for parameters if 
2456      required */
2457   if (ic->parmBytes) {
2458     int i;
2459     if (ic->parmBytes > 3) {
2460       pic14_emitcode("mov","a,%s",spname);
2461       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2462       pic14_emitcode("mov","%s,a",spname);
2463     } else 
2464       for ( i = 0 ; i <  ic->parmBytes ;i++)
2465         pic14_emitcode("dec","%s",spname);
2466
2467   }
2468
2469   /* if register bank was saved then pop them */
2470   if (ic->bankSaved)
2471     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2472
2473   /* if we hade saved some registers then unsave them */
2474   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2475     unsaveRegisters (ic);
2476
2477
2478 }
2479
2480 /*-----------------------------------------------------------------*/
2481 /* genPcall - generates a call by pointer statement                */
2482 /*-----------------------------------------------------------------*/
2483 static void genPcall (iCode *ic)
2484 {
2485     sym_link *dtype;
2486     symbol *rlbl = newiTempLabel(NULL);
2487
2488
2489     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2490     /* if caller saves & we have not saved then */
2491     if (!ic->regsSaved)
2492         saveRegisters(ic);
2493
2494     /* if we are calling a function that is not using
2495     the same register bank then we need to save the
2496     destination registers on the stack */
2497     dtype = operandType(IC_LEFT(ic));
2498     if (currFunc && dtype && 
2499         IFFUNC_ISISR(currFunc->type) &&
2500         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2501         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2502
2503
2504     /* push the return address on to the stack */
2505     pic14_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2506     pic14_emitcode("push","acc");    
2507     pic14_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2508     pic14_emitcode("push","acc");
2509     
2510     if (options.model == MODEL_FLAT24)
2511     {
2512         pic14_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2513         pic14_emitcode("push","acc");    
2514     }
2515
2516     /* now push the calling address */
2517     aopOp(IC_LEFT(ic),ic,FALSE);
2518
2519     pushSide(IC_LEFT(ic), FPTRSIZE);
2520
2521     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2522
2523     /* if send set is not empty the assign */
2524     if (_G.sendSet) {
2525         iCode *sic ;
2526
2527         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2528              sic = setNextItem(_G.sendSet)) {
2529             int size, offset = 0;
2530             aopOp(IC_LEFT(sic),sic,FALSE);
2531             size = AOP_SIZE(IC_LEFT(sic));
2532             while (size--) {
2533                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2534                                 FALSE,FALSE);
2535                 if (strcmp(l,fReturn[offset]))
2536                     pic14_emitcode("mov","%s,%s",
2537                              fReturn[offset],
2538                              l);
2539                 offset++;
2540             }
2541             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2542         }
2543         _G.sendSet = NULL;
2544     }
2545
2546     pic14_emitcode("ret","");
2547     pic14_emitcode("","%05d_DS_:",(rlbl->key+100));
2548
2549
2550     /* if we need assign a result value */
2551     if ((IS_ITEMP(IC_RESULT(ic)) &&
2552          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2553           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2554         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2555
2556         _G.accInUse++;
2557         aopOp(IC_RESULT(ic),ic,FALSE);
2558         _G.accInUse--;
2559         
2560         assignResultValue(IC_RESULT(ic));
2561
2562         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2563     }
2564
2565     /* adjust the stack for parameters if 
2566     required */
2567     if (ic->parmBytes) {
2568         int i;
2569         if (ic->parmBytes > 3) {
2570             pic14_emitcode("mov","a,%s",spname);
2571             pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2572             pic14_emitcode("mov","%s,a",spname);
2573         } else 
2574             for ( i = 0 ; i <  ic->parmBytes ;i++)
2575                 pic14_emitcode("dec","%s",spname);
2576
2577     }
2578
2579     /* if register bank was saved then unsave them */
2580     if (currFunc && dtype && 
2581         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2582         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2583
2584     /* if we hade saved some registers then
2585     unsave them */
2586     if (ic->regsSaved)
2587         unsaveRegisters (ic);
2588
2589 }
2590
2591 /*-----------------------------------------------------------------*/
2592 /* resultRemat - result  is rematerializable                       */
2593 /*-----------------------------------------------------------------*/
2594 static int resultRemat (iCode *ic)
2595 {
2596   //    DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2597   if (SKIP_IC(ic) || ic->op == IFX)
2598     return 0;
2599
2600   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2601     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2602     if (sym->remat && !POINTER_SET(ic)) 
2603       return 1;
2604   }
2605
2606   return 0;
2607 }
2608
2609 #if defined(__BORLANDC__) || defined(_MSC_VER)
2610 #define STRCASECMP stricmp
2611 #else
2612 #define STRCASECMP strcasecmp
2613 #endif
2614
2615 #if 0
2616 /*-----------------------------------------------------------------*/
2617 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2618 /*-----------------------------------------------------------------*/
2619 static bool inExcludeList(char *s)
2620 {
2621   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2622     int i =0;
2623     
2624     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2625     if (options.excludeRegs[i] &&
2626     STRCASECMP(options.excludeRegs[i],"none") == 0)
2627         return FALSE ;
2628
2629     for ( i = 0 ; options.excludeRegs[i]; i++) {
2630         if (options.excludeRegs[i] &&
2631         STRCASECMP(s,options.excludeRegs[i]) == 0)
2632             return TRUE;
2633     }
2634     return FALSE ;
2635 }
2636 #endif
2637
2638 /*-----------------------------------------------------------------*/
2639 /* genFunction - generated code for function entry                 */
2640 /*-----------------------------------------------------------------*/
2641 static void genFunction (iCode *ic)
2642 {
2643     symbol *sym;
2644     sym_link *ftype;
2645
2646     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2647
2648     labelOffset += (max_key+4);
2649     max_key=0;
2650     GpsuedoStkPtr=0;
2651     _G.nRegsSaved = 0;
2652     /* create the function header */
2653     pic14_emitcode(";","-----------------------------------------");
2654     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2655     pic14_emitcode(";","-----------------------------------------");
2656
2657     pic14_emitcode("","%s:",sym->rname);
2658     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2659
2660     ftype = operandType(IC_LEFT(ic));
2661
2662     /* if critical function then turn interrupts off */
2663     if (IFFUNC_ISCRITICAL(ftype))
2664         pic14_emitcode("clr","ea");
2665
2666     /* here we need to generate the equates for the
2667        register bank if required */
2668 #if 0
2669     if (FUNC_REGBANK(ftype) != rbank) {
2670         int i ;
2671
2672         rbank = FUNC_REGBANK(ftype);
2673         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2674             if (strcmp(regspic14[i].base,"0") == 0)
2675                 pic14_emitcode("","%s = 0x%02x",
2676                          regspic14[i].dname,
2677                          8*rbank+regspic14[i].offset);
2678             else
2679                 pic14_emitcode ("","%s = %s + 0x%02x",
2680                           regspic14[i].dname,
2681                           regspic14[i].base,
2682                           8*rbank+regspic14[i].offset);
2683         }
2684     }
2685 #endif
2686
2687     /* if this is an interrupt service routine then
2688     save acc, b, dpl, dph  */
2689     if (IFFUNC_ISISR(sym->type)) {
2690       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2691       emitpcodeNULLop(POC_NOP);
2692       emitpcodeNULLop(POC_NOP);
2693       emitpcodeNULLop(POC_NOP);
2694       emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2695       emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2696       emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2697       emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2698
2699       pBlockConvert2ISR(pb);
2700 #if 0  
2701         if (!inExcludeList("acc"))          
2702             pic14_emitcode ("push","acc");      
2703         if (!inExcludeList("b"))
2704             pic14_emitcode ("push","b");
2705         if (!inExcludeList("dpl"))
2706             pic14_emitcode ("push","dpl");
2707         if (!inExcludeList("dph"))
2708             pic14_emitcode ("push","dph");
2709         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2710         {
2711             pic14_emitcode ("push", "dpx");
2712             /* Make sure we're using standard DPTR */
2713             pic14_emitcode ("push", "dps");
2714             pic14_emitcode ("mov", "dps, #0x00");
2715             if (options.stack10bit)
2716             {   
2717                 /* This ISR could conceivably use DPTR2. Better save it. */
2718                 pic14_emitcode ("push", "dpl1");
2719                 pic14_emitcode ("push", "dph1");
2720                 pic14_emitcode ("push", "dpx1");
2721             }
2722         }
2723         /* if this isr has no bank i.e. is going to
2724            run with bank 0 , then we need to save more
2725            registers :-) */
2726         if (!FUNC_REGBANK(sym->type)) {
2727
2728             /* if this function does not call any other
2729                function then we can be economical and
2730                save only those registers that are used */
2731             if (! IFFUNC_HASFCALL(sym->type)) {
2732                 int i;
2733
2734                 /* if any registers used */
2735                 if (sym->regsUsed) {
2736                     /* save the registers used */
2737                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2738                         if (bitVectBitValue(sym->regsUsed,i) ||
2739                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2740                           pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);                         
2741                     }
2742                 }
2743                 
2744             } else {
2745                 /* this function has  a function call cannot
2746                    determines register usage so we will have the
2747                    entire bank */
2748                 saverbank(0,ic,FALSE);
2749             }       
2750         }
2751 #endif
2752     } else {
2753         /* if callee-save to be used for this function
2754            then save the registers being used in this function */
2755         if (IFFUNC_CALLEESAVES(sym->type)) {
2756             int i;
2757             
2758             /* if any registers used */
2759             if (sym->regsUsed) {
2760                 /* save the registers used */
2761                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2762                     if (bitVectBitValue(sym->regsUsed,i) ||
2763                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2764                       //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2765                         _G.nRegsSaved++;
2766                     }
2767                 }
2768             }
2769         }
2770     }
2771
2772     /* set the register bank to the desired value */
2773     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2774         pic14_emitcode("push","psw");
2775         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2776     }
2777
2778     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2779
2780         if (options.useXstack) {
2781             pic14_emitcode("mov","r0,%s",spname);
2782             pic14_emitcode("mov","a,_bp");
2783             pic14_emitcode("movx","@r0,a");
2784             pic14_emitcode("inc","%s",spname);
2785         }
2786         else
2787         {
2788             /* set up the stack */
2789             pic14_emitcode ("push","_bp");     /* save the callers stack  */
2790         }
2791         pic14_emitcode ("mov","_bp,%s",spname);
2792     }
2793
2794     /* adjust the stack for the function */
2795     if (sym->stack) {
2796
2797         int i = sym->stack;
2798         if (i > 256 ) 
2799             werror(W_STACK_OVERFLOW,sym->name);
2800
2801         if (i > 3 && sym->recvSize < 4) {              
2802
2803             pic14_emitcode ("mov","a,sp");
2804             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2805             pic14_emitcode ("mov","sp,a");
2806            
2807         }
2808         else
2809             while(i--)
2810                 pic14_emitcode("inc","sp");
2811     }
2812
2813      if (sym->xstack) {
2814
2815         pic14_emitcode ("mov","a,_spx");
2816         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2817         pic14_emitcode ("mov","_spx,a");
2818     }    
2819
2820 }
2821
2822 /*-----------------------------------------------------------------*/
2823 /* genEndFunction - generates epilogue for functions               */
2824 /*-----------------------------------------------------------------*/
2825 static void genEndFunction (iCode *ic)
2826 {
2827     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2828
2829     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2830
2831     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2832     {
2833         pic14_emitcode ("mov","%s,_bp",spname);
2834     }
2835
2836     /* if use external stack but some variables were
2837     added to the local stack then decrement the
2838     local stack */
2839     if (options.useXstack && sym->stack) {      
2840         pic14_emitcode("mov","a,sp");
2841         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2842         pic14_emitcode("mov","sp,a");
2843     }
2844
2845
2846     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2847         if (options.useXstack) {
2848             pic14_emitcode("mov","r0,%s",spname);
2849             pic14_emitcode("movx","a,@r0");
2850             pic14_emitcode("mov","_bp,a");
2851             pic14_emitcode("dec","%s",spname);
2852         }
2853         else
2854         {
2855             pic14_emitcode ("pop","_bp");
2856         }
2857     }
2858
2859     /* restore the register bank  */    
2860     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2861         pic14_emitcode ("pop","psw");
2862
2863     if (IFFUNC_ISISR(sym->type)) {
2864
2865         /* now we need to restore the registers */
2866         /* if this isr has no bank i.e. is going to
2867            run with bank 0 , then we need to save more
2868            registers :-) */
2869         if (!FUNC_REGBANK(sym->type)) {
2870             
2871             /* if this function does not call any other
2872                function then we can be economical and
2873                save only those registers that are used */
2874             if (! IFFUNC_HASFCALL(sym->type)) {
2875                 int i;
2876                 
2877                 /* if any registers used */
2878                 if (sym->regsUsed) {
2879                     /* save the registers used */
2880                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2881                         if (bitVectBitValue(sym->regsUsed,i) ||
2882                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2883                           pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2884                     }
2885                 }
2886                 
2887             } else {
2888                 /* this function has  a function call cannot
2889                    determines register usage so we will have the
2890                    entire bank */
2891                 unsaverbank(0,ic,FALSE);
2892             }       
2893         }
2894 #if 0
2895         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2896         {
2897             if (options.stack10bit)
2898             {
2899                 pic14_emitcode ("pop", "dpx1");
2900                 pic14_emitcode ("pop", "dph1");
2901                 pic14_emitcode ("pop", "dpl1");
2902             }   
2903             pic14_emitcode ("pop", "dps");
2904             pic14_emitcode ("pop", "dpx");
2905         }
2906         if (!inExcludeList("dph"))
2907             pic14_emitcode ("pop","dph");
2908         if (!inExcludeList("dpl"))
2909             pic14_emitcode ("pop","dpl");
2910         if (!inExcludeList("b"))
2911             pic14_emitcode ("pop","b");
2912         if (!inExcludeList("acc"))
2913             pic14_emitcode ("pop","acc");
2914
2915         if (IFFUNC_ISCRITICAL(sym->type))
2916             pic14_emitcode("setb","ea");
2917 #endif
2918
2919         /* if debug then send end of function */
2920 /*      if (options.debug && currFunc) { */
2921         if (currFunc) {
2922             _G.debugLine = 1;
2923             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2924                      FileBaseName(ic->filename),currFunc->lastLine,
2925                      ic->level,ic->block); 
2926             if (IS_STATIC(currFunc->etype))         
2927                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2928             else
2929                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2930             _G.debugLine = 0;
2931         }
2932         
2933         pic14_emitcode ("reti","");
2934
2935         emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2936         emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2937         emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2938         emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2939         emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2940         addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2941
2942         emitpcodeNULLop(POC_RETFIE);
2943
2944     }
2945     else {
2946         if (IFFUNC_ISCRITICAL(sym->type))
2947             pic14_emitcode("setb","ea");
2948         
2949         if (IFFUNC_CALLEESAVES(sym->type)) {
2950             int i;
2951             
2952             /* if any registers used */
2953             if (sym->regsUsed) {
2954                 /* save the registers used */
2955                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2956                     if (bitVectBitValue(sym->regsUsed,i) ||
2957                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2958                       pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2959                 }
2960             }
2961             
2962         }
2963
2964         /* if debug then send end of function */
2965         if (currFunc) {
2966             _G.debugLine = 1;
2967             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2968                      FileBaseName(ic->filename),currFunc->lastLine,
2969                      ic->level,ic->block); 
2970             if (IS_STATIC(currFunc->etype))         
2971                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2972             else
2973                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2974             _G.debugLine = 0;
2975         }
2976
2977         pic14_emitcode ("return","");
2978         emitpcodeNULLop(POC_RETURN);
2979
2980         /* Mark the end of a function */
2981         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2982     }
2983
2984 }
2985
2986 /*-----------------------------------------------------------------*/
2987 /* genRet - generate code for return statement                     */
2988 /*-----------------------------------------------------------------*/
2989 static void genRet (iCode *ic)
2990 {
2991   int size,offset = 0 , pushed = 0;
2992     
2993   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2994   /* if we have no return value then
2995      just generate the "ret" */
2996   if (!IC_LEFT(ic)) 
2997     goto jumpret;       
2998     
2999   /* we have something to return then
3000      move the return value into place */
3001   aopOp(IC_LEFT(ic),ic,FALSE);
3002   size = AOP_SIZE(IC_LEFT(ic));
3003     
3004   while (size--) {
3005     char *l ;
3006     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3007       /* #NOCHANGE */
3008       l = aopGet(AOP(IC_LEFT(ic)),offset++,
3009                  FALSE,TRUE);
3010       pic14_emitcode("push","%s",l);
3011       pushed++;
3012     } else {
3013       l = aopGet(AOP(IC_LEFT(ic)),offset,
3014                  FALSE,FALSE);
3015       if (strcmp(fReturn[offset],l)) {
3016         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3017             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3018           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
3019         }else {
3020           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
3021         }
3022         if(size) {
3023           emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr));
3024         }
3025         offset++;
3026       }
3027     }
3028   }    
3029
3030   if (pushed) {
3031     while(pushed) {
3032       pushed--;
3033       if (strcmp(fReturn[pushed],"a"))
3034         pic14_emitcode("pop",fReturn[pushed]);
3035       else
3036         pic14_emitcode("pop","acc");
3037     }
3038   }
3039   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3040     
3041  jumpret:
3042   /* generate a jump to the return label
3043      if the next is not the return statement */
3044   if (!(ic->next && ic->next->op == LABEL &&
3045         IC_LABEL(ic->next) == returnLabel)) {
3046         
3047     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3048     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3049   }
3050     
3051 }
3052
3053 /*-----------------------------------------------------------------*/
3054 /* genLabel - generates a label                                    */
3055 /*-----------------------------------------------------------------*/
3056 static void genLabel (iCode *ic)
3057 {
3058     /* special case never generate */
3059     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3060     if (IC_LABEL(ic) == entryLabel)
3061         return ;
3062
3063     emitpLabel(IC_LABEL(ic)->key);
3064     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3065 }
3066
3067 /*-----------------------------------------------------------------*/
3068 /* genGoto - generates a goto                                      */
3069 /*-----------------------------------------------------------------*/
3070 //tsd
3071 static void genGoto (iCode *ic)
3072 {
3073   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3074   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3075 }
3076
3077
3078 /*-----------------------------------------------------------------*/
3079 /* genMultbits :- multiplication of bits                           */
3080 /*-----------------------------------------------------------------*/
3081 static void genMultbits (operand *left, 
3082                          operand *right, 
3083                          operand *result)
3084 {
3085   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3086
3087   if(!pic14_sameRegs(AOP(result),AOP(right)))
3088     emitpcode(POC_BSF,  popGet(AOP(result),0));
3089
3090   emitpcode(POC_BTFSC,popGet(AOP(right),0));
3091   emitpcode(POC_BTFSS,popGet(AOP(left),0));
3092   emitpcode(POC_BCF,  popGet(AOP(result),0));
3093
3094 }
3095
3096
3097 /*-----------------------------------------------------------------*/
3098 /* genMultOneByte : 8 bit multiplication & division                */
3099 /*-----------------------------------------------------------------*/
3100 static void genMultOneByte (operand *left,
3101                             operand *right,
3102                             operand *result)
3103 {
3104   sym_link *opetype = operandType(result);
3105
3106   // symbol *lbl ;
3107   int size,offset;
3108
3109   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3110   DEBUGpic14_AopType(__LINE__,left,right,result);
3111   DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3112
3113   /* (if two literals, the value is computed before) */
3114   /* if one literal, literal on the right */
3115   if (AOP_TYPE(left) == AOP_LIT){
3116     operand *t = right;
3117     right = left;
3118     left = t;
3119   }
3120
3121   size = AOP_SIZE(result);
3122   if(size == 1) {
3123
3124     if (AOP_TYPE(right) == AOP_LIT){
3125       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3126                      aopGet(AOP(right),0,FALSE,FALSE), 
3127                      aopGet(AOP(left),0,FALSE,FALSE), 
3128                      aopGet(AOP(result),0,FALSE,FALSE));
3129       pic14_emitcode("call","genMultLit");
3130     } else {
3131       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3132                      aopGet(AOP(right),0,FALSE,FALSE), 
3133                      aopGet(AOP(left),0,FALSE,FALSE), 
3134                      aopGet(AOP(result),0,FALSE,FALSE));
3135       pic14_emitcode("call","genMult8X8_8");
3136
3137     }
3138     genMult8X8_8 (left, right,result);
3139
3140
3141     /* signed or unsigned */
3142     //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3143     //l = aopGet(AOP(left),0,FALSE,FALSE);
3144     //MOVA(l);       
3145     //pic14_emitcode("mul","ab");
3146     /* if result size = 1, mul signed = mul unsigned */
3147     //aopPut(AOP(result),"a",0);
3148
3149   } else {  // (size > 1)
3150
3151     pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3152                    aopGet(AOP(right),0,FALSE,FALSE), 
3153                    aopGet(AOP(left),0,FALSE,FALSE), 
3154                    aopGet(AOP(result),0,FALSE,FALSE));
3155
3156     if (SPEC_USIGN(opetype)){
3157       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3158       genUMult8X8_16 (left, right, result, NULL);
3159
3160       if (size > 2) {
3161         /* for filling the MSBs */
3162         emitpcode(POC_CLRF,  popGet(AOP(result),2));
3163         emitpcode(POC_CLRF,  popGet(AOP(result),3));
3164       }
3165     }
3166     else{
3167       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3168
3169       pic14_emitcode("mov","a,b");
3170
3171       /* adjust the MSB if left or right neg */
3172
3173       /* if one literal */
3174       if (AOP_TYPE(right) == AOP_LIT){
3175         pic14_emitcode("multiply ","right is a lit");
3176         /* AND literal negative */
3177         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3178           /* adjust MSB (c==0 after mul) */
3179           pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3180         }
3181       }
3182       else{
3183         genSMult8X8_16 (left, right, result, NULL);
3184       }
3185
3186       if(size > 2){
3187         pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3188         /* get the sign */
3189         pic14_emitcode("rlc","a");
3190         pic14_emitcode("subb","a,acc");
3191       }
3192     }
3193
3194     size -= 2;   
3195     offset = 2;
3196     if (size > 0)
3197       while (size--)
3198         pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3199     //aopPut(AOP(result),"a",offset++);
3200   }
3201 }
3202
3203 /*-----------------------------------------------------------------*/
3204 /* genMult - generates code for multiplication                     */
3205 /*-----------------------------------------------------------------*/
3206 static void genMult (iCode *ic)
3207 {
3208     operand *left = IC_LEFT(ic);
3209     operand *right = IC_RIGHT(ic);
3210     operand *result= IC_RESULT(ic);   
3211
3212     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3213     /* assign the amsops */
3214     aopOp (left,ic,FALSE);
3215     aopOp (right,ic,FALSE);
3216     aopOp (result,ic,TRUE);
3217
3218   DEBUGpic14_AopType(__LINE__,left,right,result);
3219
3220     /* special cases first */
3221     /* both are bits */
3222     if (AOP_TYPE(left) == AOP_CRY &&
3223         AOP_TYPE(right)== AOP_CRY) {
3224         genMultbits(left,right,result);
3225         goto release ;
3226     }
3227
3228     /* if both are of size == 1 */
3229     if (AOP_SIZE(left) == 1 &&
3230         AOP_SIZE(right) == 1 ) {
3231         genMultOneByte(left,right,result);
3232         goto release ;
3233     }
3234
3235     pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3236
3237     /* should have been converted to function call */
3238     //assert(0) ;
3239
3240 release :
3241     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3242     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3243     freeAsmop(result,NULL,ic,TRUE); 
3244 }
3245
3246 /*-----------------------------------------------------------------*/
3247 /* genDivbits :- division of bits                                  */
3248 /*-----------------------------------------------------------------*/
3249 static void genDivbits (operand *left, 
3250                         operand *right, 
3251                         operand *result)
3252 {
3253
3254     char *l;
3255
3256     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3257     /* the result must be bit */    
3258     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3259     l = aopGet(AOP(left),0,FALSE,FALSE);
3260
3261     MOVA(l);    
3262
3263     pic14_emitcode("div","ab");
3264     pic14_emitcode("rrc","a");
3265     aopPut(AOP(result),"c",0);
3266 }
3267
3268 /*-----------------------------------------------------------------*/
3269 /* genDivOneByte : 8 bit division                                  */
3270 /*-----------------------------------------------------------------*/
3271 static void genDivOneByte (operand *left,
3272                            operand *right,
3273                            operand *result)
3274 {
3275     sym_link *opetype = operandType(result);
3276     char *l ;
3277     symbol *lbl ;
3278     int size,offset;
3279
3280     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3281     size = AOP_SIZE(result) - 1;
3282     offset = 1;
3283     /* signed or unsigned */
3284     if (SPEC_USIGN(opetype)) {
3285         /* unsigned is easy */
3286         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3287         l = aopGet(AOP(left),0,FALSE,FALSE);
3288         MOVA(l);        
3289         pic14_emitcode("div","ab");
3290         aopPut(AOP(result),"a",0);
3291         while (size--)
3292             aopPut(AOP(result),zero,offset++);
3293         return ;
3294     }
3295
3296     /* signed is a little bit more difficult */
3297
3298     /* save the signs of the operands */
3299     l = aopGet(AOP(left),0,FALSE,FALSE);    
3300     MOVA(l);    
3301     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3302     pic14_emitcode("push","acc"); /* save it on the stack */
3303
3304     /* now sign adjust for both left & right */
3305     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3306     MOVA(l);       
3307     lbl = newiTempLabel(NULL);
3308     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3309     pic14_emitcode("cpl","a");   
3310     pic14_emitcode("inc","a");
3311     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3312     pic14_emitcode("mov","b,a");
3313
3314     /* sign adjust left side */
3315     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3316     MOVA(l);
3317
3318     lbl = newiTempLabel(NULL);
3319     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3320     pic14_emitcode("cpl","a");
3321     pic14_emitcode("inc","a");
3322     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3323
3324     /* now the division */
3325     pic14_emitcode("div","ab");
3326     /* we are interested in the lower order
3327     only */
3328     pic14_emitcode("mov","b,a");
3329     lbl = newiTempLabel(NULL);
3330     pic14_emitcode("pop","acc");   
3331     /* if there was an over flow we don't 
3332     adjust the sign of the result */
3333     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3334     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3335     CLRC;
3336     pic14_emitcode("clr","a");
3337     pic14_emitcode("subb","a,b");
3338     pic14_emitcode("mov","b,a");
3339     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3340
3341     /* now we are done */
3342     aopPut(AOP(result),"b",0);
3343     if(size > 0){
3344         pic14_emitcode("mov","c,b.7");
3345         pic14_emitcode("subb","a,acc");   
3346     }
3347     while (size--)
3348         aopPut(AOP(result),"a",offset++);
3349
3350 }
3351
3352 /*-----------------------------------------------------------------*/
3353 /* genDiv - generates code for division                            */
3354 /*-----------------------------------------------------------------*/
3355 static void genDiv (iCode *ic)
3356 {
3357     operand *left = IC_LEFT(ic);
3358     operand *right = IC_RIGHT(ic);
3359     operand *result= IC_RESULT(ic);   
3360
3361     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3362     /* assign the amsops */
3363     aopOp (left,ic,FALSE);
3364     aopOp (right,ic,FALSE);
3365     aopOp (result,ic,TRUE);
3366
3367     /* special cases first */
3368     /* both are bits */
3369     if (AOP_TYPE(left) == AOP_CRY &&
3370         AOP_TYPE(right)== AOP_CRY) {
3371         genDivbits(left,right,result);
3372         goto release ;
3373     }
3374
3375     /* if both are of size == 1 */
3376     if (AOP_SIZE(left) == 1 &&
3377         AOP_SIZE(right) == 1 ) {
3378         genDivOneByte(left,right,result);
3379         goto release ;
3380     }
3381
3382     /* should have been converted to function call */
3383     assert(0);
3384 release :
3385     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3386     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3387     freeAsmop(result,NULL,ic,TRUE); 
3388 }
3389
3390 /*-----------------------------------------------------------------*/
3391 /* genModbits :- modulus of bits                                   */
3392 /*-----------------------------------------------------------------*/
3393 static void genModbits (operand *left, 
3394                         operand *right, 
3395                         operand *result)
3396 {
3397
3398     char *l;
3399
3400     /* the result must be bit */    
3401     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3402     l = aopGet(AOP(left),0,FALSE,FALSE);
3403
3404     MOVA(l);       
3405
3406     pic14_emitcode("div","ab");
3407     pic14_emitcode("mov","a,b");
3408     pic14_emitcode("rrc","a");
3409     aopPut(AOP(result),"c",0);
3410 }
3411
3412 /*-----------------------------------------------------------------*/
3413 /* genModOneByte : 8 bit modulus                                   */
3414 /*-----------------------------------------------------------------*/
3415 static void genModOneByte (operand *left,
3416                            operand *right,
3417                            operand *result)
3418 {
3419     sym_link *opetype = operandType(result);
3420     char *l ;
3421     symbol *lbl ;
3422
3423     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3424     /* signed or unsigned */
3425     if (SPEC_USIGN(opetype)) {
3426         /* unsigned is easy */
3427         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3428         l = aopGet(AOP(left),0,FALSE,FALSE);
3429         MOVA(l);    
3430         pic14_emitcode("div","ab");
3431         aopPut(AOP(result),"b",0);
3432         return ;
3433     }
3434
3435     /* signed is a little bit more difficult */
3436
3437     /* save the signs of the operands */
3438     l = aopGet(AOP(left),0,FALSE,FALSE);    
3439     MOVA(l);
3440
3441     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3442     pic14_emitcode("push","acc"); /* save it on the stack */
3443
3444     /* now sign adjust for both left & right */
3445     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3446     MOVA(l);
3447
3448     lbl = newiTempLabel(NULL);
3449     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3450     pic14_emitcode("cpl","a");   
3451     pic14_emitcode("inc","a");
3452     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3453     pic14_emitcode("mov","b,a"); 
3454
3455     /* sign adjust left side */
3456     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3457     MOVA(l);
3458
3459     lbl = newiTempLabel(NULL);
3460     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3461     pic14_emitcode("cpl","a");   
3462     pic14_emitcode("inc","a");
3463     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3464
3465     /* now the multiplication */
3466     pic14_emitcode("div","ab");
3467     /* we are interested in the lower order
3468     only */
3469     lbl = newiTempLabel(NULL);
3470     pic14_emitcode("pop","acc");   
3471     /* if there was an over flow we don't 
3472     adjust the sign of the result */
3473     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3474     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3475     CLRC ;
3476     pic14_emitcode("clr","a");
3477     pic14_emitcode("subb","a,b");
3478     pic14_emitcode("mov","b,a");
3479     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3480
3481     /* now we are done */
3482     aopPut(AOP(result),"b",0);
3483
3484 }
3485
3486 /*-----------------------------------------------------------------*/
3487 /* genMod - generates code for division                            */
3488 /*-----------------------------------------------------------------*/
3489 static void genMod (iCode *ic)
3490 {
3491     operand *left = IC_LEFT(ic);
3492     operand *right = IC_RIGHT(ic);
3493     operand *result= IC_RESULT(ic);  
3494
3495     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3496     /* assign the amsops */
3497     aopOp (left,ic,FALSE);
3498     aopOp (right,ic,FALSE);
3499     aopOp (result,ic,TRUE);
3500
3501     /* special cases first */
3502     /* both are bits */
3503     if (AOP_TYPE(left) == AOP_CRY &&
3504         AOP_TYPE(right)== AOP_CRY) {
3505         genModbits(left,right,result);
3506         goto release ;
3507     }
3508
3509     /* if both are of size == 1 */
3510     if (AOP_SIZE(left) == 1 &&
3511         AOP_SIZE(right) == 1 ) {
3512         genModOneByte(left,right,result);
3513         goto release ;
3514     }
3515
3516     /* should have been converted to function call */
3517     assert(0);
3518
3519 release :
3520     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3521     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3522     freeAsmop(result,NULL,ic,TRUE); 
3523 }
3524
3525 /*-----------------------------------------------------------------*/
3526 /* genIfxJump :- will create a jump depending on the ifx           */
3527 /*-----------------------------------------------------------------*/
3528 /*
3529   note: May need to add parameter to indicate when a variable is in bit space.
3530 */
3531 static void genIfxJump (iCode *ic, char *jval)
3532 {
3533
3534     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3535     /* if true label then we jump if condition
3536     supplied is true */
3537     if ( IC_TRUE(ic) ) {
3538
3539         if(strcmp(jval,"a") == 0)
3540           emitSKPZ;
3541         else if (strcmp(jval,"c") == 0)
3542           emitSKPC;
3543         else {
3544           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3545           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3546         }
3547
3548         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3549         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3550
3551     }
3552     else {
3553         /* false label is present */
3554         if(strcmp(jval,"a") == 0)
3555           emitSKPNZ;
3556         else if (strcmp(jval,"c") == 0)
3557           emitSKPNC;
3558         else {
3559           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3560           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3561         }
3562
3563         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3564         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3565
3566     }
3567
3568
3569     /* mark the icode as generated */
3570     ic->generated = 1;
3571 }
3572
3573 /*-----------------------------------------------------------------*/
3574 /* genSkip                                                         */
3575 /*-----------------------------------------------------------------*/
3576 static void genSkip(iCode *ifx,int status_bit)
3577 {
3578   if(!ifx)
3579     return;
3580
3581   if ( IC_TRUE(ifx) ) {
3582     switch(status_bit) {
3583     case 'z':
3584       emitSKPNZ;
3585       break;
3586
3587     case 'c':
3588       emitSKPNC;
3589       break;
3590
3591     case 'd':
3592       emitSKPDC;
3593       break;
3594
3595     }
3596
3597     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3598     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3599
3600   } else {
3601
3602     switch(status_bit) {
3603
3604     case 'z':
3605       emitSKPZ;
3606       break;
3607
3608     case 'c':
3609       emitSKPC;
3610       break;
3611
3612     case 'd':
3613       emitSKPDC;
3614       break;
3615     }
3616     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3617     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3618
3619   }
3620
3621 }
3622
3623 /*-----------------------------------------------------------------*/
3624 /* genSkipc                                                        */
3625 /*-----------------------------------------------------------------*/
3626 static void genSkipc(resolvedIfx *rifx)
3627 {
3628   if(!rifx)
3629     return;
3630
3631   if(rifx->condition)
3632     emitSKPC;
3633   else
3634     emitSKPNC;
3635
3636   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3637   rifx->generated = 1;
3638 }
3639
3640 /*-----------------------------------------------------------------*/
3641 /* genSkipz2                                                       */
3642 /*-----------------------------------------------------------------*/
3643 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3644 {
3645   if(!rifx)
3646     return;
3647
3648   if( (rifx->condition ^ invert_condition) & 1)
3649     emitSKPZ;
3650   else
3651     emitSKPNZ;
3652
3653   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3654   rifx->generated = 1;
3655 }
3656
3657 /*-----------------------------------------------------------------*/
3658 /* genSkipz                                                        */
3659 /*-----------------------------------------------------------------*/
3660 static void genSkipz(iCode *ifx, int condition)
3661 {
3662   if(!ifx)
3663     return;
3664
3665   if(condition)
3666     emitSKPNZ;
3667   else
3668     emitSKPZ;
3669
3670   if ( IC_TRUE(ifx) )
3671     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3672   else
3673     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3674
3675   if ( IC_TRUE(ifx) )
3676     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3677   else
3678     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3679
3680 }
3681 /*-----------------------------------------------------------------*/
3682 /* genSkipCond                                                     */
3683 /*-----------------------------------------------------------------*/
3684 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3685 {
3686   if(!rifx)
3687     return;
3688
3689   if(rifx->condition)
3690     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3691   else
3692     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3693
3694
3695   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3696   rifx->generated = 1;
3697 }
3698
3699 #if 0
3700 /*-----------------------------------------------------------------*/
3701 /* genChkZeroes :- greater or less than comparison                 */
3702 /*     For each byte in a literal that is zero, inclusive or the   */
3703 /*     the corresponding byte in the operand with W                */
3704 /*     returns true if any of the bytes are zero                   */
3705 /*-----------------------------------------------------------------*/
3706 static int genChkZeroes(operand *op, int lit,  int size)
3707 {
3708
3709   int i;
3710   int flag =1;
3711
3712   while(size--) {
3713     i = (lit >> (size*8)) & 0xff;
3714
3715     if(i==0) {
3716       if(flag) 
3717         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3718       else
3719         emitpcode(POC_IORFW, popGet(AOP(op),size));
3720       flag = 0;
3721     }
3722   }
3723
3724   return (flag==0);
3725 }
3726 #endif
3727
3728 /*-----------------------------------------------------------------*/
3729 /* genCmp :- greater or less than comparison                       */
3730 /*-----------------------------------------------------------------*/
3731 static void genCmp (operand *left,operand *right,
3732                     operand *result, iCode *ifx, int sign)
3733 {
3734   int size; //, offset = 0 ;
3735   unsigned long lit = 0L,i = 0;
3736   resolvedIfx rFalseIfx;
3737   //  resolvedIfx rTrueIfx;
3738   symbol *truelbl;
3739   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3740 /*
3741   if(ifx) {
3742     DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3743     DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3744   }
3745 */
3746
3747   resolveIfx(&rFalseIfx,ifx);
3748   truelbl  = newiTempLabel(NULL);
3749   size = max(AOP_SIZE(left),AOP_SIZE(right));
3750
3751   DEBUGpic14_AopType(__LINE__,left,right,result);
3752
3753 #define _swapp
3754
3755   /* if literal is on the right then swap with left */
3756   if ((AOP_TYPE(right) == AOP_LIT)) {
3757     operand *tmp = right ;
3758     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3759     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3760 #ifdef _swapp
3761
3762     lit = (lit - 1) & mask;
3763     right = left;
3764     left = tmp;
3765     rFalseIfx.condition ^= 1;
3766 #endif
3767
3768   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3769     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3770   }
3771
3772
3773   //if(IC_TRUE(ifx) == NULL)
3774   /* if left & right are bit variables */
3775   if (AOP_TYPE(left) == AOP_CRY &&
3776       AOP_TYPE(right) == AOP_CRY ) {
3777     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3778     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3779   } else {
3780     /* subtract right from left if at the
3781        end the carry flag is set then we know that
3782        left is greater than right */
3783
3784     //    {
3785
3786     symbol *lbl  = newiTempLabel(NULL);
3787
3788 #ifndef _swapp
3789     if(AOP_TYPE(right) == AOP_LIT) {
3790
3791       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3792
3793       DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3794
3795       /* special cases */
3796
3797       if(lit == 0) {
3798
3799         if(sign != 0) 
3800           genSkipCond(&rFalseIfx,left,size-1,7);
3801         else 
3802           /* no need to compare to 0...*/
3803           /* NOTE: this is a de-generate compare that most certainly 
3804            *       creates some dead code. */
3805           emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3806
3807         if(ifx) ifx->generated = 1;
3808         return;
3809
3810       }
3811       size--;
3812
3813       if(size == 0) {
3814         //i = (lit >> (size*8)) & 0xff;
3815         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3816         
3817         emitpcode(POC_MOVFW, popGet(AOP(left),size));
3818
3819         i = ((0-lit) & 0xff);
3820         if(sign) {
3821           if( i == 0x81) { 
3822             /* lit is 0x7f, all signed chars are less than
3823              * this except for 0x7f itself */
3824             emitpcode(POC_XORLW, popGetLit(0x7f));
3825             genSkipz2(&rFalseIfx,0);
3826           } else {
3827             emitpcode(POC_ADDLW, popGetLit(0x80));
3828             emitpcode(POC_ADDLW, popGetLit(i^0x80));
3829             genSkipc(&rFalseIfx);
3830           }
3831
3832         } else {
3833           if(lit == 1) {
3834             genSkipz2(&rFalseIfx,1);
3835           } else {
3836             emitpcode(POC_ADDLW, popGetLit(i));
3837             genSkipc(&rFalseIfx);
3838           }
3839         }
3840
3841         if(ifx) ifx->generated = 1;
3842         return;
3843       }
3844
3845       /* chars are out of the way. now do ints and longs */
3846
3847
3848       DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3849         
3850       /* special cases */
3851
3852       if(sign) {
3853
3854         if(lit == 0) {
3855           genSkipCond(&rFalseIfx,left,size,7);
3856           if(ifx) ifx->generated = 1;
3857           return;
3858         }
3859
3860         if(lit <0x100) {
3861           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3862
3863           //rFalseIfx.condition ^= 1;
3864           //genSkipCond(&rFalseIfx,left,size,7);
3865           //rFalseIfx.condition ^= 1;
3866
3867           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3868           if(rFalseIfx.condition)
3869             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3870           else
3871             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3872
3873           emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3874           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3875           emitpcode(POC_MOVFW, popGet(AOP(left),1));
3876
3877           while(size > 1)
3878             emitpcode(POC_IORFW, popGet(AOP(left),size--));
3879
3880           if(rFalseIfx.condition) {
3881             emitSKPZ;
3882             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3883
3884           } else {
3885             emitSKPNZ;
3886           }
3887
3888           genSkipc(&rFalseIfx);
3889           emitpLabel(truelbl->key);
3890           if(ifx) ifx->generated = 1;
3891           return;
3892
3893         }
3894
3895         if(size == 1) {
3896
3897           if( (lit & 0xff) == 0) {
3898             /* lower byte is zero */
3899             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3900             i = ((lit >> 8) & 0xff) ^0x80;
3901             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3902             emitpcode(POC_ADDLW, popGetLit( 0x80));
3903             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3904             genSkipc(&rFalseIfx);
3905
3906
3907             if(ifx) ifx->generated = 1;
3908             return;
3909
3910           }
3911         } else {
3912           /* Special cases for signed longs */
3913           if( (lit & 0xffffff) == 0) {
3914             /* lower byte is zero */
3915             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3916             i = ((lit >> 8*3) & 0xff) ^0x80;
3917             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3918             emitpcode(POC_ADDLW, popGetLit( 0x80));
3919             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3920             genSkipc(&rFalseIfx);
3921
3922
3923             if(ifx) ifx->generated = 1;
3924             return;
3925
3926           }
3927
3928         }
3929
3930
3931         if(lit & (0x80 << (size*8))) {
3932           /* lit is negative */
3933           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3934
3935           //genSkipCond(&rFalseIfx,left,size,7);
3936
3937           emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3938
3939           if(rFalseIfx.condition)
3940             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3941           else
3942             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3943
3944
3945         } else {
3946           /* lit is positive */
3947           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3948           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3949           if(rFalseIfx.condition)
3950             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3951           else
3952             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3953
3954         }
3955
3956         /*
3957           This works, but is only good for ints.
3958           It also requires a "known zero" register.
3959           emitpcode(POC_MOVLW, popGetLit(mlit & 0xff));
3960           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3961           emitpcode(POC_RLFW,  popCopyReg(&pc_kzero));
3962           emitpcode(POC_ADDLW, popGetLit( ((mlit>>8) & 0xff)));
3963           emitpcode(POC_ADDFW, popGet(AOP(left),1));
3964           genSkipc(&rFalseIfx);
3965
3966           emitpLabel(truelbl->key);
3967           if(ifx) ifx->generated = 1;
3968           return;
3969         **/
3970           
3971         /* There are no more special cases, so perform a general compare */
3972   
3973         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3974         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3975
3976         while(size--) {
3977
3978           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3979           emitSKPNZ;
3980           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3981         }
3982         //rFalseIfx.condition ^= 1;
3983         genSkipc(&rFalseIfx);
3984
3985         emitpLabel(truelbl->key);
3986
3987         if(ifx) ifx->generated = 1;
3988         return;
3989
3990
3991       }
3992
3993
3994       /* sign is out of the way. So now do an unsigned compare */
3995       DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3996
3997
3998       /* General case - compare to an unsigned literal on the right.*/
3999
4000       i = (lit >> (size*8)) & 0xff;
4001       emitpcode(POC_MOVLW, popGetLit(i));
4002       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4003       while(size--) {
4004         i = (lit >> (size*8)) & 0xff;
4005
4006         if(i) {
4007           emitpcode(POC_MOVLW, popGetLit(i));
4008           emitSKPNZ;
4009           emitpcode(POC_SUBFW, popGet(AOP(left),size));
4010         } else {
4011           /* this byte of the lit is zero, 
4012            *if it's not the last then OR in the variable */
4013           if(size)
4014             emitpcode(POC_IORFW, popGet(AOP(left),size));
4015         }
4016       }
4017
4018
4019       emitpLabel(lbl->key);
4020       //if(emitFinalCheck)
4021       genSkipc(&rFalseIfx);
4022       if(sign)
4023         emitpLabel(truelbl->key);
4024
4025       if(ifx) ifx->generated = 1;
4026       return;
4027
4028
4029     }
4030 #endif  // _swapp
4031
4032     if(AOP_TYPE(left) == AOP_LIT) {
4033       //symbol *lbl = newiTempLabel(NULL);
4034
4035       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4036
4037
4038       DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4039
4040       /* Special cases */
4041       if((lit == 0) && (sign == 0)){
4042
4043         size--;
4044         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4045         while(size) 
4046           emitpcode(POC_IORFW, popGet(AOP(right),--size));
4047
4048         genSkipz2(&rFalseIfx,0);
4049         if(ifx) ifx->generated = 1;
4050         return;
4051       }
4052
4053       if(size==1) {
4054         /* Special cases */
4055         lit &= 0xff;
4056         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4057           /* degenerate compare can never be true */
4058           if(rFalseIfx.condition == 0)
4059             emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4060
4061           if(ifx) ifx->generated = 1;
4062           return;
4063         }
4064
4065         if(sign) {
4066           /* signed comparisons to a literal byte */
4067
4068           int lp1 = (lit+1) & 0xff;
4069
4070           DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4071           switch (lp1) {
4072           case 0:
4073             rFalseIfx.condition ^= 1;
4074             genSkipCond(&rFalseIfx,right,0,7);
4075             break;
4076           case 0x7f:
4077             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4078             emitpcode(POC_XORLW, popGetLit(0x7f));
4079             genSkipz2(&rFalseIfx,1);
4080             break;
4081           default:
4082             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4083             emitpcode(POC_ADDLW, popGetLit(0x80));
4084             emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4085             rFalseIfx.condition ^= 1;
4086             genSkipc(&rFalseIfx);
4087             break;
4088           }
4089         } else {
4090           /* unsigned comparisons to a literal byte */
4091
4092           switch(lit & 0xff ) {
4093           case 0:
4094             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4095             genSkipz2(&rFalseIfx,0);
4096             break;
4097           case 0x7f:
4098             rFalseIfx.condition ^= 1;
4099             genSkipCond(&rFalseIfx,right,0,7);
4100             break;
4101
4102           default:
4103             emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4104             emitpcode(POC_SUBFW, popGet(AOP(right),0));
4105             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4106             rFalseIfx.condition ^= 1;
4107             if (AOP_TYPE(result) == AOP_CRY)
4108               genSkipc(&rFalseIfx);
4109             else {
4110               emitpcode(POC_CLRF, popGet(AOP(result),0));
4111               emitpcode(POC_RLF, popGet(AOP(result),0));
4112             }         
4113             break;
4114           }
4115         }
4116
4117         if(ifx) ifx->generated = 1;
4118         //goto check_carry;
4119         return;
4120
4121       } else {
4122
4123         /* Size is greater than 1 */
4124
4125         if(sign) {
4126           int lp1 = lit+1;
4127
4128           size--;
4129
4130           if(lp1 == 0) {
4131             /* this means lit = 0xffffffff, or -1 */
4132
4133
4134             DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4135             rFalseIfx.condition ^= 1;
4136             genSkipCond(&rFalseIfx,right,size,7);
4137             if(ifx) ifx->generated = 1;
4138             return;
4139           }
4140
4141           if(lit == 0) {
4142             int s = size;
4143
4144             if(rFalseIfx.condition) {
4145               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4146               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4147             }
4148
4149             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4150             while(size--)
4151               emitpcode(POC_IORFW, popGet(AOP(right),size));
4152
4153
4154             emitSKPZ;
4155             if(rFalseIfx.condition) {
4156               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4157               emitpLabel(truelbl->key);
4158             }else {
4159               rFalseIfx.condition ^= 1;
4160               genSkipCond(&rFalseIfx,right,s,7);
4161             }
4162
4163             if(ifx) ifx->generated = 1;
4164             return;
4165           }
4166
4167           if((size == 1) &&  (0 == (lp1&0xff))) {
4168             /* lower byte of signed word is zero */
4169             DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4170             i = ((lp1 >> 8) & 0xff) ^0x80;
4171             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4172             emitpcode(POC_ADDLW, popGetLit( 0x80));
4173             emitpcode(POC_ADDLW, popGetLit(0x100-i));
4174             rFalseIfx.condition ^= 1;
4175             genSkipc(&rFalseIfx);
4176
4177
4178             if(ifx) ifx->generated = 1;
4179             return;
4180           }
4181
4182           if(lit & (0x80 << (size*8))) {
4183             /* Lit is less than zero */
4184             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4185             //rFalseIfx.condition ^= 1;
4186             //genSkipCond(&rFalseIfx,left,size,7);
4187             //rFalseIfx.condition ^= 1;
4188             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4189             //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4190
4191             if(rFalseIfx.condition)
4192               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4193             else
4194               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4195
4196
4197           } else {
4198             /* Lit is greater than or equal to zero */
4199             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4200             //rFalseIfx.condition ^= 1;
4201             //genSkipCond(&rFalseIfx,right,size,7);
4202             //rFalseIfx.condition ^= 1;
4203
4204             //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4205             //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4206
4207             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4208             if(rFalseIfx.condition)
4209               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4210             else
4211               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4212
4213           }
4214
4215
4216           emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4217           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4218
4219           while(size--) {
4220
4221             emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4222             emitSKPNZ;
4223             emitpcode(POC_SUBFW, popGet(AOP(right),size));
4224           }
4225           rFalseIfx.condition ^= 1;
4226           //rFalseIfx.condition = 1;
4227           genSkipc(&rFalseIfx);
4228
4229           emitpLabel(truelbl->key);
4230
4231           if(ifx) ifx->generated = 1;
4232           return;
4233           // end of if (sign)
4234         } else {
4235
4236           /* compare word or long to an unsigned literal on the right.*/
4237
4238
4239           size--;
4240           if(lit < 0xff) {
4241             DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4242             switch (lit) {
4243             case 0:
4244               break; /* handled above */
4245 /*
4246             case 0xff:
4247               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4248               while(size--)
4249                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4250               genSkipz2(&rFalseIfx,0);
4251               break;
4252 */
4253             default:
4254               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4255               while(--size)
4256                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4257
4258               emitSKPZ;
4259               if(rFalseIfx.condition)
4260                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4261               else
4262                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4263
4264
4265               emitpcode(POC_MOVLW, popGetLit(lit+1));
4266               emitpcode(POC_SUBFW, popGet(AOP(right),0));
4267
4268               rFalseIfx.condition ^= 1;
4269               genSkipc(&rFalseIfx);
4270             }
4271
4272             emitpLabel(truelbl->key);
4273
4274             if(ifx) ifx->generated = 1;
4275             return;
4276           }
4277
4278
4279           lit++;
4280           DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4281           i = (lit >> (size*8)) & 0xff;
4282
4283           emitpcode(POC_MOVLW, popGetLit(i));
4284           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4285
4286           while(size--) {
4287             i = (lit >> (size*8)) & 0xff;
4288
4289             if(i) {
4290               emitpcode(POC_MOVLW, popGetLit(i));
4291               emitSKPNZ;
4292               emitpcode(POC_SUBFW, popGet(AOP(right),size));
4293             } else {
4294               /* this byte of the lit is zero, 
4295                *if it's not the last then OR in the variable */
4296               if(size)
4297                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4298             }
4299           }
4300
4301
4302           emitpLabel(lbl->key);
4303
4304           rFalseIfx.condition ^= 1;
4305           genSkipc(&rFalseIfx);
4306         }
4307
4308         if(sign)
4309           emitpLabel(truelbl->key);
4310         if(ifx) ifx->generated = 1;
4311         return;
4312       }
4313     }
4314     /* Compare two variables */
4315
4316     DEBUGpic14_emitcode(";sign","%d",sign);
4317
4318     size--;
4319     if(sign) {
4320       /* Sigh. thus sucks... */
4321       if(size) {
4322         emitpcode(POC_MOVFW, popGet(AOP(left),size));
4323         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4324         emitpcode(POC_MOVLW, popGetLit(0x80));
4325         emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4326         emitpcode(POC_XORFW, popGet(AOP(right),size));
4327         emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4328       } else {
4329         /* Signed char comparison */
4330         /* Special thanks to Nikolai Golovchenko for this snippet */
4331         emitpcode(POC_MOVFW, popGet(AOP(right),0));
4332         emitpcode(POC_SUBFW, popGet(AOP(left),0));
4333         emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4334         emitpcode(POC_XORFW, popGet(AOP(left),0));
4335         emitpcode(POC_XORFW, popGet(AOP(right),0));
4336         emitpcode(POC_ADDLW, popGetLit(0x80));
4337
4338         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4339         genSkipc(&rFalseIfx);
4340           
4341         if(ifx) ifx->generated = 1;
4342         return;
4343       }
4344
4345     } else {
4346
4347       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4348       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4349     }
4350
4351
4352     /* The rest of the bytes of a multi-byte compare */
4353     while (size) {
4354
4355       emitSKPZ;
4356       emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4357       size--;
4358
4359       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4360       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4361
4362
4363     }
4364
4365     emitpLabel(lbl->key);
4366
4367     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4368     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4369         (AOP_TYPE(result) == AOP_REG)) {
4370       emitpcode(POC_CLRF, popGet(AOP(result),0));
4371       emitpcode(POC_RLF, popGet(AOP(result),0));
4372     } else {
4373       genSkipc(&rFalseIfx);
4374     }         
4375     //genSkipc(&rFalseIfx);
4376     if(ifx) ifx->generated = 1;
4377
4378     return;
4379
4380   }
4381
4382   // check_carry:
4383   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4384     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4385     pic14_outBitC(result);
4386   } else {
4387     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4388     /* if the result is used in the next
4389        ifx conditional branch then generate
4390        code a little differently */
4391     if (ifx )
4392       genIfxJump (ifx,"c");
4393     else
4394       pic14_outBitC(result);
4395     /* leave the result in acc */
4396   }
4397
4398 }
4399
4400 /*-----------------------------------------------------------------*/
4401 /* genCmpGt :- greater than comparison                             */
4402 /*-----------------------------------------------------------------*/
4403 static void genCmpGt (iCode *ic, iCode *ifx)
4404 {
4405     operand *left, *right, *result;
4406     sym_link *letype , *retype;
4407     int sign ;
4408
4409     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4410     left = IC_LEFT(ic);
4411     right= IC_RIGHT(ic);
4412     result = IC_RESULT(ic);
4413
4414     letype = getSpec(operandType(left));
4415     retype =getSpec(operandType(right));
4416     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4417     /* assign the amsops */
4418     aopOp (left,ic,FALSE);
4419     aopOp (right,ic,FALSE);
4420     aopOp (result,ic,TRUE);
4421
4422     genCmp(right, left, result, ifx, sign);
4423
4424     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4425     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4426     freeAsmop(result,NULL,ic,TRUE); 
4427 }
4428
4429 /*-----------------------------------------------------------------*/
4430 /* genCmpLt - less than comparisons                                */
4431 /*-----------------------------------------------------------------*/
4432 static void genCmpLt (iCode *ic, iCode *ifx)
4433 {
4434     operand *left, *right, *result;
4435     sym_link *letype , *retype;
4436     int sign ;
4437
4438     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4439     left = IC_LEFT(ic);
4440     right= IC_RIGHT(ic);
4441     result = IC_RESULT(ic);
4442
4443     letype = getSpec(operandType(left));
4444     retype =getSpec(operandType(right));
4445     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4446
4447     /* assign the amsops */
4448     aopOp (left,ic,FALSE);
4449     aopOp (right,ic,FALSE);
4450     aopOp (result,ic,TRUE);
4451
4452     genCmp(left, right, result, ifx, sign);
4453
4454     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4455     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4456     freeAsmop(result,NULL,ic,TRUE); 
4457 }
4458
4459 /*-----------------------------------------------------------------*/
4460 /* genc16bit2lit - compare a 16 bit value to a literal             */
4461 /*-----------------------------------------------------------------*/
4462 static void genc16bit2lit(operand *op, int lit, int offset)
4463 {
4464   int i;
4465
4466   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4467   if( (lit&0xff) == 0) 
4468     i=1;
4469   else
4470     i=0;
4471
4472   switch( BYTEofLONG(lit,i)) { 
4473   case 0:
4474     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4475     break;
4476   case 1:
4477     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4478     break;
4479   case 0xff:
4480     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4481     break;
4482   default:
4483     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4484     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4485   }
4486
4487   i ^= 1;
4488
4489   switch( BYTEofLONG(lit,i)) { 
4490   case 0:
4491     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4492     break;
4493   case 1:
4494     emitSKPNZ;
4495     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4496     break;
4497   case 0xff:
4498     emitSKPNZ;
4499     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4500     break;
4501   default:
4502     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4503     emitSKPNZ;
4504     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4505
4506   }
4507
4508 }
4509
4510 /*-----------------------------------------------------------------*/
4511 /* gencjneshort - compare and jump if not equal                    */
4512 /*-----------------------------------------------------------------*/
4513 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4514 {
4515   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4516   int offset = 0;
4517   int res_offset = 0;  /* the result may be a different size then left or right */
4518   int res_size = AOP_SIZE(result);
4519   resolvedIfx rIfx;
4520   symbol *lbl;
4521
4522   unsigned long lit = 0L;
4523   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4524   DEBUGpic14_AopType(__LINE__,left,right,result);
4525   if(result)
4526     DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4527   resolveIfx(&rIfx,ifx);
4528   lbl =  newiTempLabel(NULL);
4529
4530
4531   /* if the left side is a literal or 
4532      if the right is in a pointer register and left 
4533      is not */
4534   if ((AOP_TYPE(left) == AOP_LIT) || 
4535       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4536     operand *t = right;
4537     right = left;
4538     left = t;
4539   }
4540   if(AOP_TYPE(right) == AOP_LIT)
4541     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4542
4543   /* if the right side is a literal then anything goes */
4544   if (AOP_TYPE(right) == AOP_LIT &&
4545       AOP_TYPE(left) != AOP_DIR ) {
4546     switch(size) {
4547     case 2:
4548       genc16bit2lit(left, lit, 0);
4549       emitSKPNZ;
4550       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4551       break;
4552     default:
4553       while (size--) {
4554         if(lit & 0xff) {
4555           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4556           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4557         } else {
4558           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4559         }
4560
4561         emitSKPNZ;
4562         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4563         offset++;
4564         if(res_offset < res_size-1)
4565           res_offset++;
4566         lit >>= 8;
4567       }
4568       break;
4569     }
4570   }
4571
4572   /* if the right side is in a register or in direct space or
4573      if the left is a pointer register & right is not */    
4574   else if (AOP_TYPE(right) == AOP_REG ||
4575            AOP_TYPE(right) == AOP_DIR || 
4576            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4577            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4578     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4579     int lbl_key = lbl->key;
4580
4581     if(result) {
4582       emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4583       //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4584     }else {
4585       DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4586       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4587               __FUNCTION__,__LINE__);
4588       return;
4589     }
4590
4591 /*     switch(size) { */
4592 /*     case 2: */
4593 /*       genc16bit2lit(left, lit, 0); */
4594 /*       emitSKPNZ; */
4595 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4596 /*       break; */
4597 /*     default: */
4598     while (size--) {
4599       int emit_skip=1;
4600       if((AOP_TYPE(left) == AOP_DIR) && 
4601          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4602
4603         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4604         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4605
4606       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4607             
4608         switch (lit & 0xff) {
4609         case 0:
4610           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4611           break;
4612         case 1:
4613           emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4614           emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4615           //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4616           emit_skip=0;
4617           break;
4618         case 0xff:
4619           emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4620           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4621           //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4622           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4623           emit_skip=0;
4624           break;
4625         default:
4626           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4627           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4628         }
4629         lit >>= 8;
4630
4631       } else {
4632         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4633       }
4634       if(emit_skip) {
4635         if(AOP_TYPE(result) == AOP_CRY) {
4636           pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4637           if(rIfx.condition)
4638             emitSKPNZ;
4639           else
4640             emitSKPZ;
4641           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4642         } else {
4643           /* fix me. probably need to check result size too */
4644           //emitpcode(POC_CLRF,popGet(AOP(result),0));
4645           if(rIfx.condition)
4646             emitSKPZ;
4647           else
4648             emitSKPNZ;
4649           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4650           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4651         }
4652         if(ifx)
4653           ifx->generated=1;
4654       }
4655       emit_skip++;
4656       offset++;
4657       if(res_offset < res_size-1)
4658         res_offset++;
4659     }
4660 /*       break; */
4661 /*     } */
4662   } else if(AOP_TYPE(right) == AOP_REG &&
4663             AOP_TYPE(left) != AOP_DIR){
4664
4665     while(size--) {
4666       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4667       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4668       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4669       if(rIfx.condition)
4670         emitSKPNZ;
4671       else
4672         emitSKPZ;
4673       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4674       offset++;
4675       if(res_offset < res_size-1)
4676         res_offset++;
4677     }
4678       
4679   }else{
4680     /* right is a pointer reg need both a & b */
4681     while(size--) {
4682       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4683       if(strcmp(l,"b"))
4684         pic14_emitcode("mov","b,%s",l);
4685       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4686       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4687       offset++;
4688     }
4689   }
4690
4691   emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4692   if(!rIfx.condition)
4693     emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4694
4695   emitpLabel(lbl->key);
4696
4697   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4698
4699   if(ifx)
4700     ifx->generated = 1;
4701 }
4702
4703 #if 0
4704 /*-----------------------------------------------------------------*/
4705 /* gencjne - compare and jump if not equal                         */
4706 /*-----------------------------------------------------------------*/
4707 static void gencjne(operand *left, operand *right, iCode *ifx)
4708 {
4709     symbol *tlbl  = newiTempLabel(NULL);
4710
4711     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4712     gencjneshort(left, right, lbl);
4713
4714     pic14_emitcode("mov","a,%s",one);
4715     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4716     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4717     pic14_emitcode("clr","a");
4718     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4719
4720     emitpLabel(lbl->key);
4721     emitpLabel(tlbl->key);
4722
4723 }
4724 #endif
4725
4726 /*-----------------------------------------------------------------*/
4727 /* genCmpEq - generates code for equal to                          */
4728 /*-----------------------------------------------------------------*/
4729 static void genCmpEq (iCode *ic, iCode *ifx)
4730 {
4731     operand *left, *right, *result;
4732     unsigned long lit = 0L;
4733     int size,offset=0;
4734
4735     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4736
4737     if(ifx)
4738       DEBUGpic14_emitcode ("; ifx is non-null","");
4739     else
4740       DEBUGpic14_emitcode ("; ifx is null","");
4741
4742     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4743     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4744     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4745
4746     size = max(AOP_SIZE(left),AOP_SIZE(right));
4747
4748     DEBUGpic14_AopType(__LINE__,left,right,result);
4749
4750     /* if literal, literal on the right or 
4751     if the right is in a pointer register and left 
4752     is not */
4753     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4754         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4755       operand *tmp = right ;
4756       right = left;
4757       left = tmp;
4758     }
4759
4760
4761     if(ifx && !AOP_SIZE(result)){
4762         symbol *tlbl;
4763         /* if they are both bit variables */
4764         if (AOP_TYPE(left) == AOP_CRY &&
4765             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4766             if(AOP_TYPE(right) == AOP_LIT){
4767                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4768                 if(lit == 0L){
4769                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4770                     pic14_emitcode("cpl","c");
4771                 } else if(lit == 1L) {
4772                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4773                 } else {
4774                     pic14_emitcode("clr","c");
4775                 }
4776                 /* AOP_TYPE(right) == AOP_CRY */
4777             } else {
4778                 symbol *lbl = newiTempLabel(NULL);
4779                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4780                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4781                 pic14_emitcode("cpl","c");
4782                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4783             }
4784             /* if true label then we jump if condition
4785             supplied is true */
4786             tlbl = newiTempLabel(NULL);
4787             if ( IC_TRUE(ifx) ) {
4788                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4789                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4790             } else {
4791                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4792                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4793             }
4794             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4795
4796             {
4797               /* left and right are both bit variables, result is carry */
4798               resolvedIfx rIfx;
4799               
4800               resolveIfx(&rIfx,ifx);
4801
4802               emitpcode(POC_MOVLW,popGet(AOP(left),0));
4803               emitpcode(POC_ANDFW,popGet(AOP(left),0));
4804               emitpcode(POC_BTFSC,popGet(AOP(right),0));
4805               emitpcode(POC_ANDLW,popGet(AOP(left),0));
4806               genSkipz2(&rIfx,0);
4807             }
4808         } else {
4809
4810           /* They're not both bit variables. Is the right a literal? */
4811           if(AOP_TYPE(right) == AOP_LIT) {
4812             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4813             
4814             switch(size) {
4815
4816             case 1:
4817               switch(lit & 0xff) {
4818               case 1:
4819                 if ( IC_TRUE(ifx) ) {
4820                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4821                   emitSKPNZ;
4822                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4823                 } else {
4824                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4825                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4826                 }
4827                 break;
4828               case 0xff:
4829                 if ( IC_TRUE(ifx) ) {
4830                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4831                   emitSKPNZ;
4832                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4833                 } else {
4834                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4835                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4836                 }
4837                 break;
4838               default:
4839                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4840                 if(lit)
4841                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4842                 genSkip(ifx,'z');
4843               }
4844
4845
4846               /* end of size == 1 */
4847               break;
4848               
4849             case 2:
4850               genc16bit2lit(left,lit,offset);
4851               genSkip(ifx,'z');
4852               break;
4853               /* end of size == 2 */
4854
4855             default:
4856               /* size is 4 */
4857               if(lit==0) {
4858                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4859                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4860                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4861                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4862
4863               } else {
4864
4865                 /* search for patterns that can be optimized */
4866
4867                 genc16bit2lit(left,lit,0);
4868                 lit >>= 16;
4869                 if(lit) {
4870                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4871                   //genSkip(ifx,'z');
4872                   genc16bit2lit(left,lit,2);
4873                 } else {
4874                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4875                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4876
4877                 }
4878                 
4879               }
4880
4881               genSkip(ifx,'z');
4882             }
4883           
4884             ifx->generated = 1;
4885             goto release ;
4886             
4887
4888           } else if(AOP_TYPE(right) == AOP_CRY ) {
4889             /* we know the left is not a bit, but that the right is */
4890             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4891             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4892                       popGet(AOP(right),offset));
4893             emitpcode(POC_XORLW,popGetLit(1));
4894
4895             /* if the two are equal, then W will be 0 and the Z bit is set
4896              * we could test Z now, or go ahead and check the high order bytes if
4897              * the variable we're comparing is larger than a byte. */
4898
4899             while(--size)
4900               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4901
4902             if ( IC_TRUE(ifx) ) {
4903               emitSKPNZ;
4904               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4905               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4906             } else {
4907               emitSKPZ;
4908               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4909               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4910             }
4911
4912           } else {
4913             /* They're both variables that are larger than bits */
4914             int s = size;
4915
4916             tlbl = newiTempLabel(NULL);
4917
4918             while(size--) {
4919               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4920               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4921
4922               if ( IC_TRUE(ifx) ) {
4923                 if(size) {
4924                   emitSKPZ;
4925                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4926                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4927                 } else {
4928                   emitSKPNZ;
4929                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4930                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4931                 }
4932               } else {
4933                 emitSKPZ;
4934                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4935                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4936               }
4937               offset++;
4938             }
4939             if(s>1 && IC_TRUE(ifx)) {
4940               emitpLabel(tlbl->key);
4941               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4942             }
4943           }
4944         }
4945         /* mark the icode as generated */
4946         ifx->generated = 1;
4947         goto release ;
4948     }
4949
4950     /* if they are both bit variables */
4951     if (AOP_TYPE(left) == AOP_CRY &&
4952         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4953         if(AOP_TYPE(right) == AOP_LIT){
4954             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4955             if(lit == 0L){
4956                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4957                 pic14_emitcode("cpl","c");
4958             } else if(lit == 1L) {
4959                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4960             } else {
4961                 pic14_emitcode("clr","c");
4962             }
4963             /* AOP_TYPE(right) == AOP_CRY */
4964         } else {
4965             symbol *lbl = newiTempLabel(NULL);
4966             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4967             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4968             pic14_emitcode("cpl","c");
4969             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4970         }
4971         /* c = 1 if egal */
4972         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4973             pic14_outBitC(result);
4974             goto release ;
4975         }
4976         if (ifx) {
4977             genIfxJump (ifx,"c");
4978             goto release ;
4979         }
4980         /* if the result is used in an arithmetic operation
4981         then put the result in place */
4982         pic14_outBitC(result);
4983     } else {
4984       
4985       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4986       gencjne(left,right,result,ifx);
4987 /*
4988       if(ifx) 
4989         gencjne(left,right,newiTempLabel(NULL));
4990       else {
4991         if(IC_TRUE(ifx)->key)
4992           gencjne(left,right,IC_TRUE(ifx)->key);
4993         else
4994           gencjne(left,right,IC_FALSE(ifx)->key);
4995         ifx->generated = 1;
4996         goto release ;
4997       }
4998       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4999         aopPut(AOP(result),"a",0);
5000         goto release ;
5001       }
5002
5003       if (ifx) {
5004         genIfxJump (ifx,"a");
5005         goto release ;
5006       }
5007 */
5008       /* if the result is used in an arithmetic operation
5009          then put the result in place */
5010 /*
5011       if (AOP_TYPE(result) != AOP_CRY) 
5012         pic14_outAcc(result);
5013 */
5014       /* leave the result in acc */
5015     }
5016
5017 release:
5018     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5019     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5020     freeAsmop(result,NULL,ic,TRUE);
5021 }
5022
5023 /*-----------------------------------------------------------------*/
5024 /* ifxForOp - returns the icode containing the ifx for operand     */
5025 /*-----------------------------------------------------------------*/
5026 static iCode *ifxForOp ( operand *op, iCode *ic )
5027 {
5028     /* if true symbol then needs to be assigned */
5029     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5030     if (IS_TRUE_SYMOP(op))
5031         return NULL ;
5032
5033     /* if this has register type condition and
5034     the next instruction is ifx with the same operand
5035     and live to of the operand is upto the ifx only then */
5036     if (ic->next &&
5037         ic->next->op == IFX &&
5038         IC_COND(ic->next)->key == op->key &&
5039         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5040         return ic->next;
5041
5042     if (ic->next &&
5043         ic->next->op == IFX &&
5044         IC_COND(ic->next)->key == op->key) {
5045       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5046       return ic->next;
5047     }
5048
5049     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5050     if (ic->next &&
5051         ic->next->op == IFX)
5052       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5053
5054     if (ic->next &&
5055         ic->next->op == IFX &&
5056         IC_COND(ic->next)->key == op->key) {
5057       DEBUGpic14_emitcode ("; "," key is okay");
5058       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5059                            OP_SYMBOL(op)->liveTo,
5060                            ic->next->seq);
5061     }
5062
5063
5064     return NULL;
5065 }
5066 /*-----------------------------------------------------------------*/
5067 /* genAndOp - for && operation                                     */
5068 /*-----------------------------------------------------------------*/
5069 static void genAndOp (iCode *ic)
5070 {
5071     operand *left,*right, *result;
5072 /*     symbol *tlbl; */
5073
5074     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5075     /* note here that && operations that are in an
5076     if statement are taken away by backPatchLabels
5077     only those used in arthmetic operations remain */
5078     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5079     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5080     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5081
5082     DEBUGpic14_AopType(__LINE__,left,right,result);
5083
5084     emitpcode(POC_MOVFW,popGet(AOP(left),0));
5085     emitpcode(POC_ANDFW,popGet(AOP(right),0));
5086     emitpcode(POC_MOVWF,popGet(AOP(result),0));
5087
5088     /* if both are bit variables */
5089 /*     if (AOP_TYPE(left) == AOP_CRY && */
5090 /*         AOP_TYPE(right) == AOP_CRY ) { */
5091 /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5092 /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5093 /*         pic14_outBitC(result); */
5094 /*     } else { */
5095 /*         tlbl = newiTempLabel(NULL); */
5096 /*         pic14_toBoolean(left);     */
5097 /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5098 /*         pic14_toBoolean(right); */
5099 /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5100 /*         pic14_outBitAcc(result); */
5101 /*     } */
5102
5103     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5104     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5105     freeAsmop(result,NULL,ic,TRUE);
5106 }
5107
5108
5109 /*-----------------------------------------------------------------*/
5110 /* genOrOp - for || operation                                      */
5111 /*-----------------------------------------------------------------*/
5112 /*
5113   tsd pic port -
5114   modified this code, but it doesn't appear to ever get called
5115 */
5116
5117 static void genOrOp (iCode *ic)
5118 {
5119     operand *left,*right, *result;
5120     symbol *tlbl;
5121
5122     /* note here that || operations that are in an
5123     if statement are taken away by backPatchLabels
5124     only those used in arthmetic operations remain */
5125     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5126     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5127     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5128     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5129
5130     DEBUGpic14_AopType(__LINE__,left,right,result);
5131
5132     /* if both are bit variables */
5133     if (AOP_TYPE(left) == AOP_CRY &&
5134         AOP_TYPE(right) == AOP_CRY ) {
5135       pic14_emitcode("clrc","");
5136       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5137                AOP(left)->aopu.aop_dir,
5138                AOP(left)->aopu.aop_dir);
5139       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5140                AOP(right)->aopu.aop_dir,
5141                AOP(right)->aopu.aop_dir);
5142       pic14_emitcode("setc","");
5143
5144     } else {
5145         tlbl = newiTempLabel(NULL);
5146         pic14_toBoolean(left);
5147         emitSKPZ;
5148         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5149         pic14_toBoolean(right);
5150         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5151
5152         pic14_outBitAcc(result);
5153     }
5154
5155     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5156     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5157     freeAsmop(result,NULL,ic,TRUE);            
5158 }
5159
5160 /*-----------------------------------------------------------------*/
5161 /* isLiteralBit - test if lit == 2^n                               */
5162 /*-----------------------------------------------------------------*/
5163 static int isLiteralBit(unsigned long lit)
5164 {
5165     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5166     0x100L,0x200L,0x400L,0x800L,
5167     0x1000L,0x2000L,0x4000L,0x8000L,
5168     0x10000L,0x20000L,0x40000L,0x80000L,
5169     0x100000L,0x200000L,0x400000L,0x800000L,
5170     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5171     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5172     int idx;
5173     
5174     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5175     for(idx = 0; idx < 32; idx++)
5176         if(lit == pw[idx])
5177             return idx+1;
5178     return 0;
5179 }
5180
5181 /*-----------------------------------------------------------------*/
5182 /* continueIfTrue -                                                */
5183 /*-----------------------------------------------------------------*/
5184 static void continueIfTrue (iCode *ic)
5185 {
5186     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5187     if(IC_TRUE(ic))
5188         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5189     ic->generated = 1;
5190 }
5191
5192 /*-----------------------------------------------------------------*/
5193 /* jmpIfTrue -                                                     */
5194 /*-----------------------------------------------------------------*/
5195 static void jumpIfTrue (iCode *ic)
5196 {
5197     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5198     if(!IC_TRUE(ic))
5199         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5200     ic->generated = 1;
5201 }
5202
5203 /*-----------------------------------------------------------------*/
5204 /* jmpTrueOrFalse -                                                */
5205 /*-----------------------------------------------------------------*/
5206 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5207 {
5208     // ugly but optimized by peephole
5209     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5210     if(IC_TRUE(ic)){
5211         symbol *nlbl = newiTempLabel(NULL);
5212         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5213         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5214         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5215         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5216     }
5217     else{
5218         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5219         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5220     }
5221     ic->generated = 1;
5222 }
5223
5224 /*-----------------------------------------------------------------*/
5225 /* genAnd  - code for and                                          */
5226 /*-----------------------------------------------------------------*/
5227 static void genAnd (iCode *ic, iCode *ifx)
5228 {
5229   operand *left, *right, *result;
5230   int size, offset=0;  
5231   unsigned long lit = 0L;
5232   int bytelit = 0;
5233   resolvedIfx rIfx;
5234
5235
5236   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5237   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5238   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5239   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5240
5241   resolveIfx(&rIfx,ifx);
5242
5243   /* if left is a literal & right is not then exchange them */
5244   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5245       AOP_NEEDSACC(left)) {
5246     operand *tmp = right ;
5247     right = left;
5248     left = tmp;
5249   }
5250
5251   /* if result = right then exchange them */
5252   if(pic14_sameRegs(AOP(result),AOP(right))){
5253     operand *tmp = right ;
5254     right = left;
5255     left = tmp;
5256   }
5257
5258   /* if right is bit then exchange them */
5259   if (AOP_TYPE(right) == AOP_CRY &&
5260       AOP_TYPE(left) != AOP_CRY){
5261     operand *tmp = right ;
5262     right = left;
5263     left = tmp;
5264   }
5265   if(AOP_TYPE(right) == AOP_LIT)
5266     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5267
5268   size = AOP_SIZE(result);
5269
5270   DEBUGpic14_AopType(__LINE__,left,right,result);
5271
5272   // if(bit & yy)
5273   // result = bit & yy;
5274   if (AOP_TYPE(left) == AOP_CRY){
5275     // c = bit & literal;
5276     if(AOP_TYPE(right) == AOP_LIT){
5277       if(lit & 1) {
5278         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5279           // no change
5280           goto release;
5281         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5282       } else {
5283         // bit(result) = 0;
5284         if(size && (AOP_TYPE(result) == AOP_CRY)){
5285           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5286           goto release;
5287         }
5288         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5289           jumpIfTrue(ifx);
5290           goto release;
5291         }
5292         pic14_emitcode("clr","c");
5293       }
5294     } else {
5295       if (AOP_TYPE(right) == AOP_CRY){
5296         // c = bit & bit;
5297         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5298         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5299       } else {
5300         // c = bit & val;
5301         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5302         // c = lsb
5303         pic14_emitcode("rrc","a");
5304         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5305       }
5306     }
5307     // bit = c
5308     // val = c
5309     if(size)
5310       pic14_outBitC(result);
5311     // if(bit & ...)
5312     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5313       genIfxJump(ifx, "c");           
5314     goto release ;
5315   }
5316
5317   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5318   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5319   if((AOP_TYPE(right) == AOP_LIT) &&
5320      (AOP_TYPE(result) == AOP_CRY) &&
5321      (AOP_TYPE(left) != AOP_CRY)){
5322     int posbit = isLiteralBit(lit);
5323     /* left &  2^n */
5324     if(posbit){
5325       posbit--;
5326       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5327       // bit = left & 2^n
5328       if(size)
5329         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5330       // if(left &  2^n)
5331       else{
5332         if(ifx){
5333 /*
5334           if(IC_TRUE(ifx)) {
5335             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5336             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
5337           } else {
5338             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5339             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
5340           }
5341 */
5342           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5343                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5344           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5345           
5346           ifx->generated = 1;
5347         }
5348         goto release;
5349       }
5350     } else {
5351       symbol *tlbl = newiTempLabel(NULL);
5352       int sizel = AOP_SIZE(left);
5353       if(size)
5354         pic14_emitcode("setb","c");
5355       while(sizel--){
5356         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5357           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5358           // byte ==  2^n ?
5359           if((posbit = isLiteralBit(bytelit)) != 0)
5360             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5361           else{
5362             if(bytelit != 0x0FFL)
5363               pic14_emitcode("anl","a,%s",
5364                              aopGet(AOP(right),offset,FALSE,TRUE));
5365             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5366           }
5367         }
5368         offset++;
5369       }
5370       // bit = left & literal
5371       if(size){
5372         pic14_emitcode("clr","c");
5373         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5374       }
5375       // if(left & literal)
5376       else{
5377         if(ifx)
5378           jmpTrueOrFalse(ifx, tlbl);
5379         goto release ;
5380       }
5381     }
5382     pic14_outBitC(result);
5383     goto release ;
5384   }
5385
5386   /* if left is same as result */
5387   if(pic14_sameRegs(AOP(result),AOP(left))){
5388     int know_W = -1;
5389     for(;size--; offset++,lit>>=8) {
5390       if(AOP_TYPE(right) == AOP_LIT){
5391         switch(lit & 0xff) {
5392         case 0x00:
5393           /*  and'ing with 0 has clears the result */
5394           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5395           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5396           break;
5397         case 0xff:
5398           /* and'ing with 0xff is a nop when the result and left are the same */
5399           break;
5400
5401         default:
5402           {
5403             int p = my_powof2( (~lit) & 0xff );
5404             if(p>=0) {
5405               /* only one bit is set in the literal, so use a bcf instruction */
5406               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5407               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5408
5409             } else {
5410               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5411               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5412               if(know_W != (lit&0xff))
5413                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5414               know_W = lit &0xff;
5415               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5416             }
5417           }    
5418         }
5419       } else {
5420         if (AOP_TYPE(left) == AOP_ACC) {
5421           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5422         } else {                    
5423           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5424           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5425
5426         }
5427       }
5428     }
5429
5430   } else {
5431     // left & result in different registers
5432     if(AOP_TYPE(result) == AOP_CRY){
5433       // result = bit
5434       // if(size), result in bit
5435       // if(!size && ifx), conditional oper: if(left & right)
5436       symbol *tlbl = newiTempLabel(NULL);
5437       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5438       if(size)
5439         pic14_emitcode("setb","c");
5440       while(sizer--){
5441         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5442         pic14_emitcode("anl","a,%s",
5443                        aopGet(AOP(left),offset,FALSE,FALSE));
5444         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5445         offset++;
5446       }
5447       if(size){
5448         CLRC;
5449         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5450         pic14_outBitC(result);
5451       } else if(ifx)
5452         jmpTrueOrFalse(ifx, tlbl);
5453     } else {
5454       for(;(size--);offset++) {
5455         // normal case
5456         // result = left & right
5457         if(AOP_TYPE(right) == AOP_LIT){
5458           int t = (lit >> (offset*8)) & 0x0FFL;
5459           switch(t) { 
5460           case 0x00:
5461             pic14_emitcode("clrf","%s",
5462                            aopGet(AOP(result),offset,FALSE,FALSE));
5463             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5464             break;
5465           case 0xff:
5466             pic14_emitcode("movf","%s,w",
5467                            aopGet(AOP(left),offset,FALSE,FALSE));
5468             pic14_emitcode("movwf","%s",
5469                            aopGet(AOP(result),offset,FALSE,FALSE));
5470             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5471             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5472             break;
5473           default:
5474             pic14_emitcode("movlw","0x%x",t);
5475             pic14_emitcode("andwf","%s,w",
5476                            aopGet(AOP(left),offset,FALSE,FALSE));
5477             pic14_emitcode("movwf","%s",
5478                            aopGet(AOP(result),offset,FALSE,FALSE));
5479               
5480             emitpcode(POC_MOVLW, popGetLit(t));
5481             emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5482             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5483           }
5484           continue;
5485         }
5486
5487         if (AOP_TYPE(left) == AOP_ACC) {
5488           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5489           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5490         } else {
5491           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5492           pic14_emitcode("andwf","%s,w",
5493                          aopGet(AOP(left),offset,FALSE,FALSE));
5494           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5495           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5496         }
5497         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5498         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5499       }
5500     }
5501   }
5502
5503   release :
5504     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5505   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5506   freeAsmop(result,NULL,ic,TRUE);     
5507 }
5508
5509 /*-----------------------------------------------------------------*/
5510 /* genOr  - code for or                                            */
5511 /*-----------------------------------------------------------------*/
5512 static void genOr (iCode *ic, iCode *ifx)
5513 {
5514     operand *left, *right, *result;
5515     int size, offset=0;
5516     unsigned long lit = 0L;
5517
5518     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5519
5520     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5521     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5522     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5523
5524     DEBUGpic14_AopType(__LINE__,left,right,result);
5525
5526     /* if left is a literal & right is not then exchange them */
5527     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5528         AOP_NEEDSACC(left)) {
5529         operand *tmp = right ;
5530         right = left;
5531         left = tmp;
5532     }
5533
5534     /* if result = right then exchange them */
5535     if(pic14_sameRegs(AOP(result),AOP(right))){
5536         operand *tmp = right ;
5537         right = left;
5538         left = tmp;
5539     }
5540
5541     /* if right is bit then exchange them */
5542     if (AOP_TYPE(right) == AOP_CRY &&
5543         AOP_TYPE(left) != AOP_CRY){
5544         operand *tmp = right ;
5545         right = left;
5546         left = tmp;
5547     }
5548
5549     DEBUGpic14_AopType(__LINE__,left,right,result);
5550
5551     if(AOP_TYPE(right) == AOP_LIT)
5552         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5553
5554     size = AOP_SIZE(result);
5555
5556     // if(bit | yy)
5557     // xx = bit | yy;
5558     if (AOP_TYPE(left) == AOP_CRY){
5559         if(AOP_TYPE(right) == AOP_LIT){
5560             // c = bit & literal;
5561             if(lit){
5562                 // lit != 0 => result = 1
5563                 if(AOP_TYPE(result) == AOP_CRY){
5564                   if(size)
5565                     emitpcode(POC_BSF, popGet(AOP(result),0));
5566                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5567                   //     AOP(result)->aopu.aop_dir,
5568                   //     AOP(result)->aopu.aop_dir);
5569                     else if(ifx)
5570                         continueIfTrue(ifx);
5571                     goto release;
5572                 }
5573             } else {
5574                 // lit == 0 => result = left
5575                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5576                     goto release;
5577                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5578             }
5579         } else {
5580             if (AOP_TYPE(right) == AOP_CRY){
5581               if(pic14_sameRegs(AOP(result),AOP(left))){
5582                 // c = bit | bit;
5583                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5584                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5585                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5586
5587                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5588                          AOP(result)->aopu.aop_dir,
5589                          AOP(result)->aopu.aop_dir);
5590                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5591                          AOP(right)->aopu.aop_dir,
5592                          AOP(right)->aopu.aop_dir);
5593                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5594                          AOP(result)->aopu.aop_dir,
5595                          AOP(result)->aopu.aop_dir);
5596               } else {
5597                 if( AOP_TYPE(result) == AOP_ACC) {
5598                   emitpcode(POC_MOVLW, popGetLit(0));
5599                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5600                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5601                   emitpcode(POC_MOVLW, popGetLit(1));
5602
5603                 } else {
5604
5605                   emitpcode(POC_BCF,   popGet(AOP(result),0));
5606                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5607                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5608                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5609
5610                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5611                                  AOP(result)->aopu.aop_dir,
5612                                  AOP(result)->aopu.aop_dir);
5613                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5614                                  AOP(right)->aopu.aop_dir,
5615                                  AOP(right)->aopu.aop_dir);
5616                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5617                                  AOP(left)->aopu.aop_dir,
5618                                  AOP(left)->aopu.aop_dir);
5619                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5620                                  AOP(result)->aopu.aop_dir,
5621                                  AOP(result)->aopu.aop_dir);
5622                 }
5623               }
5624             } else {
5625                 // c = bit | val;
5626                 symbol *tlbl = newiTempLabel(NULL);
5627                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5628
5629
5630                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5631                 if( AOP_TYPE(right) == AOP_ACC) {
5632                   emitpcode(POC_IORLW, popGetLit(0));
5633                   emitSKPNZ;
5634                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5635                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5636                 }
5637
5638
5639
5640                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5641                     pic14_emitcode(";XXX setb","c");
5642                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5643                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5644                 pic14_toBoolean(right);
5645                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5646                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5647                     jmpTrueOrFalse(ifx, tlbl);
5648                     goto release;
5649                 } else {
5650                     CLRC;
5651                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5652                 }
5653             }
5654         }
5655         // bit = c
5656         // val = c
5657         if(size)
5658             pic14_outBitC(result);
5659         // if(bit | ...)
5660         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5661             genIfxJump(ifx, "c");           
5662         goto release ;
5663     }
5664
5665     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5666     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5667     if((AOP_TYPE(right) == AOP_LIT) &&
5668        (AOP_TYPE(result) == AOP_CRY) &&
5669        (AOP_TYPE(left) != AOP_CRY)){
5670         if(lit){
5671           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5672             // result = 1
5673             if(size)
5674                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5675             else 
5676                 continueIfTrue(ifx);
5677             goto release;
5678         } else {
5679           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5680             // lit = 0, result = boolean(left)
5681             if(size)
5682                 pic14_emitcode(";XXX setb","c");
5683             pic14_toBoolean(right);
5684             if(size){
5685                 symbol *tlbl = newiTempLabel(NULL);
5686                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5687                 CLRC;
5688                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5689             } else {
5690                 genIfxJump (ifx,"a");
5691                 goto release;
5692             }
5693         }
5694         pic14_outBitC(result);
5695         goto release ;
5696     }
5697
5698     /* if left is same as result */
5699     if(pic14_sameRegs(AOP(result),AOP(left))){
5700       int know_W = -1;
5701       for(;size--; offset++,lit>>=8) {
5702         if(AOP_TYPE(right) == AOP_LIT){
5703           if((lit & 0xff) == 0)
5704             /*  or'ing with 0 has no effect */
5705             continue;
5706           else {
5707             int p = my_powof2(lit & 0xff);
5708             if(p>=0) {
5709               /* only one bit is set in the literal, so use a bsf instruction */
5710               emitpcode(POC_BSF,
5711                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5712             } else {
5713               if(know_W != (lit & 0xff))
5714                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5715               know_W = lit & 0xff;
5716               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5717             }
5718                     
5719           }
5720         } else {
5721           if (AOP_TYPE(left) == AOP_ACC) {
5722             emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5723             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5724           } else {                  
5725             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5726             emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5727
5728             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5729             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5730
5731           }
5732         }
5733       }
5734     } else {
5735         // left & result in different registers
5736         if(AOP_TYPE(result) == AOP_CRY){
5737             // result = bit
5738             // if(size), result in bit
5739             // if(!size && ifx), conditional oper: if(left | right)
5740             symbol *tlbl = newiTempLabel(NULL);
5741             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5742             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5743
5744
5745             if(size)
5746                 pic14_emitcode(";XXX setb","c");
5747             while(sizer--){
5748                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5749                 pic14_emitcode(";XXX orl","a,%s",
5750                          aopGet(AOP(left),offset,FALSE,FALSE));
5751                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5752                 offset++;
5753             }
5754             if(size){
5755                 CLRC;
5756                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5757                 pic14_outBitC(result);
5758             } else if(ifx)
5759                 jmpTrueOrFalse(ifx, tlbl);
5760         } else for(;(size--);offset++){
5761           // normal case
5762           // result = left & right
5763           if(AOP_TYPE(right) == AOP_LIT){
5764             int t = (lit >> (offset*8)) & 0x0FFL;
5765             switch(t) { 
5766             case 0x00:
5767               emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5768               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5769
5770               pic14_emitcode("movf","%s,w",
5771                        aopGet(AOP(left),offset,FALSE,FALSE));
5772               pic14_emitcode("movwf","%s",
5773                        aopGet(AOP(result),offset,FALSE,FALSE));
5774               break;
5775             default:
5776               emitpcode(POC_MOVLW,  popGetLit(t));
5777               emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5778               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5779
5780               pic14_emitcode("movlw","0x%x",t);
5781               pic14_emitcode("iorwf","%s,w",
5782                        aopGet(AOP(left),offset,FALSE,FALSE));
5783               pic14_emitcode("movwf","%s",
5784                        aopGet(AOP(result),offset,FALSE,FALSE));
5785               
5786             }
5787             continue;
5788           }
5789
5790           // faster than result <- left, anl result,right
5791           // and better if result is SFR
5792           if (AOP_TYPE(left) == AOP_ACC) {
5793             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5794             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5795           } else {
5796             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5797             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5798
5799             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5800             pic14_emitcode("iorwf","%s,w",
5801                      aopGet(AOP(left),offset,FALSE,FALSE));
5802           }
5803           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5804           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5805         }
5806     }
5807
5808 release :
5809     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5810     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5811     freeAsmop(result,NULL,ic,TRUE);     
5812 }
5813
5814 /*-----------------------------------------------------------------*/
5815 /* genXor - code for xclusive or                                   */
5816 /*-----------------------------------------------------------------*/
5817 static void genXor (iCode *ic, iCode *ifx)
5818 {
5819   operand *left, *right, *result;
5820   int size, offset=0;
5821   unsigned long lit = 0L;
5822
5823   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5824
5825   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5826   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5827   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5828
5829   /* if left is a literal & right is not ||
5830      if left needs acc & right does not */
5831   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5832       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5833     operand *tmp = right ;
5834     right = left;
5835     left = tmp;
5836   }
5837
5838   /* if result = right then exchange them */
5839   if(pic14_sameRegs(AOP(result),AOP(right))){
5840     operand *tmp = right ;
5841     right = left;
5842     left = tmp;
5843   }
5844
5845   /* if right is bit then exchange them */
5846   if (AOP_TYPE(right) == AOP_CRY &&
5847       AOP_TYPE(left) != AOP_CRY){
5848     operand *tmp = right ;
5849     right = left;
5850     left = tmp;
5851   }
5852   if(AOP_TYPE(right) == AOP_LIT)
5853     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5854
5855   size = AOP_SIZE(result);
5856
5857   // if(bit ^ yy)
5858   // xx = bit ^ yy;
5859   if (AOP_TYPE(left) == AOP_CRY){
5860     if(AOP_TYPE(right) == AOP_LIT){
5861       // c = bit & literal;
5862       if(lit>>1){
5863         // lit>>1  != 0 => result = 1
5864         if(AOP_TYPE(result) == AOP_CRY){
5865           if(size)
5866             {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5867             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5868           else if(ifx)
5869             continueIfTrue(ifx);
5870           goto release;
5871         }
5872         pic14_emitcode("setb","c");
5873       } else{
5874         // lit == (0 or 1)
5875         if(lit == 0){
5876           // lit == 0, result = left
5877           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5878             goto release;
5879           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5880         } else{
5881           // lit == 1, result = not(left)
5882           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5883             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5884             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5885             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5886             goto release;
5887           } else {
5888             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5889             pic14_emitcode("cpl","c");
5890           }
5891         }
5892       }
5893
5894     } else {
5895       // right != literal
5896       symbol *tlbl = newiTempLabel(NULL);
5897       if (AOP_TYPE(right) == AOP_CRY){
5898         // c = bit ^ bit;
5899         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5900       }
5901       else{
5902         int sizer = AOP_SIZE(right);
5903         // c = bit ^ val
5904         // if val>>1 != 0, result = 1
5905         pic14_emitcode("setb","c");
5906         while(sizer){
5907           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5908           if(sizer == 1)
5909             // test the msb of the lsb
5910             pic14_emitcode("anl","a,#0xfe");
5911           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5912           sizer--;
5913         }
5914         // val = (0,1)
5915         pic14_emitcode("rrc","a");
5916       }
5917       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5918       pic14_emitcode("cpl","c");
5919       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5920     }
5921     // bit = c
5922     // val = c
5923     if(size)
5924       pic14_outBitC(result);
5925     // if(bit | ...)
5926     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5927       genIfxJump(ifx, "c");           
5928     goto release ;
5929   }
5930
5931   if(pic14_sameRegs(AOP(result),AOP(left))){
5932     /* if left is same as result */
5933     for(;size--; offset++) {
5934       if(AOP_TYPE(right) == AOP_LIT){
5935         int t  = (lit >> (offset*8)) & 0x0FFL;
5936         if(t == 0x00L)
5937           continue;
5938         else
5939           if (IS_AOP_PREG(left)) {
5940             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5941             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5942             aopPut(AOP(result),"a",offset);
5943           } else {
5944             emitpcode(POC_MOVLW, popGetLit(t));
5945             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5946             pic14_emitcode("xrl","%s,%s",
5947                            aopGet(AOP(left),offset,FALSE,TRUE),
5948                            aopGet(AOP(right),offset,FALSE,FALSE));
5949           }
5950       } else {
5951         if (AOP_TYPE(left) == AOP_ACC)
5952           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5953         else {
5954           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5955           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5956 /*
5957           if (IS_AOP_PREG(left)) {
5958             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5959             aopPut(AOP(result),"a",offset);
5960           } else
5961             pic14_emitcode("xrl","%s,a",
5962                            aopGet(AOP(left),offset,FALSE,TRUE));
5963 */
5964         }
5965       }
5966     }
5967   } else {
5968     // left & result in different registers
5969     if(AOP_TYPE(result) == AOP_CRY){
5970       // result = bit
5971       // if(size), result in bit
5972       // if(!size && ifx), conditional oper: if(left ^ right)
5973       symbol *tlbl = newiTempLabel(NULL);
5974       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5975       if(size)
5976         pic14_emitcode("setb","c");
5977       while(sizer--){
5978         if((AOP_TYPE(right) == AOP_LIT) &&
5979            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5980           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5981         } else {
5982           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5983           pic14_emitcode("xrl","a,%s",
5984                          aopGet(AOP(left),offset,FALSE,FALSE));
5985         }
5986         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5987         offset++;
5988       }
5989       if(size){
5990         CLRC;
5991         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5992         pic14_outBitC(result);
5993       } else if(ifx)
5994         jmpTrueOrFalse(ifx, tlbl);
5995     } else for(;(size--);offset++){
5996       // normal case
5997       // result = left & right
5998       if(AOP_TYPE(right) == AOP_LIT){
5999         int t = (lit >> (offset*8)) & 0x0FFL;
6000         switch(t) { 
6001         case 0x00:
6002           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6003           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6004           pic14_emitcode("movf","%s,w",
6005                          aopGet(AOP(left),offset,FALSE,FALSE));
6006           pic14_emitcode("movwf","%s",
6007                          aopGet(AOP(result),offset,FALSE,FALSE));
6008           break;
6009         case 0xff:
6010           emitpcode(POC_COMFW,popGet(AOP(left),offset));
6011           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6012           pic14_emitcode("comf","%s,w",
6013                          aopGet(AOP(left),offset,FALSE,FALSE));
6014           pic14_emitcode("movwf","%s",
6015                          aopGet(AOP(result),offset,FALSE,FALSE));
6016           break;
6017         default:
6018           emitpcode(POC_MOVLW, popGetLit(t));
6019           emitpcode(POC_XORFW,popGet(AOP(left),offset));
6020           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6021           pic14_emitcode("movlw","0x%x",t);
6022           pic14_emitcode("xorwf","%s,w",
6023                          aopGet(AOP(left),offset,FALSE,FALSE));
6024           pic14_emitcode("movwf","%s",
6025                          aopGet(AOP(result),offset,FALSE,FALSE));
6026
6027         }
6028         continue;
6029       }
6030
6031       // faster than result <- left, anl result,right
6032       // and better if result is SFR
6033       if (AOP_TYPE(left) == AOP_ACC) {
6034         emitpcode(POC_XORFW,popGet(AOP(right),offset));
6035         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6036       } else {
6037         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6038         emitpcode(POC_XORFW,popGet(AOP(left),offset));
6039         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6040         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
6041       }
6042       if ( AOP_TYPE(result) != AOP_ACC){
6043         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6044         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
6045       }
6046     }
6047   }
6048
6049   release :
6050     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6051   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6052   freeAsmop(result,NULL,ic,TRUE);     
6053 }
6054
6055 /*-----------------------------------------------------------------*/
6056 /* genInline - write the inline code out                           */
6057 /*-----------------------------------------------------------------*/
6058 static void genInline (iCode *ic)
6059 {
6060     char *buffer, *bp, *bp1;
6061     
6062     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6063
6064     _G.inLine += (!options.asmpeep);
6065
6066     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6067     strcpy(buffer,IC_INLINE(ic));
6068
6069     /* emit each line as a code */
6070     while (*bp) {
6071         if (*bp == '\n') {
6072             *bp++ = '\0';
6073
6074             if(*bp1)
6075               addpCode2pBlock(pb,AssembleLine(bp1));
6076             bp1 = bp;
6077         } else {
6078             if (*bp == ':') {
6079                 bp++;
6080                 *bp = '\0';
6081                 bp++;
6082                 pic14_emitcode(bp1,"");
6083                 bp1 = bp;
6084             } else
6085                 bp++;
6086         }
6087     }
6088     if ((bp1 != bp) && *bp1)
6089       addpCode2pBlock(pb,AssembleLine(bp1));
6090
6091     Safe_free(buffer);
6092
6093     _G.inLine -= (!options.asmpeep);
6094 }
6095
6096 /*-----------------------------------------------------------------*/
6097 /* genRRC - rotate right with carry                                */
6098 /*-----------------------------------------------------------------*/
6099 static void genRRC (iCode *ic)
6100 {
6101   operand *left , *result ;
6102   int size, offset = 0, same;
6103
6104   /* rotate right with carry */
6105   left = IC_LEFT(ic);
6106   result=IC_RESULT(ic);
6107   aopOp (left,ic,FALSE);
6108   aopOp (result,ic,FALSE);
6109
6110   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6111
6112   same = pic14_sameRegs(AOP(result),AOP(left));
6113
6114   size = AOP_SIZE(result);    
6115
6116   /* get the lsb and put it into the carry */
6117   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6118
6119   offset = 0 ;
6120
6121   while(size--) {
6122
6123     if(same) {
6124       emitpcode(POC_RRF, popGet(AOP(left),offset));
6125     } else {
6126       emitpcode(POC_RRFW, popGet(AOP(left),offset));
6127       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6128     }
6129
6130     offset++;
6131   }
6132
6133   freeAsmop(left,NULL,ic,TRUE);
6134   freeAsmop(result,NULL,ic,TRUE);
6135 }
6136
6137 /*-----------------------------------------------------------------*/
6138 /* genRLC - generate code for rotate left with carry               */
6139 /*-----------------------------------------------------------------*/
6140 static void genRLC (iCode *ic)
6141 {    
6142   operand *left , *result ;
6143   int size, offset = 0;
6144   int same;
6145
6146   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6147   /* rotate right with carry */
6148   left = IC_LEFT(ic);
6149   result=IC_RESULT(ic);
6150   aopOp (left,ic,FALSE);
6151   aopOp (result,ic,FALSE);
6152
6153   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6154
6155   same = pic14_sameRegs(AOP(result),AOP(left));
6156
6157   /* move it to the result */
6158   size = AOP_SIZE(result);    
6159
6160   /* get the msb and put it into the carry */
6161   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6162
6163   offset = 0 ;
6164
6165   while(size--) {
6166
6167     if(same) {
6168       emitpcode(POC_RLF, popGet(AOP(left),offset));
6169     } else {
6170       emitpcode(POC_RLFW, popGet(AOP(left),offset));
6171       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6172     }
6173
6174     offset++;
6175   }
6176
6177
6178   freeAsmop(left,NULL,ic,TRUE);
6179   freeAsmop(result,NULL,ic,TRUE);
6180 }
6181
6182 /*-----------------------------------------------------------------*/
6183 /* genGetHbit - generates code get highest order bit               */
6184 /*-----------------------------------------------------------------*/
6185 static void genGetHbit (iCode *ic)
6186 {
6187     operand *left, *result;
6188     left = IC_LEFT(ic);
6189     result=IC_RESULT(ic);
6190     aopOp (left,ic,FALSE);
6191     aopOp (result,ic,FALSE);
6192
6193     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6194     /* get the highest order byte into a */
6195     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6196     if(AOP_TYPE(result) == AOP_CRY){
6197         pic14_emitcode("rlc","a");
6198         pic14_outBitC(result);
6199     }
6200     else{
6201         pic14_emitcode("rl","a");
6202         pic14_emitcode("anl","a,#0x01");
6203         pic14_outAcc(result);
6204     }
6205
6206
6207     freeAsmop(left,NULL,ic,TRUE);
6208     freeAsmop(result,NULL,ic,TRUE);
6209 }
6210
6211 /*-----------------------------------------------------------------*/
6212 /* AccRol - rotate left accumulator by known count                 */
6213 /*-----------------------------------------------------------------*/
6214 static void AccRol (int shCount)
6215 {
6216     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6217     shCount &= 0x0007;              // shCount : 0..7
6218     switch(shCount){
6219         case 0 :
6220             break;
6221         case 1 :
6222             pic14_emitcode("rl","a");
6223             break;
6224         case 2 :
6225             pic14_emitcode("rl","a");
6226             pic14_emitcode("rl","a");
6227             break;
6228         case 3 :
6229             pic14_emitcode("swap","a");
6230             pic14_emitcode("rr","a");
6231             break;
6232         case 4 :
6233             pic14_emitcode("swap","a");
6234             break;
6235         case 5 :
6236             pic14_emitcode("swap","a");
6237             pic14_emitcode("rl","a");
6238             break;
6239         case 6 :
6240             pic14_emitcode("rr","a");
6241             pic14_emitcode("rr","a");
6242             break;
6243         case 7 :
6244             pic14_emitcode("rr","a");
6245             break;
6246     }
6247 }
6248
6249 /*-----------------------------------------------------------------*/
6250 /* AccLsh - left shift accumulator by known count                  */
6251 /*-----------------------------------------------------------------*/
6252 static void AccLsh (int shCount)
6253 {
6254     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6255     if(shCount != 0){
6256         if(shCount == 1)
6257             pic14_emitcode("add","a,acc");
6258         else 
6259             if(shCount == 2) {
6260             pic14_emitcode("add","a,acc");
6261             pic14_emitcode("add","a,acc");
6262         } else {
6263             /* rotate left accumulator */
6264             AccRol(shCount);
6265             /* and kill the lower order bits */
6266             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6267         }
6268     }
6269 }
6270
6271 /*-----------------------------------------------------------------*/
6272 /* AccRsh - right shift accumulator by known count                 */
6273 /*-----------------------------------------------------------------*/
6274 static void AccRsh (int shCount)
6275 {
6276     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6277     if(shCount != 0){
6278         if(shCount == 1){
6279             CLRC;
6280             pic14_emitcode("rrc","a");
6281         } else {
6282             /* rotate right accumulator */
6283             AccRol(8 - shCount);
6284             /* and kill the higher order bits */
6285             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6286         }
6287     }
6288 }
6289
6290 #if 0
6291 /*-----------------------------------------------------------------*/
6292 /* AccSRsh - signed right shift accumulator by known count                 */
6293 /*-----------------------------------------------------------------*/
6294 static void AccSRsh (int shCount)
6295 {
6296     symbol *tlbl ;
6297     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6298     if(shCount != 0){
6299         if(shCount == 1){
6300             pic14_emitcode("mov","c,acc.7");
6301             pic14_emitcode("rrc","a");
6302         } else if(shCount == 2){
6303             pic14_emitcode("mov","c,acc.7");
6304             pic14_emitcode("rrc","a");
6305             pic14_emitcode("mov","c,acc.7");
6306             pic14_emitcode("rrc","a");
6307         } else {
6308             tlbl = newiTempLabel(NULL);
6309             /* rotate right accumulator */
6310             AccRol(8 - shCount);
6311             /* and kill the higher order bits */
6312             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6313             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6314             pic14_emitcode("orl","a,#0x%02x",
6315                      (unsigned char)~SRMask[shCount]);
6316             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6317         }
6318     }
6319 }
6320 #endif
6321 /*-----------------------------------------------------------------*/
6322 /* shiftR1Left2Result - shift right one byte from left to result   */
6323 /*-----------------------------------------------------------------*/
6324 static void shiftR1Left2ResultSigned (operand *left, int offl,
6325                                 operand *result, int offr,
6326                                 int shCount)
6327 {
6328   int same;
6329
6330   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6331
6332   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6333
6334   switch(shCount) {
6335   case 1:
6336     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6337     if(same) 
6338       emitpcode(POC_RRF, popGet(AOP(result),offr));
6339     else {
6340       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6341       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6342     }
6343
6344     break;
6345   case 2:
6346
6347     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6348     if(same) 
6349       emitpcode(POC_RRF, popGet(AOP(result),offr));
6350     else {
6351       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6352       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6353     }
6354     emitpcode(POC_RLFW, popGet(AOP(result),offr));
6355     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6356
6357     break;
6358
6359   case 3:
6360     if(same)
6361       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6362     else {
6363       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6364       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6365     }
6366
6367     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6368     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6369     emitpcode(POC_ANDLW, popGetLit(0x1f));
6370
6371     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6372     emitpcode(POC_IORLW, popGetLit(0xe0));
6373
6374     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6375     break;
6376
6377   case 4:
6378     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6379     emitpcode(POC_ANDLW,  popGetLit(0x0f));
6380     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6381     emitpcode(POC_IORLW,  popGetLit(0xf0));
6382     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6383     break;
6384   case 5:
6385     if(same) {
6386       emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6387     } else {
6388       emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6389       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6390     }
6391     emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6392     emitpcode(POC_ANDLW,  popGetLit(0x07));
6393     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6394     emitpcode(POC_IORLW,  popGetLit(0xf8));
6395     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6396     break;
6397
6398   case 6:
6399     if(same) {
6400       emitpcode(POC_MOVLW, popGetLit(0x00));
6401       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6402       emitpcode(POC_MOVLW, popGetLit(0xfe));
6403       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6404       emitpcode(POC_IORLW, popGetLit(0x01));
6405       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6406     } else {
6407       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6408       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6409       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6410       emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6411       emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6412     }
6413     break;
6414
6415   case 7:
6416     if(same) {
6417       emitpcode(POC_MOVLW, popGetLit(0x00));
6418       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6419       emitpcode(POC_MOVLW, popGetLit(0xff));
6420       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6421     } else {
6422       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6423       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6424       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6425     }
6426
6427   default:
6428     break;
6429   }
6430 }
6431
6432 /*-----------------------------------------------------------------*/
6433 /* shiftR1Left2Result - shift right one byte from left to result   */
6434 /*-----------------------------------------------------------------*/
6435 static void shiftR1Left2Result (operand *left, int offl,
6436                                 operand *result, int offr,
6437                                 int shCount, int sign)
6438 {
6439   int same;
6440
6441   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6442
6443   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6444
6445   /* Copy the msb into the carry if signed. */
6446   if(sign) {
6447     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6448     return;
6449   }
6450
6451
6452
6453   switch(shCount) {
6454   case 1:
6455     emitCLRC;
6456     if(same) 
6457       emitpcode(POC_RRF, popGet(AOP(result),offr));
6458     else {
6459       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6460       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6461     }
6462     break;
6463   case 2:
6464     emitCLRC;
6465     if(same) {
6466       emitpcode(POC_RRF, popGet(AOP(result),offr));
6467     } else {
6468       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6469       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6470     }
6471     emitCLRC;
6472     emitpcode(POC_RRF, popGet(AOP(result),offr));
6473
6474     break;
6475   case 3:
6476     if(same)
6477       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6478     else {
6479       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6480       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6481     }
6482
6483     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6484     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6485     emitpcode(POC_ANDLW, popGetLit(0x1f));
6486     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6487     break;
6488       
6489   case 4:
6490     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6491     emitpcode(POC_ANDLW, popGetLit(0x0f));
6492     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6493     break;
6494
6495   case 5:
6496     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6497     emitpcode(POC_ANDLW, popGetLit(0x0f));
6498     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6499     emitCLRC;
6500     emitpcode(POC_RRF, popGet(AOP(result),offr));
6501
6502     break;
6503   case 6:
6504
6505     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6506     emitpcode(POC_ANDLW, popGetLit(0x80));
6507     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6508     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6509     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6510     break;
6511
6512   case 7:
6513
6514     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6515     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6516     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6517
6518     break;
6519
6520   default:
6521     break;
6522   }
6523 }
6524
6525 /*-----------------------------------------------------------------*/
6526 /* shiftL1Left2Result - shift left one byte from left to result    */
6527 /*-----------------------------------------------------------------*/
6528 static void shiftL1Left2Result (operand *left, int offl,
6529                                 operand *result, int offr, int shCount)
6530 {
6531   int same;
6532
6533   //    char *l;
6534   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6535
6536   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6537   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6538     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6539     //    MOVA(l);
6540     /* shift left accumulator */
6541     //AccLsh(shCount); // don't comment out just yet...
6542   //    aopPut(AOP(result),"a",offr);
6543
6544   switch(shCount) {
6545   case 1:
6546     /* Shift left 1 bit position */
6547     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6548     if(same) {
6549       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6550     } else {
6551       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6552       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6553     }
6554     break;
6555   case 2:
6556     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6557     emitpcode(POC_ANDLW,popGetLit(0x7e));
6558     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6559     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6560     break;
6561   case 3:
6562     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6563     emitpcode(POC_ANDLW,popGetLit(0x3e));
6564     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6565     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6566     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6567     break;
6568   case 4:
6569     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6570     emitpcode(POC_ANDLW, popGetLit(0xf0));
6571     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6572     break;
6573   case 5:
6574     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6575     emitpcode(POC_ANDLW, popGetLit(0xf0));
6576     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6577     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6578     break;
6579   case 6:
6580     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6581     emitpcode(POC_ANDLW, popGetLit(0x30));
6582     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6583     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6584     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6585     break;
6586   case 7:
6587     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6588     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6589     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6590     break;
6591
6592   default:
6593     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6594   }
6595
6596 }
6597
6598 /*-----------------------------------------------------------------*/
6599 /* movLeft2Result - move byte from left to result                  */
6600 /*-----------------------------------------------------------------*/
6601 static void movLeft2Result (operand *left, int offl,
6602                             operand *result, int offr)
6603 {
6604   char *l;
6605   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6606   if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6607     l = aopGet(AOP(left),offl,FALSE,FALSE);
6608
6609     if (*l == '@' && (IS_AOP_PREG(result))) {
6610       pic14_emitcode("mov","a,%s",l);
6611       aopPut(AOP(result),"a",offr);
6612     } else {
6613       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6614       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6615     }
6616   }
6617 }
6618
6619 /*-----------------------------------------------------------------*/
6620 /* shiftL2Left2Result - shift left two bytes from left to result   */
6621 /*-----------------------------------------------------------------*/
6622 static void shiftL2Left2Result (operand *left, int offl,
6623                                 operand *result, int offr, int shCount)
6624 {
6625
6626
6627   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6628
6629   if(pic14_sameRegs(AOP(result), AOP(left))) {
6630     switch(shCount) {
6631     case 0:
6632       break;
6633     case 1:
6634     case 2:
6635     case 3:
6636
6637       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6638       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6639       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6640
6641       while(--shCount) {
6642         emitCLRC;
6643         emitpcode(POC_RLF, popGet(AOP(result),offr));
6644         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6645       }
6646
6647       break;
6648     case 4:
6649     case 5:
6650       emitpcode(POC_MOVLW, popGetLit(0x0f));
6651       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6652       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6653       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6654       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6655       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6656       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6657       if(shCount >=5) {
6658         emitpcode(POC_RLF, popGet(AOP(result),offr));
6659         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6660       }
6661       break;
6662     case 6:
6663       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6664       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6665       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6666       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6667       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6668       emitpcode(POC_ANDLW,popGetLit(0xc0));
6669       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6670       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6671       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6672       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6673       break;
6674     case 7:
6675       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6676       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6677       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6678       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6679       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6680     }
6681
6682   } else {
6683     switch(shCount) {
6684     case 0:
6685       break;
6686     case 1:
6687     case 2:
6688     case 3:
6689       /* note, use a mov/add for the shift since the mov has a
6690          chance of getting optimized out */
6691       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6692       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6693       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6694       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6695       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6696
6697       while(--shCount) {
6698         emitCLRC;
6699         emitpcode(POC_RLF, popGet(AOP(result),offr));
6700         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6701       }
6702       break;
6703
6704     case 4:
6705     case 5:
6706       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6707       emitpcode(POC_ANDLW, popGetLit(0xF0));
6708       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6709       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6710       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6711       emitpcode(POC_ANDLW, popGetLit(0xF0));
6712       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6713       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6714
6715
6716       if(shCount == 5) {
6717         emitpcode(POC_RLF, popGet(AOP(result),offr));
6718         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6719       }
6720       break;
6721     case 6:
6722       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6723       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6724       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6725       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6726
6727       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6728       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6729       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6730       emitpcode(POC_ANDLW,popGetLit(0xc0));
6731       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6732       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6733       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6734       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6735       break;
6736     case 7:
6737       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6738       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6739       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6740       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6741       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6742     }
6743   }
6744
6745 }
6746 /*-----------------------------------------------------------------*/
6747 /* shiftR2Left2Result - shift right two bytes from left to result  */
6748 /*-----------------------------------------------------------------*/
6749 static void shiftR2Left2Result (operand *left, int offl,
6750                                 operand *result, int offr,
6751                                 int shCount, int sign)
6752 {
6753   int same=0;
6754
6755   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6756   same = pic14_sameRegs(AOP(result), AOP(left));
6757
6758   if(same && ((offl + MSB16) == offr)){
6759     same=1;
6760     /* don't crash result[offr] */
6761     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6762     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6763   }
6764 /* else {
6765     movLeft2Result(left,offl, result, offr);
6766     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6767   }
6768 */
6769   /* a:x >> shCount (x = lsb(result))*/
6770 /*
6771   if(sign)
6772     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6773   else {
6774     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6775 */
6776   switch(shCount) {
6777   case 0:
6778     break;
6779   case 1:
6780   case 2:
6781   case 3:
6782     if(sign)
6783       emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6784     else
6785       emitCLRC;
6786
6787     if(same) {
6788       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6789       emitpcode(POC_RRF,popGet(AOP(result),offr));
6790     } else {
6791       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6792       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6793       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6794       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6795     }
6796
6797     while(--shCount) {
6798       if(sign)
6799         emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6800       else
6801         emitCLRC;
6802       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6803       emitpcode(POC_RRF,popGet(AOP(result),offr));
6804     }
6805     break;
6806   case 4:
6807   case 5:
6808     if(same) {
6809
6810       emitpcode(POC_MOVLW, popGetLit(0xf0));
6811       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6812       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6813
6814       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6815       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6816       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6817       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6818     } else {
6819       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6820       emitpcode(POC_ANDLW, popGetLit(0x0f));
6821       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6822
6823       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6824       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6825       emitpcode(POC_ANDLW, popGetLit(0xf0));
6826       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6827       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6828     }
6829
6830     if(shCount >=5) {
6831       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6832       emitpcode(POC_RRF, popGet(AOP(result),offr));
6833     }
6834
6835     if(sign) {
6836       emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6837       emitpcode(POC_BTFSC, 
6838                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6839       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6840     }
6841
6842     break;
6843
6844   case 6:
6845     if(same) {
6846
6847       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6848       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6849
6850       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6851       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6852       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6853       emitpcode(POC_ANDLW,popGetLit(0x03));
6854       if(sign) {
6855         emitpcode(POC_BTFSC, 
6856                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6857         emitpcode(POC_IORLW,popGetLit(0xfc));
6858       }
6859       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6860       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6861       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6862       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6863     } else {
6864       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6865       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6866       emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6867       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6868       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6869       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6870       emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6871       emitpcode(POC_ANDLW,popGetLit(0x03));
6872       if(sign) {
6873         emitpcode(POC_BTFSC, 
6874                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6875         emitpcode(POC_IORLW,popGetLit(0xfc));
6876       }
6877       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6878       //emitpcode(POC_RLF,  popGet(AOP(result),offr));
6879
6880         
6881     }
6882
6883     break;
6884   case 7:
6885     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6886     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6887     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6888     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6889     if(sign) {
6890       emitSKPNC;
6891       emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6892     } else 
6893       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6894   }
6895 }
6896
6897
6898 /*-----------------------------------------------------------------*/
6899 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6900 /*-----------------------------------------------------------------*/
6901 static void shiftLLeftOrResult (operand *left, int offl,
6902                                 operand *result, int offr, int shCount)
6903 {
6904     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6905     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6906     /* shift left accumulator */
6907     AccLsh(shCount);
6908     /* or with result */
6909     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6910     /* back to result */
6911     aopPut(AOP(result),"a",offr);
6912 }
6913
6914 /*-----------------------------------------------------------------*/
6915 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6916 /*-----------------------------------------------------------------*/
6917 static void shiftRLeftOrResult (operand *left, int offl,
6918                                 operand *result, int offr, int shCount)
6919 {
6920     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6921     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6922     /* shift right accumulator */
6923     AccRsh(shCount);
6924     /* or with result */
6925     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6926     /* back to result */
6927     aopPut(AOP(result),"a",offr);
6928 }
6929
6930 /*-----------------------------------------------------------------*/
6931 /* genlshOne - left shift a one byte quantity by known count       */
6932 /*-----------------------------------------------------------------*/
6933 static void genlshOne (operand *result, operand *left, int shCount)
6934 {       
6935     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6936     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6937 }
6938
6939 /*-----------------------------------------------------------------*/
6940 /* genlshTwo - left shift two bytes by known amount != 0           */
6941 /*-----------------------------------------------------------------*/
6942 static void genlshTwo (operand *result,operand *left, int shCount)
6943 {
6944     int size;
6945     
6946     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6947     size = pic14_getDataSize(result);
6948
6949     /* if shCount >= 8 */
6950     if (shCount >= 8) {
6951         shCount -= 8 ;
6952
6953         if (size > 1){
6954             if (shCount)
6955                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6956             else 
6957                 movLeft2Result(left, LSB, result, MSB16);
6958         }
6959         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6960     }
6961
6962     /*  1 <= shCount <= 7 */
6963     else {  
6964         if(size == 1)
6965             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6966         else 
6967             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6968     }
6969 }
6970
6971 /*-----------------------------------------------------------------*/
6972 /* shiftLLong - shift left one long from left to result            */
6973 /* offl = LSB or MSB16                                             */
6974 /*-----------------------------------------------------------------*/
6975 static void shiftLLong (operand *left, operand *result, int offr )
6976 {
6977     char *l;
6978     int size = AOP_SIZE(result);
6979
6980     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6981     if(size >= LSB+offr){
6982         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6983         MOVA(l);
6984         pic14_emitcode("add","a,acc");
6985         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6986             size >= MSB16+offr && offr != LSB )
6987             pic14_emitcode("xch","a,%s",
6988                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6989         else        
6990             aopPut(AOP(result),"a",LSB+offr);
6991     }
6992
6993     if(size >= MSB16+offr){
6994         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6995             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6996             MOVA(l);
6997         }
6998         pic14_emitcode("rlc","a");
6999         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7000             size >= MSB24+offr && offr != LSB)
7001             pic14_emitcode("xch","a,%s",
7002                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7003         else        
7004             aopPut(AOP(result),"a",MSB16+offr);
7005     }
7006
7007     if(size >= MSB24+offr){
7008         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7009             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7010             MOVA(l);
7011         }
7012         pic14_emitcode("rlc","a");
7013         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7014             size >= MSB32+offr && offr != LSB )
7015             pic14_emitcode("xch","a,%s",
7016                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7017         else        
7018             aopPut(AOP(result),"a",MSB24+offr);
7019     }
7020
7021     if(size > MSB32+offr){
7022         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7023             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7024             MOVA(l);    
7025         }
7026         pic14_emitcode("rlc","a");
7027         aopPut(AOP(result),"a",MSB32+offr);
7028     }
7029     if(offr != LSB)
7030         aopPut(AOP(result),zero,LSB);       
7031 }
7032
7033 /*-----------------------------------------------------------------*/
7034 /* genlshFour - shift four byte by a known amount != 0             */
7035 /*-----------------------------------------------------------------*/
7036 static void genlshFour (operand *result, operand *left, int shCount)
7037 {
7038     int size;
7039
7040     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7041     size = AOP_SIZE(result);
7042
7043     /* if shifting more that 3 bytes */
7044     if (shCount >= 24 ) {
7045         shCount -= 24;
7046         if (shCount)
7047             /* lowest order of left goes to the highest
7048             order of the destination */
7049             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7050         else
7051             movLeft2Result(left, LSB, result, MSB32);
7052         aopPut(AOP(result),zero,LSB);
7053         aopPut(AOP(result),zero,MSB16);
7054         aopPut(AOP(result),zero,MSB32);
7055         return;
7056     }
7057
7058     /* more than two bytes */
7059     else if ( shCount >= 16 ) {
7060         /* lower order two bytes goes to higher order two bytes */
7061         shCount -= 16;
7062         /* if some more remaining */
7063         if (shCount)
7064             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7065         else {
7066             movLeft2Result(left, MSB16, result, MSB32);
7067             movLeft2Result(left, LSB, result, MSB24);
7068         }
7069         aopPut(AOP(result),zero,MSB16);
7070         aopPut(AOP(result),zero,LSB);
7071         return;
7072     }    
7073
7074     /* if more than 1 byte */
7075     else if ( shCount >= 8 ) {
7076         /* lower order three bytes goes to higher order  three bytes */
7077         shCount -= 8;
7078         if(size == 2){
7079             if(shCount)
7080                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7081             else
7082                 movLeft2Result(left, LSB, result, MSB16);
7083         }
7084         else{   /* size = 4 */
7085             if(shCount == 0){
7086                 movLeft2Result(left, MSB24, result, MSB32);
7087                 movLeft2Result(left, MSB16, result, MSB24);
7088                 movLeft2Result(left, LSB, result, MSB16);
7089                 aopPut(AOP(result),zero,LSB);
7090             }
7091             else if(shCount == 1)
7092                 shiftLLong(left, result, MSB16);
7093             else{
7094                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7095                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7096                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7097                 aopPut(AOP(result),zero,LSB);
7098             }
7099         }
7100     }
7101
7102     /* 1 <= shCount <= 7 */
7103     else if(shCount <= 2){
7104         shiftLLong(left, result, LSB);
7105         if(shCount == 2)
7106             shiftLLong(result, result, LSB);
7107     }
7108     /* 3 <= shCount <= 7, optimize */
7109     else{
7110         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7111         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7112         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7113     }
7114 }
7115
7116 /*-----------------------------------------------------------------*/
7117 /* genLeftShiftLiteral - left shifting by known count              */
7118 /*-----------------------------------------------------------------*/
7119 static void genLeftShiftLiteral (operand *left,
7120                                  operand *right,
7121                                  operand *result,
7122                                  iCode *ic)
7123 {    
7124     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7125     int size;
7126
7127     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7128     freeAsmop(right,NULL,ic,TRUE);
7129
7130     aopOp(left,ic,FALSE);
7131     aopOp(result,ic,FALSE);
7132
7133     size = getSize(operandType(result));
7134
7135 #if VIEW_SIZE
7136     pic14_emitcode("; shift left ","result %d, left %d",size,
7137              AOP_SIZE(left));
7138 #endif
7139
7140     /* I suppose that the left size >= result size */
7141     if(shCount == 0){
7142         while(size--){
7143             movLeft2Result(left, size, result, size);
7144         }
7145     }
7146
7147     else if(shCount >= (size * 8))
7148         while(size--)
7149             aopPut(AOP(result),zero,size);
7150     else{
7151         switch (size) {
7152             case 1:
7153                 genlshOne (result,left,shCount);
7154                 break;
7155
7156             case 2:
7157             case 3:
7158                 genlshTwo (result,left,shCount);
7159                 break;
7160
7161             case 4:
7162                 genlshFour (result,left,shCount);
7163                 break;
7164         }
7165     }
7166     freeAsmop(left,NULL,ic,TRUE);
7167     freeAsmop(result,NULL,ic,TRUE);
7168 }
7169
7170 /*-----------------------------------------------------------------*
7171  * genMultiAsm - repeat assembly instruction for size of register.
7172  * if endian == 1, then the high byte (i.e base address + size of 
7173  * register) is used first else the low byte is used first;
7174  *-----------------------------------------------------------------*/
7175 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7176 {
7177
7178   int offset = 0;
7179
7180   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7181
7182   if(!reg)
7183     return;
7184
7185   if(!endian) {
7186     endian = 1;
7187   } else {
7188     endian = -1;
7189     offset = size-1;
7190   }
7191
7192   while(size--) {
7193     emitpcode(poc,    popGet(AOP(reg),offset));
7194     offset += endian;
7195   }
7196
7197 }
7198 /*-----------------------------------------------------------------*/
7199 /* genLeftShift - generates code for left shifting                 */
7200 /*-----------------------------------------------------------------*/
7201 static void genLeftShift (iCode *ic)
7202 {
7203   operand *left,*right, *result;
7204   int size, offset;
7205   char *l;
7206   symbol *tlbl , *tlbl1;
7207   pCodeOp *pctemp;
7208
7209   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7210
7211   right = IC_RIGHT(ic);
7212   left  = IC_LEFT(ic);
7213   result = IC_RESULT(ic);
7214
7215   aopOp(right,ic,FALSE);
7216
7217   /* if the shift count is known then do it 
7218      as efficiently as possible */
7219   if (AOP_TYPE(right) == AOP_LIT) {
7220     genLeftShiftLiteral (left,right,result,ic);
7221     return ;
7222   }
7223
7224   /* shift count is unknown then we have to form 
7225      a loop get the loop count in B : Note: we take
7226      only the lower order byte since shifting
7227      more that 32 bits make no sense anyway, ( the
7228      largest size of an object can be only 32 bits ) */  
7229
7230     
7231   aopOp(left,ic,FALSE);
7232   aopOp(result,ic,FALSE);
7233
7234   /* now move the left to the result if they are not the
7235      same */
7236   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7237       AOP_SIZE(result) > 1) {
7238
7239     size = AOP_SIZE(result);
7240     offset=0;
7241     while (size--) {
7242       l = aopGet(AOP(left),offset,FALSE,TRUE);
7243       if (*l == '@' && (IS_AOP_PREG(result))) {
7244
7245         pic14_emitcode("mov","a,%s",l);
7246         aopPut(AOP(result),"a",offset);
7247       } else {
7248         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7249         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7250         //aopPut(AOP(result),l,offset);
7251       }
7252       offset++;
7253     }
7254   }
7255
7256   size = AOP_SIZE(result);
7257
7258   /* if it is only one byte then */
7259   if (size == 1) {
7260     if(optimized_for_speed) {
7261       emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7262       emitpcode(POC_ANDLW,  popGetLit(0xf0));
7263       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7264       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7265       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7266       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7267       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7268       emitpcode(POC_RLFW,   popGet(AOP(result),0));
7269       emitpcode(POC_ANDLW,  popGetLit(0xfe));
7270       emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7271       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7272       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7273     } else {
7274
7275       tlbl = newiTempLabel(NULL);
7276       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7277         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7278         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7279       }
7280
7281       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7282       emitpcode(POC_RRF,    popGet(AOP(result),0));
7283       emitpLabel(tlbl->key);
7284       emitpcode(POC_RLF,    popGet(AOP(result),0));
7285       emitpcode(POC_ADDLW,  popGetLit(1));
7286       emitSKPC;
7287       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7288     }
7289     goto release ;
7290   }
7291     
7292   if (pic14_sameRegs(AOP(left),AOP(result))) {
7293
7294     tlbl = newiTempLabel(NULL);
7295     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7296     genMultiAsm(POC_RRF, result, size,1);
7297     emitpLabel(tlbl->key);
7298     genMultiAsm(POC_RLF, result, size,0);
7299     emitpcode(POC_ADDLW,  popGetLit(1));
7300     emitSKPC;
7301     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7302     goto release;
7303   }
7304
7305   //tlbl = newiTempLabel(NULL);
7306   //offset = 0 ;   
7307   //tlbl1 = newiTempLabel(NULL);
7308
7309   //reAdjustPreg(AOP(result));    
7310     
7311   //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7312   //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7313   //l = aopGet(AOP(result),offset,FALSE,FALSE);
7314   //MOVA(l);
7315   //pic14_emitcode("add","a,acc");         
7316   //aopPut(AOP(result),"a",offset++);
7317   //while (--size) {
7318   //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7319   //  MOVA(l);
7320   //  pic14_emitcode("rlc","a");         
7321   //  aopPut(AOP(result),"a",offset++);
7322   //}
7323   //reAdjustPreg(AOP(result));
7324
7325   //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7326   //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7327
7328
7329   tlbl = newiTempLabel(NULL);
7330   tlbl1= newiTempLabel(NULL);
7331
7332   size = AOP_SIZE(result);
7333   offset = 1;
7334
7335   pctemp = popGetTempReg();  /* grab a temporary working register. */
7336
7337   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7338
7339   /* offset should be 0, 1 or 3 */
7340   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7341   emitSKPNZ;
7342   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7343
7344   emitpcode(POC_MOVWF, pctemp);
7345
7346
7347   emitpLabel(tlbl->key);
7348
7349   emitCLRC;
7350   emitpcode(POC_RLF,  popGet(AOP(result),0));
7351   while(--size)
7352     emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7353
7354   emitpcode(POC_DECFSZ,  pctemp);
7355   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7356   emitpLabel(tlbl1->key);
7357
7358   popReleaseTempReg(pctemp);
7359
7360
7361  release:
7362   freeAsmop (right,NULL,ic,TRUE);
7363   freeAsmop(left,NULL,ic,TRUE);
7364   freeAsmop(result,NULL,ic,TRUE);
7365 }
7366
7367 /*-----------------------------------------------------------------*/
7368 /* genrshOne - right shift a one byte quantity by known count      */
7369 /*-----------------------------------------------------------------*/
7370 static void genrshOne (operand *result, operand *left,
7371                        int shCount, int sign)
7372 {
7373     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7374     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7375 }
7376
7377 /*-----------------------------------------------------------------*/
7378 /* genrshTwo - right shift two bytes by known amount != 0          */
7379 /*-----------------------------------------------------------------*/
7380 static void genrshTwo (operand *result,operand *left,
7381                        int shCount, int sign)
7382 {
7383   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7384   /* if shCount >= 8 */
7385   if (shCount >= 8) {
7386     shCount -= 8 ;
7387     if (shCount)
7388       shiftR1Left2Result(left, MSB16, result, LSB,
7389                          shCount, sign);
7390     else
7391       movLeft2Result(left, MSB16, result, LSB);
7392
7393     emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7394
7395     if(sign) {
7396       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7397       emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7398     }
7399   }
7400
7401   /*  1 <= shCount <= 7 */
7402   else
7403     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7404 }
7405
7406 /*-----------------------------------------------------------------*/
7407 /* shiftRLong - shift right one long from left to result           */
7408 /* offl = LSB or MSB16                                             */
7409 /*-----------------------------------------------------------------*/
7410 static void shiftRLong (operand *left, int offl,
7411                         operand *result, int sign)
7412 {
7413     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7414     if(!sign)
7415         pic14_emitcode("clr","c");
7416     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7417     if(sign)
7418         pic14_emitcode("mov","c,acc.7");
7419     pic14_emitcode("rrc","a");
7420     aopPut(AOP(result),"a",MSB32-offl);
7421     if(offl == MSB16)
7422         /* add sign of "a" */
7423         addSign(result, MSB32, sign);
7424
7425     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7426     pic14_emitcode("rrc","a");
7427     aopPut(AOP(result),"a",MSB24-offl);
7428
7429     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7430     pic14_emitcode("rrc","a");
7431     aopPut(AOP(result),"a",MSB16-offl);
7432
7433     if(offl == LSB){
7434         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7435         pic14_emitcode("rrc","a");
7436         aopPut(AOP(result),"a",LSB);
7437     }
7438 }
7439
7440 /*-----------------------------------------------------------------*/
7441 /* genrshFour - shift four byte by a known amount != 0             */
7442 /*-----------------------------------------------------------------*/
7443 static void genrshFour (operand *result, operand *left,
7444                         int shCount, int sign)
7445 {
7446   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7447   /* if shifting more that 3 bytes */
7448   if(shCount >= 24 ) {
7449     shCount -= 24;
7450     if(shCount)
7451       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7452     else
7453       movLeft2Result(left, MSB32, result, LSB);
7454
7455     addSign(result, MSB16, sign);
7456   }
7457   else if(shCount >= 16){
7458     shCount -= 16;
7459     if(shCount)
7460       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7461     else{
7462       movLeft2Result(left, MSB24, result, LSB);
7463       movLeft2Result(left, MSB32, result, MSB16);
7464     }
7465     addSign(result, MSB24, sign);
7466   }
7467   else if(shCount >= 8){
7468     shCount -= 8;
7469     if(shCount == 1)
7470       shiftRLong(left, MSB16, result, sign);
7471     else if(shCount == 0){
7472       movLeft2Result(left, MSB16, result, LSB);
7473       movLeft2Result(left, MSB24, result, MSB16);
7474       movLeft2Result(left, MSB32, result, MSB24);
7475       addSign(result, MSB32, sign);
7476     }
7477     else{
7478       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7479       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7480       /* the last shift is signed */
7481       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7482       addSign(result, MSB32, sign);
7483     }
7484   }
7485   else{   /* 1 <= shCount <= 7 */
7486     if(shCount <= 2){
7487       shiftRLong(left, LSB, result, sign);
7488       if(shCount == 2)
7489         shiftRLong(result, LSB, result, sign);
7490     }
7491     else{
7492       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7493       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7494       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7495     }
7496   }
7497 }
7498
7499 /*-----------------------------------------------------------------*/
7500 /* genRightShiftLiteral - right shifting by known count            */
7501 /*-----------------------------------------------------------------*/
7502 static void genRightShiftLiteral (operand *left,
7503                                   operand *right,
7504                                   operand *result,
7505                                   iCode *ic,
7506                                   int sign)
7507 {    
7508   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7509   int lsize,res_size;
7510
7511   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7512   freeAsmop(right,NULL,ic,TRUE);
7513
7514   aopOp(left,ic,FALSE);
7515   aopOp(result,ic,FALSE);
7516
7517 #if VIEW_SIZE
7518   pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7519                  AOP_SIZE(left));
7520 #endif
7521
7522   lsize = pic14_getDataSize(left);
7523   res_size = pic14_getDataSize(result);
7524   /* test the LEFT size !!! */
7525
7526   /* I suppose that the left size >= result size */
7527   if(shCount == 0){
7528     while(res_size--)
7529       movLeft2Result(left, lsize, result, res_size);
7530   }
7531
7532   else if(shCount >= (lsize * 8)){
7533
7534     if(res_size == 1) {
7535       emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7536       if(sign) {
7537         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7538         emitpcode(POC_DECF, popGet(AOP(result),LSB));
7539       }
7540     } else {
7541
7542       if(sign) {
7543         emitpcode(POC_MOVLW, popGetLit(0));
7544         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7545         emitpcode(POC_MOVLW, popGetLit(0xff));
7546         while(res_size--)
7547           emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7548
7549       } else {
7550
7551         while(res_size--)
7552           emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7553       }
7554     }
7555   } else {
7556
7557     switch (res_size) {
7558     case 1:
7559       genrshOne (result,left,shCount,sign);
7560       break;
7561
7562     case 2:
7563       genrshTwo (result,left,shCount,sign);
7564       break;
7565
7566     case 4:
7567       genrshFour (result,left,shCount,sign);
7568       break;
7569     default :
7570       break;
7571     }
7572
7573   }
7574
7575   freeAsmop(left,NULL,ic,TRUE);
7576   freeAsmop(result,NULL,ic,TRUE);
7577 }
7578
7579 /*-----------------------------------------------------------------*/
7580 /* genSignedRightShift - right shift of signed number              */
7581 /*-----------------------------------------------------------------*/
7582 static void genSignedRightShift (iCode *ic)
7583 {
7584   operand *right, *left, *result;
7585   int size, offset;
7586   //  char *l;
7587   symbol *tlbl, *tlbl1 ;
7588   pCodeOp *pctemp;
7589
7590   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7591
7592   /* we do it the hard way put the shift count in b
7593      and loop thru preserving the sign */
7594   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7595
7596   right = IC_RIGHT(ic);
7597   left  = IC_LEFT(ic);
7598   result = IC_RESULT(ic);
7599
7600   aopOp(right,ic,FALSE);  
7601   aopOp(left,ic,FALSE);
7602   aopOp(result,ic,FALSE);
7603
7604
7605   if ( AOP_TYPE(right) == AOP_LIT) {
7606     genRightShiftLiteral (left,right,result,ic,1);
7607     return ;
7608   }
7609   /* shift count is unknown then we have to form 
7610      a loop get the loop count in B : Note: we take
7611      only the lower order byte since shifting
7612      more that 32 bits make no sense anyway, ( the
7613      largest size of an object can be only 32 bits ) */  
7614
7615   //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7616   //pic14_emitcode("inc","b");
7617   //freeAsmop (right,NULL,ic,TRUE);
7618   //aopOp(left,ic,FALSE);
7619   //aopOp(result,ic,FALSE);
7620
7621   /* now move the left to the result if they are not the
7622      same */
7623   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7624       AOP_SIZE(result) > 1) {
7625
7626     size = AOP_SIZE(result);
7627     offset=0;
7628     while (size--) { 
7629       /*
7630         l = aopGet(AOP(left),offset,FALSE,TRUE);
7631         if (*l == '@' && IS_AOP_PREG(result)) {
7632
7633         pic14_emitcode("mov","a,%s",l);
7634         aopPut(AOP(result),"a",offset);
7635         } else
7636         aopPut(AOP(result),l,offset);
7637       */
7638       emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7639       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7640
7641       offset++;
7642     }
7643   }
7644
7645   /* mov the highest order bit to OVR */    
7646   tlbl = newiTempLabel(NULL);
7647   tlbl1= newiTempLabel(NULL);
7648
7649   size = AOP_SIZE(result);
7650   offset = size - 1;
7651
7652   pctemp = popGetTempReg();  /* grab a temporary working register. */
7653
7654   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7655
7656   /* offset should be 0, 1 or 3 */
7657   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7658   emitSKPNZ;
7659   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7660
7661   emitpcode(POC_MOVWF, pctemp);
7662
7663
7664   emitpLabel(tlbl->key);
7665
7666   emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7667   emitpcode(POC_RRF,   popGet(AOP(result),offset));
7668
7669   while(--size) {
7670     emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7671   }
7672
7673   emitpcode(POC_DECFSZ,  pctemp);
7674   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7675   emitpLabel(tlbl1->key);
7676
7677   popReleaseTempReg(pctemp);
7678 #if 0
7679   size = AOP_SIZE(result);
7680   offset = size - 1;
7681   pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7682   pic14_emitcode("rlc","a");
7683   pic14_emitcode("mov","ov,c");
7684   /* if it is only one byte then */
7685   if (size == 1) {
7686     l = aopGet(AOP(left),0,FALSE,FALSE);
7687     MOVA(l);
7688     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7689     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7690     pic14_emitcode("mov","c,ov");
7691     pic14_emitcode("rrc","a");
7692     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7693     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7694     aopPut(AOP(result),"a",0);
7695     goto release ;
7696   }
7697
7698   reAdjustPreg(AOP(result));
7699   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7700   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7701   pic14_emitcode("mov","c,ov");
7702   while (size--) {
7703     l = aopGet(AOP(result),offset,FALSE,FALSE);
7704     MOVA(l);
7705     pic14_emitcode("rrc","a");         
7706     aopPut(AOP(result),"a",offset--);
7707   }
7708   reAdjustPreg(AOP(result));
7709   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7710   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7711
7712  release:
7713 #endif
7714
7715   freeAsmop(left,NULL,ic,TRUE);
7716   freeAsmop(result,NULL,ic,TRUE);
7717   freeAsmop(right,NULL,ic,TRUE);
7718 }
7719
7720 /*-----------------------------------------------------------------*/
7721 /* genRightShift - generate code for right shifting                */
7722 /*-----------------------------------------------------------------*/
7723 static void genRightShift (iCode *ic)
7724 {
7725     operand *right, *left, *result;
7726     sym_link *retype ;
7727     int size, offset;
7728     char *l;
7729     symbol *tlbl, *tlbl1 ;
7730
7731     /* if signed then we do it the hard way preserve the
7732     sign bit moving it inwards */
7733     retype = getSpec(operandType(IC_RESULT(ic)));
7734     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7735
7736     if (!SPEC_USIGN(retype)) {
7737         genSignedRightShift (ic);
7738         return ;
7739     }
7740
7741     /* signed & unsigned types are treated the same : i.e. the
7742     signed is NOT propagated inwards : quoting from the
7743     ANSI - standard : "for E1 >> E2, is equivalent to division
7744     by 2**E2 if unsigned or if it has a non-negative value,
7745     otherwise the result is implementation defined ", MY definition
7746     is that the sign does not get propagated */
7747
7748     right = IC_RIGHT(ic);
7749     left  = IC_LEFT(ic);
7750     result = IC_RESULT(ic);
7751
7752     aopOp(right,ic,FALSE);
7753
7754     /* if the shift count is known then do it 
7755     as efficiently as possible */
7756     if (AOP_TYPE(right) == AOP_LIT) {
7757         genRightShiftLiteral (left,right,result,ic, 0);
7758         return ;
7759     }
7760
7761     /* shift count is unknown then we have to form 
7762     a loop get the loop count in B : Note: we take
7763     only the lower order byte since shifting
7764     more that 32 bits make no sense anyway, ( the
7765     largest size of an object can be only 32 bits ) */  
7766
7767     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7768     pic14_emitcode("inc","b");
7769     aopOp(left,ic,FALSE);
7770     aopOp(result,ic,FALSE);
7771
7772     /* now move the left to the result if they are not the
7773     same */
7774     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7775         AOP_SIZE(result) > 1) {
7776
7777         size = AOP_SIZE(result);
7778         offset=0;
7779         while (size--) {
7780             l = aopGet(AOP(left),offset,FALSE,TRUE);
7781             if (*l == '@' && IS_AOP_PREG(result)) {
7782
7783                 pic14_emitcode("mov","a,%s",l);
7784                 aopPut(AOP(result),"a",offset);
7785             } else
7786                 aopPut(AOP(result),l,offset);
7787             offset++;
7788         }
7789     }
7790
7791     tlbl = newiTempLabel(NULL);
7792     tlbl1= newiTempLabel(NULL);
7793     size = AOP_SIZE(result);
7794     offset = size - 1;
7795
7796     /* if it is only one byte then */
7797     if (size == 1) {
7798
7799       tlbl = newiTempLabel(NULL);
7800       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7801         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7802         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7803       }
7804
7805       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7806       emitpcode(POC_RLF,    popGet(AOP(result),0));
7807       emitpLabel(tlbl->key);
7808       emitpcode(POC_RRF,    popGet(AOP(result),0));
7809       emitpcode(POC_ADDLW,  popGetLit(1));
7810       emitSKPC;
7811       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7812
7813       goto release ;
7814     }
7815
7816     reAdjustPreg(AOP(result));
7817     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7818     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7819     CLRC;
7820     while (size--) {
7821         l = aopGet(AOP(result),offset,FALSE,FALSE);
7822         MOVA(l);
7823         pic14_emitcode("rrc","a");         
7824         aopPut(AOP(result),"a",offset--);
7825     }
7826     reAdjustPreg(AOP(result));
7827
7828     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7829     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7830
7831 release:
7832     freeAsmop(left,NULL,ic,TRUE);
7833     freeAsmop (right,NULL,ic,TRUE);
7834     freeAsmop(result,NULL,ic,TRUE);
7835 }
7836
7837 /*-----------------------------------------------------------------*/
7838 /* genUnpackBits - generates code for unpacking bits               */
7839 /*-----------------------------------------------------------------*/
7840 static void genUnpackBits (operand *result, char *rname, int ptype)
7841 {    
7842     int shCnt ;
7843     int rlen = 0 ;
7844     sym_link *etype;
7845     int offset = 0 ;
7846
7847     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7848     etype = getSpec(operandType(result));
7849
7850     /* read the first byte  */
7851     switch (ptype) {
7852
7853     case POINTER:
7854     case IPOINTER:
7855         pic14_emitcode("mov","a,@%s",rname);
7856         break;
7857         
7858     case PPOINTER:
7859         pic14_emitcode("movx","a,@%s",rname);
7860         break;
7861         
7862     case FPOINTER:
7863         pic14_emitcode("movx","a,@dptr");
7864         break;
7865
7866     case CPOINTER:
7867         pic14_emitcode("clr","a");
7868         pic14_emitcode("movc","a","@a+dptr");
7869         break;
7870
7871     case GPOINTER:
7872         pic14_emitcode("lcall","__gptrget");
7873         break;
7874     }
7875
7876     /* if we have bitdisplacement then it fits   */
7877     /* into this byte completely or if length is */
7878     /* less than a byte                          */
7879     if ((shCnt = SPEC_BSTR(etype)) || 
7880         (SPEC_BLEN(etype) <= 8))  {
7881
7882         /* shift right acc */
7883         AccRsh(shCnt);
7884
7885         pic14_emitcode("anl","a,#0x%02x",
7886                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7887         aopPut(AOP(result),"a",offset);
7888         return ;
7889     }
7890
7891     /* bit field did not fit in a byte  */
7892     rlen = SPEC_BLEN(etype) - 8;
7893     aopPut(AOP(result),"a",offset++);
7894
7895     while (1)  {
7896
7897         switch (ptype) {
7898         case POINTER:
7899         case IPOINTER:
7900             pic14_emitcode("inc","%s",rname);
7901             pic14_emitcode("mov","a,@%s",rname);
7902             break;
7903             
7904         case PPOINTER:
7905             pic14_emitcode("inc","%s",rname);
7906             pic14_emitcode("movx","a,@%s",rname);
7907             break;
7908
7909         case FPOINTER:
7910             pic14_emitcode("inc","dptr");
7911             pic14_emitcode("movx","a,@dptr");
7912             break;
7913             
7914         case CPOINTER:
7915             pic14_emitcode("clr","a");
7916             pic14_emitcode("inc","dptr");
7917             pic14_emitcode("movc","a","@a+dptr");
7918             break;
7919             
7920         case GPOINTER:
7921             pic14_emitcode("inc","dptr");
7922             pic14_emitcode("lcall","__gptrget");
7923             break;
7924         }
7925
7926         rlen -= 8;            
7927         /* if we are done */
7928         if ( rlen <= 0 )
7929             break ;
7930         
7931         aopPut(AOP(result),"a",offset++);
7932                               
7933     }
7934     
7935     if (rlen) {
7936         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7937         aopPut(AOP(result),"a",offset);        
7938     }
7939     
7940     return ;
7941 }
7942
7943 #if 0
7944 /*-----------------------------------------------------------------*/
7945 /* genDataPointerGet - generates code when ptr offset is known     */
7946 /*-----------------------------------------------------------------*/
7947 static void genDataPointerGet (operand *left, 
7948                                operand *result, 
7949                                iCode *ic)
7950 {
7951   int size , offset = 0;
7952
7953
7954   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7955
7956
7957   /* optimization - most of the time, left and result are the same
7958    * address, but different types. for the pic code, we could omit
7959    * the following
7960    */
7961
7962   aopOp(result,ic,TRUE);
7963
7964   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7965
7966   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7967
7968   size = AOP_SIZE(result);
7969
7970   while (size--) {
7971     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7972     offset++;
7973   }
7974
7975   freeAsmop(left,NULL,ic,TRUE);
7976   freeAsmop(result,NULL,ic,TRUE);
7977 }
7978 #endif
7979 /*-----------------------------------------------------------------*/
7980 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7981 /*-----------------------------------------------------------------*/
7982 static void genNearPointerGet (operand *left, 
7983                                operand *result, 
7984                                iCode *ic)
7985 {
7986     asmop *aop = NULL;
7987     //regs *preg = NULL ;
7988     char *rname ;
7989     sym_link *rtype, *retype;
7990     sym_link *ltype = operandType(left);    
7991     //char buffer[80];
7992
7993     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7994
7995     rtype = operandType(result);
7996     retype= getSpec(rtype);
7997     
7998     aopOp(left,ic,FALSE);
7999     
8000     /* if left is rematerialisable and
8001        result is not bit variable type and
8002        the left is pointer to data space i.e
8003        lower 128 bytes of space */
8004     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8005         !IS_BITVAR(retype)         &&
8006         DCL_TYPE(ltype) == POINTER) {
8007       //genDataPointerGet (left,result,ic);
8008         return ;
8009     }
8010     
8011     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8012
8013         /* if the value is already in a pointer register
8014        then don't need anything more */
8015     if (!AOP_INPREG(AOP(left))) {
8016         /* otherwise get a free pointer register */
8017     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8018 /*
8019         aop = newAsmop(0);
8020         preg = getFreePtr(ic,&aop,FALSE);
8021         pic14_emitcode("mov","%s,%s",
8022                 preg->name,
8023                 aopGet(AOP(left),0,FALSE,TRUE));
8024         rname = preg->name ;
8025 */
8026     rname ="BAD";
8027     } else
8028         rname = aopGet(AOP(left),0,FALSE,FALSE);
8029     
8030     aopOp (result,ic,FALSE);
8031     
8032       /* if bitfield then unpack the bits */
8033     if (IS_BITVAR(retype)) 
8034         genUnpackBits (result,rname,POINTER);
8035     else {
8036         /* we have can just get the values */
8037       int size = AOP_SIZE(result);
8038       int offset = 0 ;  
8039         
8040       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8041
8042       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8043       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8044       while(size--) {
8045         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8046         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8047         if(size)
8048           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8049       }
8050 /*
8051         while (size--) {
8052             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8053
8054                 pic14_emitcode("mov","a,@%s",rname);
8055                 aopPut(AOP(result),"a",offset);
8056             } else {
8057                 sprintf(buffer,"@%s",rname);
8058                 aopPut(AOP(result),buffer,offset);
8059             }
8060             offset++ ;
8061             if (size)
8062                 pic14_emitcode("inc","%s",rname);
8063         }
8064 */
8065     }
8066
8067     /* now some housekeeping stuff */
8068     if (aop) {
8069         /* we had to allocate for this iCode */
8070     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8071         freeAsmop(NULL,aop,ic,TRUE);
8072     } else { 
8073         /* we did not allocate which means left
8074            already in a pointer register, then
8075            if size > 0 && this could be used again
8076            we have to point it back to where it 
8077            belongs */
8078     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8079         if (AOP_SIZE(result) > 1 &&
8080             !OP_SYMBOL(left)->remat &&
8081             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8082               ic->depth )) {
8083             int size = AOP_SIZE(result) - 1;
8084             while (size--)
8085                 pic14_emitcode("dec","%s",rname);
8086         }
8087     }
8088
8089     /* done */
8090     freeAsmop(left,NULL,ic,TRUE);
8091     freeAsmop(result,NULL,ic,TRUE);
8092      
8093 }
8094
8095 /*-----------------------------------------------------------------*/
8096 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8097 /*-----------------------------------------------------------------*/
8098 static void genPagedPointerGet (operand *left, 
8099                                operand *result, 
8100                                iCode *ic)
8101 {
8102     asmop *aop = NULL;
8103     regs *preg = NULL ;
8104     char *rname ;
8105     sym_link *rtype, *retype;    
8106
8107     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8108
8109     rtype = operandType(result);
8110     retype= getSpec(rtype);
8111     
8112     aopOp(left,ic,FALSE);
8113
8114   /* if the value is already in a pointer register
8115        then don't need anything more */
8116     if (!AOP_INPREG(AOP(left))) {
8117         /* otherwise get a free pointer register */
8118         aop = newAsmop(0);
8119         preg = getFreePtr(ic,&aop,FALSE);
8120         pic14_emitcode("mov","%s,%s",
8121                 preg->name,
8122                 aopGet(AOP(left),0,FALSE,TRUE));
8123         rname = preg->name ;
8124     } else
8125         rname = aopGet(AOP(left),0,FALSE,FALSE);
8126     
8127     freeAsmop(left,NULL,ic,TRUE);
8128     aopOp (result,ic,FALSE);
8129
8130     /* if bitfield then unpack the bits */
8131     if (IS_BITVAR(retype)) 
8132         genUnpackBits (result,rname,PPOINTER);
8133     else {
8134         /* we have can just get the values */
8135         int size = AOP_SIZE(result);
8136         int offset = 0 ;        
8137         
8138         while (size--) {
8139             
8140             pic14_emitcode("movx","a,@%s",rname);
8141             aopPut(AOP(result),"a",offset);
8142             
8143             offset++ ;
8144             
8145             if (size)
8146                 pic14_emitcode("inc","%s",rname);
8147         }
8148     }
8149
8150     /* now some housekeeping stuff */
8151     if (aop) {
8152         /* we had to allocate for this iCode */
8153         freeAsmop(NULL,aop,ic,TRUE);
8154     } else { 
8155         /* we did not allocate which means left
8156            already in a pointer register, then
8157            if size > 0 && this could be used again
8158            we have to point it back to where it 
8159            belongs */
8160         if (AOP_SIZE(result) > 1 &&
8161             !OP_SYMBOL(left)->remat &&
8162             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8163               ic->depth )) {
8164             int size = AOP_SIZE(result) - 1;
8165             while (size--)
8166                 pic14_emitcode("dec","%s",rname);
8167         }
8168     }
8169
8170     /* done */
8171     freeAsmop(result,NULL,ic,TRUE);
8172     
8173         
8174 }
8175
8176 /*-----------------------------------------------------------------*/
8177 /* genFarPointerGet - gget value from far space                    */
8178 /*-----------------------------------------------------------------*/
8179 static void genFarPointerGet (operand *left,
8180                               operand *result, iCode *ic)
8181 {
8182     int size, offset ;
8183     sym_link *retype = getSpec(operandType(result));
8184
8185     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8186
8187     aopOp(left,ic,FALSE);
8188
8189     /* if the operand is already in dptr 
8190     then we do nothing else we move the value to dptr */
8191     if (AOP_TYPE(left) != AOP_STR) {
8192         /* if this is remateriazable */
8193         if (AOP_TYPE(left) == AOP_IMMD)
8194             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8195         else { /* we need to get it byte by byte */
8196             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8197             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8198             if (options.model == MODEL_FLAT24)
8199             {
8200                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8201             }
8202         }
8203     }
8204     /* so dptr know contains the address */
8205     freeAsmop(left,NULL,ic,TRUE);
8206     aopOp(result,ic,FALSE);
8207
8208     /* if bit then unpack */
8209     if (IS_BITVAR(retype)) 
8210         genUnpackBits(result,"dptr",FPOINTER);
8211     else {
8212         size = AOP_SIZE(result);
8213         offset = 0 ;
8214
8215         while (size--) {
8216             pic14_emitcode("movx","a,@dptr");
8217             aopPut(AOP(result),"a",offset++);
8218             if (size)
8219                 pic14_emitcode("inc","dptr");
8220         }
8221     }
8222
8223     freeAsmop(result,NULL,ic,TRUE);
8224 }
8225 #if 0
8226 /*-----------------------------------------------------------------*/
8227 /* genCodePointerGet - get value from code space                  */
8228 /*-----------------------------------------------------------------*/
8229 static void genCodePointerGet (operand *left,
8230                                 operand *result, iCode *ic)
8231 {
8232     int size, offset ;
8233     sym_link *retype = getSpec(operandType(result));
8234
8235     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8236
8237     aopOp(left,ic,FALSE);
8238
8239     /* if the operand is already in dptr 
8240     then we do nothing else we move the value to dptr */
8241     if (AOP_TYPE(left) != AOP_STR) {
8242         /* if this is remateriazable */
8243         if (AOP_TYPE(left) == AOP_IMMD)
8244             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8245         else { /* we need to get it byte by byte */
8246             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8247             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8248             if (options.model == MODEL_FLAT24)
8249             {
8250                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8251             }
8252         }
8253     }
8254     /* so dptr know contains the address */
8255     freeAsmop(left,NULL,ic,TRUE);
8256     aopOp(result,ic,FALSE);
8257
8258     /* if bit then unpack */
8259     if (IS_BITVAR(retype)) 
8260         genUnpackBits(result,"dptr",CPOINTER);
8261     else {
8262         size = AOP_SIZE(result);
8263         offset = 0 ;
8264
8265         while (size--) {
8266             pic14_emitcode("clr","a");
8267             pic14_emitcode("movc","a,@a+dptr");
8268             aopPut(AOP(result),"a",offset++);
8269             if (size)
8270                 pic14_emitcode("inc","dptr");
8271         }
8272     }
8273
8274     freeAsmop(result,NULL,ic,TRUE);
8275 }
8276 #endif
8277 /*-----------------------------------------------------------------*/
8278 /* genGenPointerGet - gget value from generic pointer space        */
8279 /*-----------------------------------------------------------------*/
8280 static void genGenPointerGet (operand *left,
8281                               operand *result, iCode *ic)
8282 {
8283   int size, offset ;
8284   sym_link *retype = getSpec(operandType(result));
8285
8286   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8287   aopOp(left,ic,FALSE);
8288   aopOp(result,ic,FALSE);
8289
8290
8291   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8292
8293   /* if the operand is already in dptr 
8294      then we do nothing else we move the value to dptr */
8295   //  if (AOP_TYPE(left) != AOP_STR) {
8296     /* if this is remateriazable */
8297     if (AOP_TYPE(left) == AOP_IMMD) {
8298       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8299       pic14_emitcode("mov","b,#%d",pointerCode(retype));
8300     }
8301     else { /* we need to get it byte by byte */
8302
8303       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8304       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8305
8306       size = AOP_SIZE(result);
8307       offset = 0 ;
8308
8309       while(size--) {
8310         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8311         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8312         if(size)
8313           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8314       }
8315       goto release;
8316     }
8317     //}
8318   /* so dptr know contains the address */
8319
8320   /* if bit then unpack */
8321   //if (IS_BITVAR(retype)) 
8322   //  genUnpackBits(result,"dptr",GPOINTER);
8323
8324  release:
8325   freeAsmop(left,NULL,ic,TRUE);
8326   freeAsmop(result,NULL,ic,TRUE);
8327
8328 }
8329
8330 /*-----------------------------------------------------------------*/
8331 /* genConstPointerGet - get value from const generic pointer space */
8332 /*-----------------------------------------------------------------*/
8333 static void genConstPointerGet (operand *left,
8334                                 operand *result, iCode *ic)
8335 {
8336   //sym_link *retype = getSpec(operandType(result));
8337   symbol *albl = newiTempLabel(NULL);
8338   symbol *blbl = newiTempLabel(NULL);
8339   PIC_OPCODE poc;
8340
8341   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8342   aopOp(left,ic,FALSE);
8343   aopOp(result,ic,FALSE);
8344
8345
8346   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8347
8348   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8349
8350   emitpcode(POC_CALL,popGetLabel(albl->key));
8351   emitpcode(POC_GOTO,popGetLabel(blbl->key));
8352   emitpLabel(albl->key);
8353
8354   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8355     
8356   emitpcode(poc,popGet(AOP(left),1));
8357   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8358   emitpcode(poc,popGet(AOP(left),0));
8359   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8360
8361   emitpLabel(blbl->key);
8362
8363   emitpcode(POC_MOVWF,popGet(AOP(result),0));
8364
8365
8366   freeAsmop(left,NULL,ic,TRUE);
8367   freeAsmop(result,NULL,ic,TRUE);
8368
8369 }
8370 /*-----------------------------------------------------------------*/
8371 /* genPointerGet - generate code for pointer get                   */
8372 /*-----------------------------------------------------------------*/
8373 static void genPointerGet (iCode *ic)
8374 {
8375     operand *left, *result ;
8376     sym_link *type, *etype;
8377     int p_type;
8378
8379     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8380
8381     left = IC_LEFT(ic);
8382     result = IC_RESULT(ic) ;
8383
8384     /* depending on the type of pointer we need to
8385     move it to the correct pointer register */
8386     type = operandType(left);
8387     etype = getSpec(type);
8388
8389     if (IS_PTR_CONST(type))
8390       DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8391
8392     /* if left is of type of pointer then it is simple */
8393     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8394         p_type = DCL_TYPE(type);
8395     else {
8396         /* we have to go by the storage class */
8397         p_type = PTR_TYPE(SPEC_OCLS(etype));
8398
8399         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8400
8401         if (SPEC_OCLS(etype)->codesp ) {
8402           DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8403           //p_type = CPOINTER ; 
8404         }
8405         else
8406             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8407               DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8408                /*p_type = FPOINTER ;*/ 
8409             else
8410                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8411                   DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8412 /*                  p_type = PPOINTER; */
8413                 else
8414                     if (SPEC_OCLS(etype) == idata )
8415                       DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8416 /*                      p_type = IPOINTER; */
8417                     else
8418                       DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8419 /*                      p_type = POINTER ; */
8420     }
8421
8422     /* now that we have the pointer type we assign
8423     the pointer values */
8424     switch (p_type) {
8425
8426     case POINTER:       
8427     case IPOINTER:
8428         genNearPointerGet (left,result,ic);
8429         break;
8430
8431     case PPOINTER:
8432         genPagedPointerGet(left,result,ic);
8433         break;
8434
8435     case FPOINTER:
8436         genFarPointerGet (left,result,ic);
8437         break;
8438
8439     case CPOINTER:
8440         genConstPointerGet (left,result,ic);
8441         //pic14_emitcodePointerGet (left,result,ic);
8442         break;
8443
8444     case GPOINTER:
8445       if (IS_PTR_CONST(type))
8446         genConstPointerGet (left,result,ic);
8447       else
8448         genGenPointerGet (left,result,ic);
8449       break;
8450     }
8451
8452 }
8453
8454 /*-----------------------------------------------------------------*/
8455 /* genPackBits - generates code for packed bit storage             */
8456 /*-----------------------------------------------------------------*/
8457 static void genPackBits (sym_link    *etype ,
8458                          operand *right ,
8459                          char *rname, int p_type)
8460 {
8461     int shCount = 0 ;
8462     int offset = 0  ;
8463     int rLen = 0 ;
8464     int blen, bstr ;   
8465     char *l ;
8466
8467     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8468     blen = SPEC_BLEN(etype);
8469     bstr = SPEC_BSTR(etype);
8470
8471     l = aopGet(AOP(right),offset++,FALSE,FALSE);
8472     MOVA(l);   
8473
8474     /* if the bit lenth is less than or    */
8475     /* it exactly fits a byte then         */
8476     if (SPEC_BLEN(etype) <= 8 )  {
8477         shCount = SPEC_BSTR(etype) ;
8478
8479         /* shift left acc */
8480         AccLsh(shCount);
8481
8482         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8483
8484
8485             switch (p_type) {
8486                 case POINTER:
8487                     pic14_emitcode ("mov","b,a");
8488                     pic14_emitcode("mov","a,@%s",rname);
8489                     break;
8490
8491                 case FPOINTER:
8492                     pic14_emitcode ("mov","b,a");
8493                     pic14_emitcode("movx","a,@dptr");
8494                     break;
8495
8496                 case GPOINTER:
8497                     pic14_emitcode ("push","b");
8498                     pic14_emitcode ("push","acc");
8499                     pic14_emitcode ("lcall","__gptrget");
8500                     pic14_emitcode ("pop","b");
8501                     break;
8502             }
8503
8504             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8505                       ((unsigned char)(0xFF << (blen+bstr)) | 
8506                        (unsigned char)(0xFF >> (8-bstr)) ) );
8507             pic14_emitcode ("orl","a,b");
8508             if (p_type == GPOINTER)
8509                 pic14_emitcode("pop","b");
8510         }
8511     }
8512
8513     switch (p_type) {
8514         case POINTER:
8515             pic14_emitcode("mov","@%s,a",rname);
8516             break;
8517
8518         case FPOINTER:
8519             pic14_emitcode("movx","@dptr,a");
8520             break;
8521
8522         case GPOINTER:
8523             DEBUGpic14_emitcode(";lcall","__gptrput");
8524             break;
8525     }
8526
8527     /* if we r done */
8528     if ( SPEC_BLEN(etype) <= 8 )
8529         return ;
8530
8531     pic14_emitcode("inc","%s",rname);
8532     rLen = SPEC_BLEN(etype) ;     
8533
8534     /* now generate for lengths greater than one byte */
8535     while (1) {
8536
8537         l = aopGet(AOP(right),offset++,FALSE,TRUE);
8538
8539         rLen -= 8 ;
8540         if (rLen <= 0 )
8541             break ;
8542
8543         switch (p_type) {
8544             case POINTER:
8545                 if (*l == '@') {
8546                     MOVA(l);
8547                     pic14_emitcode("mov","@%s,a",rname);
8548                 } else
8549                     pic14_emitcode("mov","@%s,%s",rname,l);
8550                 break;
8551
8552             case FPOINTER:
8553                 MOVA(l);
8554                 pic14_emitcode("movx","@dptr,a");
8555                 break;
8556
8557             case GPOINTER:
8558                 MOVA(l);
8559                 DEBUGpic14_emitcode(";lcall","__gptrput");
8560                 break;  
8561         }   
8562         pic14_emitcode ("inc","%s",rname);
8563     }
8564
8565     MOVA(l);
8566
8567     /* last last was not complete */
8568     if (rLen)   {
8569         /* save the byte & read byte */
8570         switch (p_type) {
8571             case POINTER:
8572                 pic14_emitcode ("mov","b,a");
8573                 pic14_emitcode("mov","a,@%s",rname);
8574                 break;
8575
8576             case FPOINTER:
8577                 pic14_emitcode ("mov","b,a");
8578                 pic14_emitcode("movx","a,@dptr");
8579                 break;
8580
8581             case GPOINTER:
8582                 pic14_emitcode ("push","b");
8583                 pic14_emitcode ("push","acc");
8584                 pic14_emitcode ("lcall","__gptrget");
8585                 pic14_emitcode ("pop","b");
8586                 break;
8587         }
8588
8589         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8590         pic14_emitcode ("orl","a,b");
8591     }
8592
8593     if (p_type == GPOINTER)
8594         pic14_emitcode("pop","b");
8595
8596     switch (p_type) {
8597
8598     case POINTER:
8599         pic14_emitcode("mov","@%s,a",rname);
8600         break;
8601         
8602     case FPOINTER:
8603         pic14_emitcode("movx","@dptr,a");
8604         break;
8605         
8606     case GPOINTER:
8607         DEBUGpic14_emitcode(";lcall","__gptrput");
8608         break;                  
8609     }
8610 }
8611 /*-----------------------------------------------------------------*/
8612 /* genDataPointerSet - remat pointer to data space                 */
8613 /*-----------------------------------------------------------------*/
8614 static void genDataPointerSet(operand *right,
8615                               operand *result,
8616                               iCode *ic)
8617 {
8618     int size, offset = 0 ;
8619     char *l, buffer[256];
8620
8621     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8622     aopOp(right,ic,FALSE);
8623     
8624     l = aopGet(AOP(result),0,FALSE,TRUE);
8625     size = AOP_SIZE(right);
8626 /*
8627     if ( AOP_TYPE(result) == AOP_PCODE) {
8628       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8629               AOP(result)->aopu.pcop->name,
8630               PCOI(AOP(result)->aopu.pcop)->offset);
8631     }
8632 */
8633
8634     // tsd, was l+1 - the underline `_' prefix was being stripped
8635     while (size--) {
8636       if (offset) {
8637         sprintf(buffer,"(%s + %d)",l,offset);
8638         fprintf(stderr,"oops  %s\n",buffer);
8639       } else
8640         sprintf(buffer,"%s",l);
8641
8642         if (AOP_TYPE(right) == AOP_LIT) {
8643           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8644           lit = lit >> (8*offset);
8645           if(lit&0xff) {
8646             pic14_emitcode("movlw","%d",lit);
8647             pic14_emitcode("movwf","%s",buffer);
8648
8649             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8650             //emitpcode(POC_MOVWF, popRegFromString(buffer));
8651             emitpcode(POC_MOVWF, popGet(AOP(result),0));
8652
8653           } else {
8654             pic14_emitcode("clrf","%s",buffer);
8655             //emitpcode(POC_CLRF, popRegFromString(buffer));
8656             emitpcode(POC_CLRF, popGet(AOP(result),0));
8657           }
8658         }else {
8659           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8660           pic14_emitcode("movwf","%s",buffer);
8661
8662           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8663           //emitpcode(POC_MOVWF, popRegFromString(buffer));
8664           emitpcode(POC_MOVWF, popGet(AOP(result),0));
8665
8666         }
8667
8668         offset++;
8669     }
8670
8671     freeAsmop(right,NULL,ic,TRUE);
8672     freeAsmop(result,NULL,ic,TRUE);
8673 }
8674
8675 /*-----------------------------------------------------------------*/
8676 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8677 /*-----------------------------------------------------------------*/
8678 static void genNearPointerSet (operand *right,
8679                                operand *result, 
8680                                iCode *ic)
8681 {
8682   asmop *aop = NULL;
8683   char *l;
8684   sym_link *retype;
8685   sym_link *ptype = operandType(result);
8686
8687     
8688   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8689   retype= getSpec(operandType(right));
8690
8691   aopOp(result,ic,FALSE);
8692
8693     
8694   /* if the result is rematerializable &
8695      in data space & not a bit variable */
8696   //if (AOP_TYPE(result) == AOP_IMMD &&
8697   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8698       DCL_TYPE(ptype) == POINTER   &&
8699       !IS_BITVAR(retype)) {
8700     genDataPointerSet (right,result,ic);
8701     freeAsmop(result,NULL,ic,TRUE);
8702     return;
8703   }
8704
8705   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8706   aopOp(right,ic,FALSE);
8707   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8708
8709   /* if the value is already in a pointer register
8710      then don't need anything more */
8711   if (!AOP_INPREG(AOP(result))) {
8712     /* otherwise get a free pointer register */
8713     //aop = newAsmop(0);
8714     //preg = getFreePtr(ic,&aop,FALSE);
8715     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8716     //pic14_emitcode("mov","%s,%s",
8717     //         preg->name,
8718     //         aopGet(AOP(result),0,FALSE,TRUE));
8719     //rname = preg->name ;
8720     //pic14_emitcode("movwf","fsr");
8721     emitpcode(POC_MOVFW, popGet(AOP(result),0));
8722     emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8723     emitpcode(POC_MOVFW, popGet(AOP(right),0));
8724     emitpcode(POC_MOVWF, popCopyReg(&pc_indf));
8725     goto release;
8726
8727   }// else
8728   //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8729
8730
8731   /* if bitfield then unpack the bits */
8732   if (IS_BITVAR(retype)) {
8733     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8734            "The programmer is obviously confused");
8735     //genPackBits (retype,right,rname,POINTER);
8736     exit(1);
8737   }
8738   else {
8739     /* we have can just get the values */
8740     int size = AOP_SIZE(right);
8741     int offset = 0 ;    
8742
8743     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8744     while (size--) {
8745       l = aopGet(AOP(right),offset,FALSE,TRUE);
8746       if (*l == '@' ) {
8747         //MOVA(l);
8748         //pic14_emitcode("mov","@%s,a",rname);
8749         pic14_emitcode("movf","indf,w ;1");
8750       } else {
8751
8752         if (AOP_TYPE(right) == AOP_LIT) {
8753           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8754           if(lit) {
8755             pic14_emitcode("movlw","%s",l);
8756             pic14_emitcode("movwf","indf ;2");
8757           } else 
8758             pic14_emitcode("clrf","indf");
8759         }else {
8760           pic14_emitcode("movf","%s,w",l);
8761           pic14_emitcode("movwf","indf ;2");
8762         }
8763         //pic14_emitcode("mov","@%s,%s",rname,l);
8764       }
8765       if (size)
8766         pic14_emitcode("incf","fsr,f ;3");
8767       //pic14_emitcode("inc","%s",rname);
8768       offset++;
8769     }
8770   }
8771
8772   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8773   /* now some housekeeping stuff */
8774   if (aop) {
8775     /* we had to allocate for this iCode */
8776     freeAsmop(NULL,aop,ic,TRUE);
8777   } else { 
8778     /* we did not allocate which means left
8779        already in a pointer register, then
8780        if size > 0 && this could be used again
8781        we have to point it back to where it 
8782        belongs */
8783     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8784     if (AOP_SIZE(right) > 1 &&
8785         !OP_SYMBOL(result)->remat &&
8786         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8787           ic->depth )) {
8788       int size = AOP_SIZE(right) - 1;
8789       while (size--)
8790         pic14_emitcode("decf","fsr,f");
8791       //pic14_emitcode("dec","%s",rname);
8792     }
8793   }
8794
8795   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8796   /* done */
8797  release:
8798   freeAsmop(right,NULL,ic,TRUE);
8799   freeAsmop(result,NULL,ic,TRUE);
8800 }
8801
8802 /*-----------------------------------------------------------------*/
8803 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8804 /*-----------------------------------------------------------------*/
8805 static void genPagedPointerSet (operand *right,
8806                                operand *result, 
8807                                iCode *ic)
8808 {
8809     asmop *aop = NULL;
8810     regs *preg = NULL ;
8811     char *rname , *l;
8812     sym_link *retype;
8813        
8814     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8815
8816     retype= getSpec(operandType(right));
8817     
8818     aopOp(result,ic,FALSE);
8819     
8820     /* if the value is already in a pointer register
8821        then don't need anything more */
8822     if (!AOP_INPREG(AOP(result))) {
8823         /* otherwise get a free pointer register */
8824         aop = newAsmop(0);
8825         preg = getFreePtr(ic,&aop,FALSE);
8826         pic14_emitcode("mov","%s,%s",
8827                 preg->name,
8828                 aopGet(AOP(result),0,FALSE,TRUE));
8829         rname = preg->name ;
8830     } else
8831         rname = aopGet(AOP(result),0,FALSE,FALSE);
8832     
8833     freeAsmop(result,NULL,ic,TRUE);
8834     aopOp (right,ic,FALSE);
8835
8836     /* if bitfield then unpack the bits */
8837     if (IS_BITVAR(retype)) 
8838         genPackBits (retype,right,rname,PPOINTER);
8839     else {
8840         /* we have can just get the values */
8841         int size = AOP_SIZE(right);
8842         int offset = 0 ;        
8843         
8844         while (size--) {
8845             l = aopGet(AOP(right),offset,FALSE,TRUE);
8846             
8847             MOVA(l);
8848             pic14_emitcode("movx","@%s,a",rname);
8849
8850             if (size)
8851                 pic14_emitcode("inc","%s",rname);
8852
8853             offset++;
8854         }
8855     }
8856     
8857     /* now some housekeeping stuff */
8858     if (aop) {
8859         /* we had to allocate for this iCode */
8860         freeAsmop(NULL,aop,ic,TRUE);
8861     } else { 
8862         /* we did not allocate which means left
8863            already in a pointer register, then
8864            if size > 0 && this could be used again
8865            we have to point it back to where it 
8866            belongs */
8867         if (AOP_SIZE(right) > 1 &&
8868             !OP_SYMBOL(result)->remat &&
8869             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8870               ic->depth )) {
8871             int size = AOP_SIZE(right) - 1;
8872             while (size--)
8873                 pic14_emitcode("dec","%s",rname);
8874         }
8875     }
8876
8877     /* done */
8878     freeAsmop(right,NULL,ic,TRUE);
8879     
8880         
8881 }
8882
8883 /*-----------------------------------------------------------------*/
8884 /* genFarPointerSet - set value from far space                     */
8885 /*-----------------------------------------------------------------*/
8886 static void genFarPointerSet (operand *right,
8887                               operand *result, iCode *ic)
8888 {
8889     int size, offset ;
8890     sym_link *retype = getSpec(operandType(right));
8891
8892     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8893     aopOp(result,ic,FALSE);
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         else { /* we need to get it byte by byte */
8902             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8903             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8904             if (options.model == MODEL_FLAT24)
8905             {
8906                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8907             }
8908         }
8909     }
8910     /* so dptr know contains the address */
8911     freeAsmop(result,NULL,ic,TRUE);
8912     aopOp(right,ic,FALSE);
8913
8914     /* if bit then unpack */
8915     if (IS_BITVAR(retype)) 
8916         genPackBits(retype,right,"dptr",FPOINTER);
8917     else {
8918         size = AOP_SIZE(right);
8919         offset = 0 ;
8920
8921         while (size--) {
8922             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8923             MOVA(l);
8924             pic14_emitcode("movx","@dptr,a");
8925             if (size)
8926                 pic14_emitcode("inc","dptr");
8927         }
8928     }
8929
8930     freeAsmop(right,NULL,ic,TRUE);
8931 }
8932
8933 /*-----------------------------------------------------------------*/
8934 /* genGenPointerSet - set value from generic pointer space         */
8935 /*-----------------------------------------------------------------*/
8936 static void genGenPointerSet (operand *right,
8937                               operand *result, iCode *ic)
8938 {
8939   int size, offset ;
8940   sym_link *retype = getSpec(operandType(right));
8941
8942   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8943
8944   aopOp(result,ic,FALSE);
8945   aopOp(right,ic,FALSE);
8946   size = AOP_SIZE(right);
8947
8948   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8949
8950   /* if the operand is already in dptr 
8951      then we do nothing else we move the value to dptr */
8952   if (AOP_TYPE(result) != AOP_STR) {
8953     /* if this is remateriazable */
8954     if (AOP_TYPE(result) == AOP_IMMD) {
8955       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8956       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8957     }
8958     else { /* we need to get it byte by byte */
8959       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8960       size = AOP_SIZE(right);
8961       offset = 0 ;
8962
8963       /* hack hack! see if this the FSR. If so don't load W */
8964       if(AOP_TYPE(right) != AOP_ACC) {
8965
8966
8967         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8968         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8969
8970         if(AOP_SIZE(result) > 1) {
8971           emitpcode(POC_BCF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8972           emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8973           emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8974
8975         }
8976
8977         //if(size==2)
8978         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8979         //if(size==4) {
8980         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8981         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8982         //}
8983
8984         while(size--) {
8985           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
8986           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8987           
8988           if(size)
8989             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8990         }
8991
8992
8993         goto release;
8994       } 
8995
8996       if(aopIdx(AOP(result),0) != 4) {
8997
8998         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8999         goto release;
9000       }
9001
9002       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9003       goto release;
9004
9005     }
9006   }
9007   /* so dptr know contains the address */
9008
9009
9010   /* if bit then unpack */
9011   if (IS_BITVAR(retype)) 
9012     genPackBits(retype,right,"dptr",GPOINTER);
9013   else {
9014     size = AOP_SIZE(right);
9015     offset = 0 ;
9016
9017   DEBUGpic14_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9018
9019     while (size--) {
9020
9021       emitpcode(POC_MOVFW,popGet(AOP(result),offset));
9022       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9023
9024       if (AOP_TYPE(right) == AOP_LIT) 
9025         emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9026       else
9027         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9028
9029       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9030
9031       offset++;
9032     }
9033   }
9034
9035  release:
9036   freeAsmop(right,NULL,ic,TRUE);
9037   freeAsmop(result,NULL,ic,TRUE);
9038 }
9039
9040 /*-----------------------------------------------------------------*/
9041 /* genPointerSet - stores the value into a pointer location        */
9042 /*-----------------------------------------------------------------*/
9043 static void genPointerSet (iCode *ic)
9044 {    
9045     operand *right, *result ;
9046     sym_link *type, *etype;
9047     int p_type;
9048
9049     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9050
9051     right = IC_RIGHT(ic);
9052     result = IC_RESULT(ic) ;
9053
9054     /* depending on the type of pointer we need to
9055     move it to the correct pointer register */
9056     type = operandType(result);
9057     etype = getSpec(type);
9058     /* if left is of type of pointer then it is simple */
9059     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9060         p_type = DCL_TYPE(type);
9061     }
9062     else {
9063         /* we have to go by the storage class */
9064         p_type = PTR_TYPE(SPEC_OCLS(etype));
9065
9066 /*      if (SPEC_OCLS(etype)->codesp ) { */
9067 /*          p_type = CPOINTER ;  */
9068 /*      } */
9069 /*      else */
9070 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9071 /*              p_type = FPOINTER ; */
9072 /*          else */
9073 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9074 /*                  p_type = PPOINTER ; */
9075 /*              else */
9076 /*                  if (SPEC_OCLS(etype) == idata ) */
9077 /*                      p_type = IPOINTER ; */
9078 /*                  else */
9079 /*                      p_type = POINTER ; */
9080     }
9081
9082     /* now that we have the pointer type we assign
9083     the pointer values */
9084     switch (p_type) {
9085
9086     case POINTER:
9087     case IPOINTER:
9088         genNearPointerSet (right,result,ic);
9089         break;
9090
9091     case PPOINTER:
9092         genPagedPointerSet (right,result,ic);
9093         break;
9094
9095     case FPOINTER:
9096         genFarPointerSet (right,result,ic);
9097         break;
9098
9099     case GPOINTER:
9100         genGenPointerSet (right,result,ic);
9101         break;
9102
9103     default:
9104       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9105               "genPointerSet: illegal pointer type");
9106     }
9107 }
9108
9109 /*-----------------------------------------------------------------*/
9110 /* genIfx - generate code for Ifx statement                        */
9111 /*-----------------------------------------------------------------*/
9112 static void genIfx (iCode *ic, iCode *popIc)
9113 {
9114   operand *cond = IC_COND(ic);
9115   int isbit =0;
9116
9117   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9118
9119   aopOp(cond,ic,FALSE);
9120
9121   /* get the value into acc */
9122   if (AOP_TYPE(cond) != AOP_CRY)
9123     pic14_toBoolean(cond);
9124   else
9125     isbit = 1;
9126   /* the result is now in the accumulator */
9127   freeAsmop(cond,NULL,ic,TRUE);
9128
9129   /* if there was something to be popped then do it */
9130   if (popIc)
9131     genIpop(popIc);
9132
9133   /* if the condition is  a bit variable */
9134   if (isbit && IS_ITEMP(cond) && 
9135       SPIL_LOC(cond)) {
9136     genIfxJump(ic,SPIL_LOC(cond)->rname);
9137     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9138   }
9139   else {
9140     if (isbit && !IS_ITEMP(cond))
9141       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9142     else
9143       genIfxJump(ic,"a");
9144   }
9145   ic->generated = 1;
9146
9147 }
9148
9149 /*-----------------------------------------------------------------*/
9150 /* genAddrOf - generates code for address of                       */
9151 /*-----------------------------------------------------------------*/
9152 static void genAddrOf (iCode *ic)
9153 {
9154   operand *right, *result, *left;
9155   int size, offset ;
9156
9157   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9158
9159
9160   //aopOp(IC_RESULT(ic),ic,FALSE);
9161
9162   aopOp((left=IC_LEFT(ic)),ic,FALSE);
9163   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9164   aopOp((result=IC_RESULT(ic)),ic,TRUE);
9165
9166   DEBUGpic14_AopType(__LINE__,left,right,result);
9167
9168   size = AOP_SIZE(IC_RESULT(ic));
9169   offset = 0;
9170
9171   while (size--) {
9172     emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9173     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9174     offset++;
9175   }
9176
9177   freeAsmop(left,NULL,ic,FALSE);
9178   freeAsmop(result,NULL,ic,TRUE);
9179
9180 }
9181
9182 #if 0
9183 /*-----------------------------------------------------------------*/
9184 /* genFarFarAssign - assignment when both are in far space         */
9185 /*-----------------------------------------------------------------*/
9186 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9187 {
9188     int size = AOP_SIZE(right);
9189     int offset = 0;
9190     char *l ;
9191     /* first push the right side on to the stack */
9192     while (size--) {
9193         l = aopGet(AOP(right),offset++,FALSE,FALSE);
9194         MOVA(l);
9195         pic14_emitcode ("push","acc");
9196     }
9197     
9198     freeAsmop(right,NULL,ic,FALSE);
9199     /* now assign DPTR to result */
9200     aopOp(result,ic,FALSE);
9201     size = AOP_SIZE(result);
9202     while (size--) {
9203         pic14_emitcode ("pop","acc");
9204         aopPut(AOP(result),"a",--offset);
9205     }
9206     freeAsmop(result,NULL,ic,FALSE);
9207         
9208 }
9209 #endif
9210
9211 /*-----------------------------------------------------------------*/
9212 /* genAssign - generate code for assignment                        */
9213 /*-----------------------------------------------------------------*/
9214 static void genAssign (iCode *ic)
9215 {
9216   operand *result, *right;
9217   int size, offset,know_W;
9218   unsigned long lit = 0L;
9219
9220   result = IC_RESULT(ic);
9221   right  = IC_RIGHT(ic) ;
9222
9223   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9224
9225   /* if they are the same */
9226   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9227     return ;
9228
9229   aopOp(right,ic,FALSE);
9230   aopOp(result,ic,TRUE);
9231
9232   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9233
9234   /* if they are the same registers */
9235   if (pic14_sameRegs(AOP(right),AOP(result)))
9236     goto release;
9237
9238   /* if the result is a bit */
9239   if (AOP_TYPE(result) == AOP_CRY) {
9240
9241     /* if the right size is a literal then
9242        we know what the value is */
9243     if (AOP_TYPE(right) == AOP_LIT) {
9244           
9245       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9246                   popGet(AOP(result),0));
9247
9248       if (((int) operandLitValue(right))) 
9249         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9250                        AOP(result)->aopu.aop_dir,
9251                        AOP(result)->aopu.aop_dir);
9252       else
9253         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9254                        AOP(result)->aopu.aop_dir,
9255                        AOP(result)->aopu.aop_dir);
9256       goto release;
9257     }
9258
9259     /* the right is also a bit variable */
9260     if (AOP_TYPE(right) == AOP_CRY) {
9261       emitpcode(POC_BCF,    popGet(AOP(result),0));
9262       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9263       emitpcode(POC_BSF,    popGet(AOP(result),0));
9264
9265       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9266                      AOP(result)->aopu.aop_dir,
9267                      AOP(result)->aopu.aop_dir);
9268       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9269                      AOP(right)->aopu.aop_dir,
9270                      AOP(right)->aopu.aop_dir);
9271       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9272                      AOP(result)->aopu.aop_dir,
9273                      AOP(result)->aopu.aop_dir);
9274       goto release ;
9275     }
9276
9277     /* we need to or */
9278     emitpcode(POC_BCF,    popGet(AOP(result),0));
9279     pic14_toBoolean(right);
9280     emitSKPZ;
9281     emitpcode(POC_BSF,    popGet(AOP(result),0));
9282     //aopPut(AOP(result),"a",0);
9283     goto release ;
9284   }
9285
9286   /* bit variables done */
9287   /* general case */
9288   size = AOP_SIZE(result);
9289   offset = 0 ;
9290   if(AOP_TYPE(right) == AOP_LIT)
9291     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9292
9293   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9294   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9295     if(aopIdx(AOP(result),0) == 4) {
9296   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9297       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9298       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9299       goto release;
9300     } else
9301       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9302   }
9303
9304   know_W=-1;
9305   while (size--) {
9306   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9307     if(AOP_TYPE(right) == AOP_LIT) {
9308       if(lit&0xff) {
9309         if(know_W != (lit&0xff))
9310           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9311         know_W = lit&0xff;
9312         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9313       } else
9314         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9315
9316       lit >>= 8;
9317
9318     } else if (AOP_TYPE(right) == AOP_CRY) {
9319       emitpcode(POC_CLRF, popGet(AOP(result),offset));
9320       if(offset == 0) {
9321         emitpcode(POC_BTFSS, popGet(AOP(right),0));
9322         emitpcode(POC_INCF, popGet(AOP(result),0));
9323       }
9324     } else {
9325   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9326       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9327       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9328     }
9329             
9330     offset++;
9331   }
9332
9333     
9334  release:
9335   freeAsmop (right,NULL,ic,FALSE);
9336   freeAsmop (result,NULL,ic,TRUE);
9337 }   
9338
9339 /*-----------------------------------------------------------------*/
9340 /* genJumpTab - genrates code for jump table                       */
9341 /*-----------------------------------------------------------------*/
9342 static void genJumpTab (iCode *ic)
9343 {
9344     symbol *jtab;
9345     char *l;
9346
9347     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9348
9349     aopOp(IC_JTCOND(ic),ic,FALSE);
9350     /* get the condition into accumulator */
9351     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9352     MOVA(l);
9353     /* multiply by three */
9354     pic14_emitcode("add","a,acc");
9355     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9356
9357     jtab = newiTempLabel(NULL);
9358     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9359     pic14_emitcode("jmp","@a+dptr");
9360     pic14_emitcode("","%05d_DS_:",jtab->key+100);
9361
9362     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9363     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9364     emitSKPNC;
9365     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9366     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9367     emitpLabel(jtab->key);
9368
9369     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9370
9371     /* now generate the jump labels */
9372     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9373          jtab = setNextItem(IC_JTLABELS(ic))) {
9374         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9375         emitpcode(POC_GOTO,popGetLabel(jtab->key));
9376         
9377     }
9378
9379 }
9380
9381 /*-----------------------------------------------------------------*/
9382 /* genMixedOperation - gen code for operators between mixed types  */
9383 /*-----------------------------------------------------------------*/
9384 /*
9385   TSD - Written for the PIC port - but this unfortunately is buggy.
9386   This routine is good in that it is able to efficiently promote 
9387   types to different (larger) sizes. Unfortunately, the temporary
9388   variables that are optimized out by this routine are sometimes
9389   used in other places. So until I know how to really parse the 
9390   iCode tree, I'm going to not be using this routine :(.
9391 */
9392 static int genMixedOperation (iCode *ic)
9393 {
9394 #if 0
9395   operand *result = IC_RESULT(ic);
9396   sym_link *ctype = operandType(IC_LEFT(ic));
9397   operand *right = IC_RIGHT(ic);
9398   int ret = 0;
9399   int big,small;
9400   int offset;
9401
9402   iCode *nextic;
9403   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9404
9405   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9406
9407   nextic = ic->next;
9408   if(!nextic)
9409     return 0;
9410
9411   nextright = IC_RIGHT(nextic);
9412   nextleft  = IC_LEFT(nextic);
9413   nextresult = IC_RESULT(nextic);
9414
9415   aopOp(right,ic,FALSE);
9416   aopOp(result,ic,FALSE);
9417   aopOp(nextright,  nextic, FALSE);
9418   aopOp(nextleft,   nextic, FALSE);
9419   aopOp(nextresult, nextic, FALSE);
9420
9421   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9422
9423     operand *t = right;
9424     right = nextright;
9425     nextright = t; 
9426
9427     pic14_emitcode(";remove right +","");
9428
9429   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9430 /*
9431     operand *t = right;
9432     right = nextleft;
9433     nextleft = t; 
9434 */
9435     pic14_emitcode(";remove left +","");
9436   } else
9437     return 0;
9438
9439   big = AOP_SIZE(nextleft);
9440   small = AOP_SIZE(nextright);
9441
9442   switch(nextic->op) {
9443
9444   case '+':
9445     pic14_emitcode(";optimize a +","");
9446     /* if unsigned or not an integral type */
9447     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9448       pic14_emitcode(";add a bit to something","");
9449     } else {
9450
9451       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9452
9453       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9454         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9455         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9456       } else
9457         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9458
9459       offset = 0;
9460       while(--big) {
9461
9462         offset++;
9463
9464         if(--small) {
9465           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9466             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9467             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9468           }
9469
9470           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9471           emitSKPNC;
9472           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9473                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9474                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9475           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9476           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9477
9478         } else {
9479           pic14_emitcode("rlf","known_zero,w");
9480
9481           /*
9482             if right is signed
9483               btfsc  right,7
9484                addlw ff
9485           */
9486           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9487             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9488             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9489           } else {
9490             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9491           }
9492         }
9493       }
9494       ret = 1;
9495     }
9496   }
9497   ret = 1;
9498
9499 release:
9500   freeAsmop(right,NULL,ic,TRUE);
9501   freeAsmop(result,NULL,ic,TRUE);
9502   freeAsmop(nextright,NULL,ic,TRUE);
9503   freeAsmop(nextleft,NULL,ic,TRUE);
9504   if(ret)
9505     nextic->generated = 1;
9506
9507   return ret;
9508 #else
9509   return 0;
9510 #endif
9511 }
9512 /*-----------------------------------------------------------------*/
9513 /* genCast - gen code for casting                                  */
9514 /*-----------------------------------------------------------------*/
9515 static void genCast (iCode *ic)
9516 {
9517     operand *result = IC_RESULT(ic);
9518     sym_link *ctype = operandType(IC_LEFT(ic));
9519     sym_link *rtype = operandType(IC_RIGHT(ic));
9520     operand *right = IC_RIGHT(ic);
9521     int size, offset ;
9522
9523     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9524     /* if they are equivalent then do nothing */
9525     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9526         return ;
9527
9528     aopOp(right,ic,FALSE) ;
9529     aopOp(result,ic,FALSE);
9530
9531     DEBUGpic14_AopType(__LINE__,NULL,right,result);
9532
9533     /* if the result is a bit */
9534     if (AOP_TYPE(result) == AOP_CRY) {
9535         /* if the right size is a literal then
9536         we know what the value is */
9537       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9538         if (AOP_TYPE(right) == AOP_LIT) {
9539
9540           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9541                       popGet(AOP(result),0));
9542
9543             if (((int) operandLitValue(right))) 
9544               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9545                        AOP(result)->aopu.aop_dir,
9546                        AOP(result)->aopu.aop_dir);
9547             else
9548               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9549                        AOP(result)->aopu.aop_dir,
9550                        AOP(result)->aopu.aop_dir);
9551
9552             goto release;
9553         }
9554
9555         /* the right is also a bit variable */
9556         if (AOP_TYPE(right) == AOP_CRY) {
9557
9558           emitCLRC;
9559           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9560
9561           pic14_emitcode("clrc","");
9562           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9563                    AOP(right)->aopu.aop_dir,
9564                    AOP(right)->aopu.aop_dir);
9565             aopPut(AOP(result),"c",0);
9566             goto release ;
9567         }
9568
9569         /* we need to or */
9570         if (AOP_TYPE(right) == AOP_REG) {
9571           emitpcode(POC_BCF,    popGet(AOP(result),0));
9572           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9573           emitpcode(POC_BSF,    popGet(AOP(result),0));
9574         }
9575         pic14_toBoolean(right);
9576         aopPut(AOP(result),"a",0);
9577         goto release ;
9578     }
9579
9580     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9581       int offset = 1;
9582       size = AOP_SIZE(result);
9583
9584       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9585
9586       emitpcode(POC_CLRF,   popGet(AOP(result),0));
9587       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9588       emitpcode(POC_INCF,   popGet(AOP(result),0));
9589
9590       while (size--)
9591         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9592
9593       goto release;
9594     }
9595
9596     /* if they are the same size : or less */
9597     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9598
9599         /* if they are in the same place */
9600       if (pic14_sameRegs(AOP(right),AOP(result)))
9601         goto release;
9602
9603       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9604       if (IS_PTR_CONST(rtype))
9605         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9606       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9607         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9608
9609       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9610         emitpcode(POC_MOVLW, popGet(AOP(right),0));
9611         emitpcode(POC_MOVWF, popGet(AOP(result),0));
9612         emitpcode(POC_MOVLW, popGet(AOP(right),1));
9613         emitpcode(POC_MOVWF, popGet(AOP(result),1));
9614         if(AOP_SIZE(result) <2)
9615           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9616
9617       } else {
9618
9619         /* if they in different places then copy */
9620         size = AOP_SIZE(result);
9621         offset = 0 ;
9622         while (size--) {
9623           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9624           emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9625
9626           //aopPut(AOP(result),
9627           // aopGet(AOP(right),offset,FALSE,FALSE),
9628           // offset);
9629
9630           offset++;
9631         }
9632       }
9633       goto release;
9634     }
9635
9636
9637     /* if the result is of type pointer */
9638     if (IS_PTR(ctype)) {
9639
9640         int p_type;
9641         sym_link *type = operandType(right);
9642         sym_link *etype = getSpec(type);
9643       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9644
9645         /* pointer to generic pointer */
9646         if (IS_GENPTR(ctype)) {
9647             char *l = zero;
9648             
9649             if (IS_PTR(type)) 
9650                 p_type = DCL_TYPE(type);
9651             else {
9652                 /* we have to go by the storage class */
9653                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9654
9655 /*              if (SPEC_OCLS(etype)->codesp )  */
9656 /*                  p_type = CPOINTER ;  */
9657 /*              else */
9658 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9659 /*                      p_type = FPOINTER ; */
9660 /*                  else */
9661 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9662 /*                          p_type = PPOINTER; */
9663 /*                      else */
9664 /*                          if (SPEC_OCLS(etype) == idata ) */
9665 /*                              p_type = IPOINTER ; */
9666 /*                          else */
9667 /*                              p_type = POINTER ; */
9668             }
9669                 
9670             /* the first two bytes are known */
9671       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9672             size = GPTRSIZE - 1; 
9673             offset = 0 ;
9674             while (size--) {
9675               if(offset < AOP_SIZE(right)) {
9676       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9677                 if ((AOP_TYPE(right) == AOP_PCODE) && 
9678                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9679                   emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9680                   emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9681                 } else { 
9682                   aopPut(AOP(result),
9683                          aopGet(AOP(right),offset,FALSE,FALSE),
9684                          offset);
9685                 }
9686               } else 
9687                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
9688               offset++;
9689             }
9690             /* the last byte depending on type */
9691             switch (p_type) {
9692             case IPOINTER:
9693             case POINTER:
9694                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9695                 break;
9696             case FPOINTER:
9697               pic14_emitcode(";BUG!? ","%d",__LINE__);
9698                 l = one;
9699                 break;
9700             case CPOINTER:
9701               pic14_emitcode(";BUG!? ","%d",__LINE__);
9702                 l = "#0x02";
9703                 break;                          
9704             case PPOINTER:
9705               pic14_emitcode(";BUG!? ","%d",__LINE__);
9706                 l = "#0x03";
9707                 break;
9708                 
9709             default:
9710                 /* this should never happen */
9711                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9712                        "got unknown pointer type");
9713                 exit(1);
9714             }
9715             //aopPut(AOP(result),l, GPTRSIZE - 1);          
9716             goto release ;
9717         }
9718         
9719         /* just copy the pointers */
9720         size = AOP_SIZE(result);
9721         offset = 0 ;
9722         while (size--) {
9723             aopPut(AOP(result),
9724                    aopGet(AOP(right),offset,FALSE,FALSE),
9725                    offset);
9726             offset++;
9727         }
9728         goto release ;
9729     }
9730     
9731
9732
9733     /* so we now know that the size of destination is greater
9734     than the size of the source.
9735     Now, if the next iCode is an operator then we might be
9736     able to optimize the operation without performing a cast.
9737     */
9738     if(genMixedOperation(ic))
9739       goto release;
9740
9741     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9742     
9743     /* we move to result for the size of source */
9744     size = AOP_SIZE(right);
9745     offset = 0 ;
9746     while (size--) {
9747       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9748       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9749       offset++;
9750     }
9751
9752     /* now depending on the sign of the destination */
9753     size = AOP_SIZE(result) - AOP_SIZE(right);
9754     /* if unsigned or not an integral type */
9755     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9756       while (size--)
9757         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9758     } else {
9759       /* we need to extend the sign :{ */
9760
9761       if(size == 1) {
9762         /* Save one instruction of casting char to int */
9763         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9764         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9765         emitpcode(POC_DECF,   popGet(AOP(result),offset));
9766       } else {
9767         emitpcodeNULLop(POC_CLRW);
9768
9769         if(offset)
9770           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9771         else
9772           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9773         
9774         emitpcode(POC_MOVLW,   popGetLit(0xff));
9775
9776         while (size--)
9777           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9778       }
9779     }
9780
9781 release:
9782     freeAsmop(right,NULL,ic,TRUE);
9783     freeAsmop(result,NULL,ic,TRUE);
9784
9785 }
9786
9787 /*-----------------------------------------------------------------*/
9788 /* genDjnz - generate decrement & jump if not zero instrucion      */
9789 /*-----------------------------------------------------------------*/
9790 static int genDjnz (iCode *ic, iCode *ifx)
9791 {
9792     symbol *lbl, *lbl1;
9793     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9794
9795     if (!ifx)
9796         return 0;
9797     
9798     /* if the if condition has a false label
9799        then we cannot save */
9800     if (IC_FALSE(ifx))
9801         return 0;
9802
9803     /* if the minus is not of the form 
9804        a = a - 1 */
9805     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9806         !IS_OP_LITERAL(IC_RIGHT(ic)))
9807         return 0;
9808
9809     if (operandLitValue(IC_RIGHT(ic)) != 1)
9810         return 0;
9811
9812     /* if the size of this greater than one then no
9813        saving */
9814     if (getSize(operandType(IC_RESULT(ic))) > 1)
9815         return 0;
9816
9817     /* otherwise we can save BIG */
9818     lbl = newiTempLabel(NULL);
9819     lbl1= newiTempLabel(NULL);
9820
9821     aopOp(IC_RESULT(ic),ic,FALSE);
9822     
9823     if (IS_AOP_PREG(IC_RESULT(ic))) {
9824         pic14_emitcode("dec","%s",
9825                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9826         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9827         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9828     } else {    
9829
9830
9831       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9832       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9833
9834       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9835       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9836
9837     }
9838 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9839 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9840 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9841 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9842
9843     
9844     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9845     ifx->generated = 1;
9846     return 1;
9847 }
9848
9849 /*-----------------------------------------------------------------*/
9850 /* genReceive - generate code for a receive iCode                  */
9851 /*-----------------------------------------------------------------*/
9852 static void genReceive (iCode *ic)
9853 {    
9854   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9855
9856   if (isOperandInFarSpace(IC_RESULT(ic)) && 
9857       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9858         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9859
9860     int size = getSize(operandType(IC_RESULT(ic)));
9861     int offset =  fReturnSizePic - size;
9862     while (size--) {
9863       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9864                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9865       offset++;
9866     }
9867     aopOp(IC_RESULT(ic),ic,FALSE);  
9868     size = AOP_SIZE(IC_RESULT(ic));
9869     offset = 0;
9870     while (size--) {
9871       pic14_emitcode ("pop","acc");
9872       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9873     }
9874         
9875   } else {
9876     _G.accInUse++;
9877     aopOp(IC_RESULT(ic),ic,FALSE);  
9878     _G.accInUse--;
9879     assignResultValue(IC_RESULT(ic));   
9880   }
9881
9882   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9883 }
9884
9885 /*-----------------------------------------------------------------*/
9886 /* genpic14Code - generate code for pic14 based controllers        */
9887 /*-----------------------------------------------------------------*/
9888 /*
9889  * At this point, ralloc.c has gone through the iCode and attempted
9890  * to optimize in a way suitable for a PIC. Now we've got to generate
9891  * PIC instructions that correspond to the iCode.
9892  *
9893  * Once the instructions are generated, we'll pass through both the
9894  * peep hole optimizer and the pCode optimizer.
9895  *-----------------------------------------------------------------*/
9896
9897 void genpic14Code (iCode *lic)
9898 {
9899     iCode *ic;
9900     int cln = 0;
9901
9902     lineHead = lineCurr = NULL;
9903
9904     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9905     addpBlock(pb);
9906
9907     /* if debug information required */
9908     if (options.debug && currFunc) { 
9909       if (currFunc) {
9910         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9911         _G.debugLine = 1;
9912         if (IS_STATIC(currFunc->etype)) {
9913           pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9914           //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9915         } else {
9916           pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9917           //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9918         }
9919         _G.debugLine = 0;
9920       }
9921     }
9922
9923
9924     for (ic = lic ; ic ; ic = ic->next ) {
9925
9926       DEBUGpic14_emitcode(";ic","");
9927         if ( cln != ic->lineno ) {
9928             if ( options.debug ) {
9929                 _G.debugLine = 1;
9930                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9931                          FileBaseName(ic->filename),ic->lineno,
9932                          ic->level,ic->block);
9933                 _G.debugLine = 0;
9934             }
9935             /*
9936               pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9937               pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9938               printCLine(ic->filename, ic->lineno));
9939             */
9940             if (!options.noCcodeInAsm) {
9941               addpCode2pBlock(pb,
9942                               newpCodeCSource(ic->lineno, 
9943                                               ic->filename, 
9944                                               printCLine(ic->filename, ic->lineno)));
9945             }
9946
9947             cln = ic->lineno ;
9948         }
9949
9950         // if you want printILine too, look at ../mcs51/gen.c, i don't understand this :)
9951
9952         /* if the result is marked as
9953            spilt and rematerializable or code for
9954            this has already been generated then
9955            do nothing */
9956         if (resultRemat(ic) || ic->generated ) 
9957             continue ;
9958         
9959         /* depending on the operation */
9960         switch (ic->op) {
9961         case '!' :
9962             genNot(ic);
9963             break;
9964             
9965         case '~' :
9966             genCpl(ic);
9967             break;
9968             
9969         case UNARYMINUS:
9970             genUminus (ic);
9971             break;
9972             
9973         case IPUSH:
9974             genIpush (ic);
9975             break;
9976             
9977         case IPOP:
9978             /* IPOP happens only when trying to restore a 
9979                spilt live range, if there is an ifx statement
9980                following this pop then the if statement might
9981                be using some of the registers being popped which
9982                would destory the contents of the register so
9983                we need to check for this condition and handle it */
9984             if (ic->next            && 
9985                 ic->next->op == IFX &&
9986                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9987                 genIfx (ic->next,ic);
9988             else
9989                 genIpop (ic);
9990             break; 
9991             
9992         case CALL:
9993             genCall (ic);
9994             break;
9995             
9996         case PCALL:
9997             genPcall (ic);
9998             break;
9999             
10000         case FUNCTION:
10001             genFunction (ic);
10002             break;
10003             
10004         case ENDFUNCTION:
10005             genEndFunction (ic);
10006             break;
10007             
10008         case RETURN:
10009             genRet (ic);
10010             break;
10011             
10012         case LABEL:
10013             genLabel (ic);
10014             break;
10015             
10016         case GOTO:
10017             genGoto (ic);
10018             break;
10019             
10020         case '+' :
10021             genPlus (ic) ;
10022             break;
10023             
10024         case '-' :
10025             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10026                 genMinus (ic);
10027             break;
10028             
10029         case '*' :
10030             genMult (ic);
10031             break;
10032             
10033         case '/' :
10034             genDiv (ic) ;
10035             break;
10036             
10037         case '%' :
10038             genMod (ic);
10039             break;
10040             
10041         case '>' :
10042             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10043             break;
10044             
10045         case '<' :
10046             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10047             break;
10048             
10049         case LE_OP:
10050         case GE_OP:
10051         case NE_OP:
10052             
10053             /* note these two are xlated by algebraic equivalence
10054                during parsing SDCC.y */
10055             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10056                    "got '>=' or '<=' shouldn't have come here");
10057             break;      
10058             
10059         case EQ_OP:
10060             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10061             break;          
10062             
10063         case AND_OP:
10064             genAndOp (ic);
10065             break;
10066             
10067         case OR_OP:
10068             genOrOp (ic);
10069             break;
10070             
10071         case '^' :
10072             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10073             break;
10074             
10075         case '|' :
10076                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10077             break;
10078             
10079         case BITWISEAND:
10080             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10081             break;
10082             
10083         case INLINEASM:
10084             genInline (ic);
10085             break;
10086             
10087         case RRC:
10088             genRRC (ic);
10089             break;
10090             
10091         case RLC:
10092             genRLC (ic);
10093             break;
10094             
10095         case GETHBIT:
10096             genGetHbit (ic);
10097             break;
10098             
10099         case LEFT_OP:
10100             genLeftShift (ic);
10101             break;
10102             
10103         case RIGHT_OP:
10104             genRightShift (ic);
10105             break;
10106             
10107         case GET_VALUE_AT_ADDRESS:
10108             genPointerGet(ic);
10109             break;
10110             
10111         case '=' :
10112             if (POINTER_SET(ic))
10113                 genPointerSet(ic);
10114             else
10115                 genAssign(ic);
10116             break;
10117             
10118         case IFX:
10119             genIfx (ic,NULL);
10120             break;
10121             
10122         case ADDRESS_OF:
10123             genAddrOf (ic);
10124             break;
10125             
10126         case JUMPTABLE:
10127             genJumpTab (ic);
10128             break;
10129             
10130         case CAST:
10131             genCast (ic);
10132             break;
10133             
10134         case RECEIVE:
10135             genReceive(ic);
10136             break;
10137             
10138         case SEND:
10139             addSet(&_G.sendSet,ic);
10140             break;
10141
10142         default :
10143             ic = ic;
10144         }
10145     }
10146     
10147
10148     /* now we are ready to call the 
10149        peep hole optimizer */
10150     if (!options.nopeep) {
10151       peepHole (&lineHead);
10152     }
10153     /* now do the actual printing */
10154     printLine (lineHead,codeOutFile);
10155
10156 #ifdef PCODE_DEBUG
10157     DFPRINTF((stderr,"printing pBlock\n\n"));
10158     printpBlock(stdout,pb);
10159 #endif
10160
10161     return;
10162 }