Fixed bug 609628 ==> x=(x+1)&0x0f generated bad code in the pic port.
[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           if(ifx) ifx->generated = 1;
4090         } else {
4091           /* unsigned comparisons to a literal byte */
4092
4093           switch(lit & 0xff ) {
4094           case 0:
4095             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4096             genSkipz2(&rFalseIfx,0);
4097             if(ifx) ifx->generated = 1;
4098             break;
4099           case 0x7f:
4100             rFalseIfx.condition ^= 1;
4101             genSkipCond(&rFalseIfx,right,0,7);
4102             if(ifx) ifx->generated = 1;
4103             break;
4104
4105           default:
4106             emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4107             emitpcode(POC_SUBFW, popGet(AOP(right),0));
4108             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4109             rFalseIfx.condition ^= 1;
4110             if (AOP_TYPE(result) == AOP_CRY) {
4111               genSkipc(&rFalseIfx);
4112               if(ifx) ifx->generated = 1;
4113             } else {
4114               DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4115               emitpcode(POC_CLRF, popGet(AOP(result),0));
4116               emitpcode(POC_RLF, popGet(AOP(result),0));
4117               emitpcode(POC_MOVLW, popGetLit(0x01));
4118               emitpcode(POC_XORWF, popGet(AOP(result),0));
4119             }         
4120             break;
4121           }
4122         }
4123
4124         //goto check_carry;
4125         return;
4126
4127       } else {
4128
4129         /* Size is greater than 1 */
4130
4131         if(sign) {
4132           int lp1 = lit+1;
4133
4134           size--;
4135
4136           if(lp1 == 0) {
4137             /* this means lit = 0xffffffff, or -1 */
4138
4139
4140             DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4141             rFalseIfx.condition ^= 1;
4142             genSkipCond(&rFalseIfx,right,size,7);
4143             if(ifx) ifx->generated = 1;
4144             return;
4145           }
4146
4147           if(lit == 0) {
4148             int s = size;
4149
4150             if(rFalseIfx.condition) {
4151               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4152               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4153             }
4154
4155             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4156             while(size--)
4157               emitpcode(POC_IORFW, popGet(AOP(right),size));
4158
4159
4160             emitSKPZ;
4161             if(rFalseIfx.condition) {
4162               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4163               emitpLabel(truelbl->key);
4164             }else {
4165               rFalseIfx.condition ^= 1;
4166               genSkipCond(&rFalseIfx,right,s,7);
4167             }
4168
4169             if(ifx) ifx->generated = 1;
4170             return;
4171           }
4172
4173           if((size == 1) &&  (0 == (lp1&0xff))) {
4174             /* lower byte of signed word is zero */
4175             DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4176             i = ((lp1 >> 8) & 0xff) ^0x80;
4177             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4178             emitpcode(POC_ADDLW, popGetLit( 0x80));
4179             emitpcode(POC_ADDLW, popGetLit(0x100-i));
4180             rFalseIfx.condition ^= 1;
4181             genSkipc(&rFalseIfx);
4182
4183
4184             if(ifx) ifx->generated = 1;
4185             return;
4186           }
4187
4188           if(lit & (0x80 << (size*8))) {
4189             /* Lit is less than zero */
4190             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4191             //rFalseIfx.condition ^= 1;
4192             //genSkipCond(&rFalseIfx,left,size,7);
4193             //rFalseIfx.condition ^= 1;
4194             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4195             //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4196
4197             if(rFalseIfx.condition)
4198               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4199             else
4200               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4201
4202
4203           } else {
4204             /* Lit is greater than or equal to zero */
4205             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4206             //rFalseIfx.condition ^= 1;
4207             //genSkipCond(&rFalseIfx,right,size,7);
4208             //rFalseIfx.condition ^= 1;
4209
4210             //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4211             //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4212
4213             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4214             if(rFalseIfx.condition)
4215               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4216             else
4217               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4218
4219           }
4220
4221
4222           emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4223           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4224
4225           while(size--) {
4226
4227             emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4228             emitSKPNZ;
4229             emitpcode(POC_SUBFW, popGet(AOP(right),size));
4230           }
4231           rFalseIfx.condition ^= 1;
4232           //rFalseIfx.condition = 1;
4233           genSkipc(&rFalseIfx);
4234
4235           emitpLabel(truelbl->key);
4236
4237           if(ifx) ifx->generated = 1;
4238           return;
4239           // end of if (sign)
4240         } else {
4241
4242           /* compare word or long to an unsigned literal on the right.*/
4243
4244
4245           size--;
4246           if(lit < 0xff) {
4247             DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4248             switch (lit) {
4249             case 0:
4250               break; /* handled above */
4251 /*
4252             case 0xff:
4253               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4254               while(size--)
4255                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4256               genSkipz2(&rFalseIfx,0);
4257               break;
4258 */
4259             default:
4260               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4261               while(--size)
4262                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4263
4264               emitSKPZ;
4265               if(rFalseIfx.condition)
4266                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4267               else
4268                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4269
4270
4271               emitpcode(POC_MOVLW, popGetLit(lit+1));
4272               emitpcode(POC_SUBFW, popGet(AOP(right),0));
4273
4274               rFalseIfx.condition ^= 1;
4275               genSkipc(&rFalseIfx);
4276             }
4277
4278             emitpLabel(truelbl->key);
4279
4280             if(ifx) ifx->generated = 1;
4281             return;
4282           }
4283
4284
4285           lit++;
4286           DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4287           i = (lit >> (size*8)) & 0xff;
4288
4289           emitpcode(POC_MOVLW, popGetLit(i));
4290           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4291
4292           while(size--) {
4293             i = (lit >> (size*8)) & 0xff;
4294
4295             if(i) {
4296               emitpcode(POC_MOVLW, popGetLit(i));
4297               emitSKPNZ;
4298               emitpcode(POC_SUBFW, popGet(AOP(right),size));
4299             } else {
4300               /* this byte of the lit is zero, 
4301                *if it's not the last then OR in the variable */
4302               if(size)
4303                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4304             }
4305           }
4306
4307
4308           emitpLabel(lbl->key);
4309
4310           rFalseIfx.condition ^= 1;
4311           genSkipc(&rFalseIfx);
4312         }
4313
4314         if(sign)
4315           emitpLabel(truelbl->key);
4316         if(ifx) ifx->generated = 1;
4317         return;
4318       }
4319     }
4320     /* Compare two variables */
4321
4322     DEBUGpic14_emitcode(";sign","%d",sign);
4323
4324     size--;
4325     if(sign) {
4326       /* Sigh. thus sucks... */
4327       if(size) {
4328         emitpcode(POC_MOVFW, popGet(AOP(left),size));
4329         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4330         emitpcode(POC_MOVLW, popGetLit(0x80));
4331         emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4332         emitpcode(POC_XORFW, popGet(AOP(right),size));
4333         emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4334       } else {
4335         /* Signed char comparison */
4336         /* Special thanks to Nikolai Golovchenko for this snippet */
4337         emitpcode(POC_MOVFW, popGet(AOP(right),0));
4338         emitpcode(POC_SUBFW, popGet(AOP(left),0));
4339         emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4340         emitpcode(POC_XORFW, popGet(AOP(left),0));
4341         emitpcode(POC_XORFW, popGet(AOP(right),0));
4342         emitpcode(POC_ADDLW, popGetLit(0x80));
4343
4344         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4345         genSkipc(&rFalseIfx);
4346           
4347         if(ifx) ifx->generated = 1;
4348         return;
4349       }
4350
4351     } else {
4352
4353       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4354       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4355     }
4356
4357
4358     /* The rest of the bytes of a multi-byte compare */
4359     while (size) {
4360
4361       emitSKPZ;
4362       emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4363       size--;
4364
4365       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4366       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4367
4368
4369     }
4370
4371     emitpLabel(lbl->key);
4372
4373     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4374     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4375         (AOP_TYPE(result) == AOP_REG)) {
4376       emitpcode(POC_CLRF, popGet(AOP(result),0));
4377       emitpcode(POC_RLF, popGet(AOP(result),0));
4378     } else {
4379       genSkipc(&rFalseIfx);
4380     }         
4381     //genSkipc(&rFalseIfx);
4382     if(ifx) ifx->generated = 1;
4383
4384     return;
4385
4386   }
4387
4388   // check_carry:
4389   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4390     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4391     pic14_outBitC(result);
4392   } else {
4393     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4394     /* if the result is used in the next
4395        ifx conditional branch then generate
4396        code a little differently */
4397     if (ifx )
4398       genIfxJump (ifx,"c");
4399     else
4400       pic14_outBitC(result);
4401     /* leave the result in acc */
4402   }
4403
4404 }
4405
4406 /*-----------------------------------------------------------------*/
4407 /* genCmpGt :- greater than comparison                             */
4408 /*-----------------------------------------------------------------*/
4409 static void genCmpGt (iCode *ic, iCode *ifx)
4410 {
4411     operand *left, *right, *result;
4412     sym_link *letype , *retype;
4413     int sign ;
4414
4415     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4416     left = IC_LEFT(ic);
4417     right= IC_RIGHT(ic);
4418     result = IC_RESULT(ic);
4419
4420     letype = getSpec(operandType(left));
4421     retype =getSpec(operandType(right));
4422     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4423     /* assign the amsops */
4424     aopOp (left,ic,FALSE);
4425     aopOp (right,ic,FALSE);
4426     aopOp (result,ic,TRUE);
4427
4428     genCmp(right, left, result, ifx, sign);
4429
4430     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4431     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4432     freeAsmop(result,NULL,ic,TRUE); 
4433 }
4434
4435 /*-----------------------------------------------------------------*/
4436 /* genCmpLt - less than comparisons                                */
4437 /*-----------------------------------------------------------------*/
4438 static void genCmpLt (iCode *ic, iCode *ifx)
4439 {
4440     operand *left, *right, *result;
4441     sym_link *letype , *retype;
4442     int sign ;
4443
4444     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4445     left = IC_LEFT(ic);
4446     right= IC_RIGHT(ic);
4447     result = IC_RESULT(ic);
4448
4449     letype = getSpec(operandType(left));
4450     retype =getSpec(operandType(right));
4451     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4452
4453     /* assign the amsops */
4454     aopOp (left,ic,FALSE);
4455     aopOp (right,ic,FALSE);
4456     aopOp (result,ic,TRUE);
4457
4458     genCmp(left, right, result, ifx, sign);
4459
4460     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4461     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4462     freeAsmop(result,NULL,ic,TRUE); 
4463 }
4464
4465 /*-----------------------------------------------------------------*/
4466 /* genc16bit2lit - compare a 16 bit value to a literal             */
4467 /*-----------------------------------------------------------------*/
4468 static void genc16bit2lit(operand *op, int lit, int offset)
4469 {
4470   int i;
4471
4472   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4473   if( (lit&0xff) == 0) 
4474     i=1;
4475   else
4476     i=0;
4477
4478   switch( BYTEofLONG(lit,i)) { 
4479   case 0:
4480     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4481     break;
4482   case 1:
4483     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4484     break;
4485   case 0xff:
4486     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4487     break;
4488   default:
4489     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4490     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4491   }
4492
4493   i ^= 1;
4494
4495   switch( BYTEofLONG(lit,i)) { 
4496   case 0:
4497     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4498     break;
4499   case 1:
4500     emitSKPNZ;
4501     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4502     break;
4503   case 0xff:
4504     emitSKPNZ;
4505     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4506     break;
4507   default:
4508     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4509     emitSKPNZ;
4510     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4511
4512   }
4513
4514 }
4515
4516 /*-----------------------------------------------------------------*/
4517 /* gencjneshort - compare and jump if not equal                    */
4518 /*-----------------------------------------------------------------*/
4519 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4520 {
4521   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4522   int offset = 0;
4523   int res_offset = 0;  /* the result may be a different size then left or right */
4524   int res_size = AOP_SIZE(result);
4525   resolvedIfx rIfx;
4526   symbol *lbl;
4527
4528   unsigned long lit = 0L;
4529   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4530   DEBUGpic14_AopType(__LINE__,left,right,result);
4531   if(result)
4532     DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4533   resolveIfx(&rIfx,ifx);
4534   lbl =  newiTempLabel(NULL);
4535
4536
4537   /* if the left side is a literal or 
4538      if the right is in a pointer register and left 
4539      is not */
4540   if ((AOP_TYPE(left) == AOP_LIT) || 
4541       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4542     operand *t = right;
4543     right = left;
4544     left = t;
4545   }
4546   if(AOP_TYPE(right) == AOP_LIT)
4547     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4548
4549   /* if the right side is a literal then anything goes */
4550   if (AOP_TYPE(right) == AOP_LIT &&
4551       AOP_TYPE(left) != AOP_DIR ) {
4552     switch(size) {
4553     case 2:
4554       genc16bit2lit(left, lit, 0);
4555       emitSKPNZ;
4556       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4557       break;
4558     default:
4559       while (size--) {
4560         if(lit & 0xff) {
4561           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4562           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4563         } else {
4564           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4565         }
4566
4567         emitSKPNZ;
4568         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4569         offset++;
4570         if(res_offset < res_size-1)
4571           res_offset++;
4572         lit >>= 8;
4573       }
4574       break;
4575     }
4576   }
4577
4578   /* if the right side is in a register or in direct space or
4579      if the left is a pointer register & right is not */    
4580   else if (AOP_TYPE(right) == AOP_REG ||
4581            AOP_TYPE(right) == AOP_DIR || 
4582            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4583            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4584     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4585     int lbl_key = lbl->key;
4586
4587     if(result) {
4588       emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4589       //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4590     }else {
4591       DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4592       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4593               __FUNCTION__,__LINE__);
4594       return;
4595     }
4596
4597 /*     switch(size) { */
4598 /*     case 2: */
4599 /*       genc16bit2lit(left, lit, 0); */
4600 /*       emitSKPNZ; */
4601 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4602 /*       break; */
4603 /*     default: */
4604     while (size--) {
4605       int emit_skip=1;
4606       if((AOP_TYPE(left) == AOP_DIR) && 
4607          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4608
4609         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4610         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4611
4612       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4613             
4614         switch (lit & 0xff) {
4615         case 0:
4616           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4617           break;
4618         case 1:
4619           emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4620           emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4621           //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4622           emit_skip=0;
4623           break;
4624         case 0xff:
4625           emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4626           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4627           //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4628           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4629           emit_skip=0;
4630           break;
4631         default:
4632           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4633           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4634         }
4635         lit >>= 8;
4636
4637       } else {
4638         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4639       }
4640       if(emit_skip) {
4641         if(AOP_TYPE(result) == AOP_CRY) {
4642           pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4643           if(rIfx.condition)
4644             emitSKPNZ;
4645           else
4646             emitSKPZ;
4647           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4648         } else {
4649           /* fix me. probably need to check result size too */
4650           //emitpcode(POC_CLRF,popGet(AOP(result),0));
4651           if(rIfx.condition)
4652             emitSKPZ;
4653           else
4654             emitSKPNZ;
4655           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4656           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4657         }
4658         if(ifx)
4659           ifx->generated=1;
4660       }
4661       emit_skip++;
4662       offset++;
4663       if(res_offset < res_size-1)
4664         res_offset++;
4665     }
4666 /*       break; */
4667 /*     } */
4668   } else if(AOP_TYPE(right) == AOP_REG &&
4669             AOP_TYPE(left) != AOP_DIR){
4670
4671     while(size--) {
4672       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4673       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4674       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4675       if(rIfx.condition)
4676         emitSKPNZ;
4677       else
4678         emitSKPZ;
4679       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4680       offset++;
4681       if(res_offset < res_size-1)
4682         res_offset++;
4683     }
4684       
4685   }else{
4686     /* right is a pointer reg need both a & b */
4687     while(size--) {
4688       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4689       if(strcmp(l,"b"))
4690         pic14_emitcode("mov","b,%s",l);
4691       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4692       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4693       offset++;
4694     }
4695   }
4696
4697   emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4698   if(!rIfx.condition)
4699     emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4700
4701   emitpLabel(lbl->key);
4702
4703   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4704
4705   if(ifx)
4706     ifx->generated = 1;
4707 }
4708
4709 #if 0
4710 /*-----------------------------------------------------------------*/
4711 /* gencjne - compare and jump if not equal                         */
4712 /*-----------------------------------------------------------------*/
4713 static void gencjne(operand *left, operand *right, iCode *ifx)
4714 {
4715     symbol *tlbl  = newiTempLabel(NULL);
4716
4717     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4718     gencjneshort(left, right, lbl);
4719
4720     pic14_emitcode("mov","a,%s",one);
4721     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4722     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4723     pic14_emitcode("clr","a");
4724     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4725
4726     emitpLabel(lbl->key);
4727     emitpLabel(tlbl->key);
4728
4729 }
4730 #endif
4731
4732 /*-----------------------------------------------------------------*/
4733 /* genCmpEq - generates code for equal to                          */
4734 /*-----------------------------------------------------------------*/
4735 static void genCmpEq (iCode *ic, iCode *ifx)
4736 {
4737     operand *left, *right, *result;
4738     unsigned long lit = 0L;
4739     int size,offset=0;
4740
4741     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4742
4743     if(ifx)
4744       DEBUGpic14_emitcode ("; ifx is non-null","");
4745     else
4746       DEBUGpic14_emitcode ("; ifx is null","");
4747
4748     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4749     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4750     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4751
4752     size = max(AOP_SIZE(left),AOP_SIZE(right));
4753
4754     DEBUGpic14_AopType(__LINE__,left,right,result);
4755
4756     /* if literal, literal on the right or 
4757     if the right is in a pointer register and left 
4758     is not */
4759     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4760         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4761       operand *tmp = right ;
4762       right = left;
4763       left = tmp;
4764     }
4765
4766
4767     if(ifx && !AOP_SIZE(result)){
4768         symbol *tlbl;
4769         /* if they are both bit variables */
4770         if (AOP_TYPE(left) == AOP_CRY &&
4771             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4772             if(AOP_TYPE(right) == AOP_LIT){
4773                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4774                 if(lit == 0L){
4775                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4776                     pic14_emitcode("cpl","c");
4777                 } else if(lit == 1L) {
4778                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4779                 } else {
4780                     pic14_emitcode("clr","c");
4781                 }
4782                 /* AOP_TYPE(right) == AOP_CRY */
4783             } else {
4784                 symbol *lbl = newiTempLabel(NULL);
4785                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4786                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4787                 pic14_emitcode("cpl","c");
4788                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4789             }
4790             /* if true label then we jump if condition
4791             supplied is true */
4792             tlbl = newiTempLabel(NULL);
4793             if ( IC_TRUE(ifx) ) {
4794                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4795                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4796             } else {
4797                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4798                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4799             }
4800             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4801
4802             {
4803               /* left and right are both bit variables, result is carry */
4804               resolvedIfx rIfx;
4805               
4806               resolveIfx(&rIfx,ifx);
4807
4808               emitpcode(POC_MOVLW,popGet(AOP(left),0));
4809               emitpcode(POC_ANDFW,popGet(AOP(left),0));
4810               emitpcode(POC_BTFSC,popGet(AOP(right),0));
4811               emitpcode(POC_ANDLW,popGet(AOP(left),0));
4812               genSkipz2(&rIfx,0);
4813             }
4814         } else {
4815
4816           /* They're not both bit variables. Is the right a literal? */
4817           if(AOP_TYPE(right) == AOP_LIT) {
4818             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4819             
4820             switch(size) {
4821
4822             case 1:
4823               switch(lit & 0xff) {
4824               case 1:
4825                 if ( IC_TRUE(ifx) ) {
4826                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4827                   emitSKPNZ;
4828                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4829                 } else {
4830                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4831                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4832                 }
4833                 break;
4834               case 0xff:
4835                 if ( IC_TRUE(ifx) ) {
4836                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4837                   emitSKPNZ;
4838                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4839                 } else {
4840                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4841                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4842                 }
4843                 break;
4844               default:
4845                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4846                 if(lit)
4847                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4848                 genSkip(ifx,'z');
4849               }
4850
4851
4852               /* end of size == 1 */
4853               break;
4854               
4855             case 2:
4856               genc16bit2lit(left,lit,offset);
4857               genSkip(ifx,'z');
4858               break;
4859               /* end of size == 2 */
4860
4861             default:
4862               /* size is 4 */
4863               if(lit==0) {
4864                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4865                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4866                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4867                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4868
4869               } else {
4870
4871                 /* search for patterns that can be optimized */
4872
4873                 genc16bit2lit(left,lit,0);
4874                 lit >>= 16;
4875                 if(lit) {
4876                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4877                   //genSkip(ifx,'z');
4878                   genc16bit2lit(left,lit,2);
4879                 } else {
4880                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4881                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4882
4883                 }
4884                 
4885               }
4886
4887               genSkip(ifx,'z');
4888             }
4889           
4890             ifx->generated = 1;
4891             goto release ;
4892             
4893
4894           } else if(AOP_TYPE(right) == AOP_CRY ) {
4895             /* we know the left is not a bit, but that the right is */
4896             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4897             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4898                       popGet(AOP(right),offset));
4899             emitpcode(POC_XORLW,popGetLit(1));
4900
4901             /* if the two are equal, then W will be 0 and the Z bit is set
4902              * we could test Z now, or go ahead and check the high order bytes if
4903              * the variable we're comparing is larger than a byte. */
4904
4905             while(--size)
4906               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4907
4908             if ( IC_TRUE(ifx) ) {
4909               emitSKPNZ;
4910               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4911               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4912             } else {
4913               emitSKPZ;
4914               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4915               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4916             }
4917
4918           } else {
4919             /* They're both variables that are larger than bits */
4920             int s = size;
4921
4922             tlbl = newiTempLabel(NULL);
4923
4924             while(size--) {
4925               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4926               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4927
4928               if ( IC_TRUE(ifx) ) {
4929                 if(size) {
4930                   emitSKPZ;
4931                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4932                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4933                 } else {
4934                   emitSKPNZ;
4935                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4936                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4937                 }
4938               } else {
4939                 emitSKPZ;
4940                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4941                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4942               }
4943               offset++;
4944             }
4945             if(s>1 && IC_TRUE(ifx)) {
4946               emitpLabel(tlbl->key);
4947               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4948             }
4949           }
4950         }
4951         /* mark the icode as generated */
4952         ifx->generated = 1;
4953         goto release ;
4954     }
4955
4956     /* if they are both bit variables */
4957     if (AOP_TYPE(left) == AOP_CRY &&
4958         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4959         if(AOP_TYPE(right) == AOP_LIT){
4960             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4961             if(lit == 0L){
4962                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4963                 pic14_emitcode("cpl","c");
4964             } else if(lit == 1L) {
4965                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4966             } else {
4967                 pic14_emitcode("clr","c");
4968             }
4969             /* AOP_TYPE(right) == AOP_CRY */
4970         } else {
4971             symbol *lbl = newiTempLabel(NULL);
4972             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4973             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4974             pic14_emitcode("cpl","c");
4975             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4976         }
4977         /* c = 1 if egal */
4978         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4979             pic14_outBitC(result);
4980             goto release ;
4981         }
4982         if (ifx) {
4983             genIfxJump (ifx,"c");
4984             goto release ;
4985         }
4986         /* if the result is used in an arithmetic operation
4987         then put the result in place */
4988         pic14_outBitC(result);
4989     } else {
4990       
4991       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4992       gencjne(left,right,result,ifx);
4993 /*
4994       if(ifx) 
4995         gencjne(left,right,newiTempLabel(NULL));
4996       else {
4997         if(IC_TRUE(ifx)->key)
4998           gencjne(left,right,IC_TRUE(ifx)->key);
4999         else
5000           gencjne(left,right,IC_FALSE(ifx)->key);
5001         ifx->generated = 1;
5002         goto release ;
5003       }
5004       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5005         aopPut(AOP(result),"a",0);
5006         goto release ;
5007       }
5008
5009       if (ifx) {
5010         genIfxJump (ifx,"a");
5011         goto release ;
5012       }
5013 */
5014       /* if the result is used in an arithmetic operation
5015          then put the result in place */
5016 /*
5017       if (AOP_TYPE(result) != AOP_CRY) 
5018         pic14_outAcc(result);
5019 */
5020       /* leave the result in acc */
5021     }
5022
5023 release:
5024     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5025     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5026     freeAsmop(result,NULL,ic,TRUE);
5027 }
5028
5029 /*-----------------------------------------------------------------*/
5030 /* ifxForOp - returns the icode containing the ifx for operand     */
5031 /*-----------------------------------------------------------------*/
5032 static iCode *ifxForOp ( operand *op, iCode *ic )
5033 {
5034     /* if true symbol then needs to be assigned */
5035     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5036     if (IS_TRUE_SYMOP(op))
5037         return NULL ;
5038
5039     /* if this has register type condition and
5040     the next instruction is ifx with the same operand
5041     and live to of the operand is upto the ifx only then */
5042     if (ic->next &&
5043         ic->next->op == IFX &&
5044         IC_COND(ic->next)->key == op->key &&
5045         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5046         return ic->next;
5047
5048     if (ic->next &&
5049         ic->next->op == IFX &&
5050         IC_COND(ic->next)->key == op->key) {
5051       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5052       return ic->next;
5053     }
5054
5055     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5056     if (ic->next &&
5057         ic->next->op == IFX)
5058       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5059
5060     if (ic->next &&
5061         ic->next->op == IFX &&
5062         IC_COND(ic->next)->key == op->key) {
5063       DEBUGpic14_emitcode ("; "," key is okay");
5064       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5065                            OP_SYMBOL(op)->liveTo,
5066                            ic->next->seq);
5067     }
5068
5069
5070     return NULL;
5071 }
5072 /*-----------------------------------------------------------------*/
5073 /* genAndOp - for && operation                                     */
5074 /*-----------------------------------------------------------------*/
5075 static void genAndOp (iCode *ic)
5076 {
5077     operand *left,*right, *result;
5078 /*     symbol *tlbl; */
5079
5080     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5081     /* note here that && operations that are in an
5082     if statement are taken away by backPatchLabels
5083     only those used in arthmetic operations remain */
5084     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5085     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5086     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5087
5088     DEBUGpic14_AopType(__LINE__,left,right,result);
5089
5090     emitpcode(POC_MOVFW,popGet(AOP(left),0));
5091     emitpcode(POC_ANDFW,popGet(AOP(right),0));
5092     emitpcode(POC_MOVWF,popGet(AOP(result),0));
5093
5094     /* if both are bit variables */
5095 /*     if (AOP_TYPE(left) == AOP_CRY && */
5096 /*         AOP_TYPE(right) == AOP_CRY ) { */
5097 /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5098 /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5099 /*         pic14_outBitC(result); */
5100 /*     } else { */
5101 /*         tlbl = newiTempLabel(NULL); */
5102 /*         pic14_toBoolean(left);     */
5103 /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5104 /*         pic14_toBoolean(right); */
5105 /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5106 /*         pic14_outBitAcc(result); */
5107 /*     } */
5108
5109     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5110     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5111     freeAsmop(result,NULL,ic,TRUE);
5112 }
5113
5114
5115 /*-----------------------------------------------------------------*/
5116 /* genOrOp - for || operation                                      */
5117 /*-----------------------------------------------------------------*/
5118 /*
5119   tsd pic port -
5120   modified this code, but it doesn't appear to ever get called
5121 */
5122
5123 static void genOrOp (iCode *ic)
5124 {
5125     operand *left,*right, *result;
5126     symbol *tlbl;
5127
5128     /* note here that || operations that are in an
5129     if statement are taken away by backPatchLabels
5130     only those used in arthmetic operations remain */
5131     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5132     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5133     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5134     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5135
5136     DEBUGpic14_AopType(__LINE__,left,right,result);
5137
5138     /* if both are bit variables */
5139     if (AOP_TYPE(left) == AOP_CRY &&
5140         AOP_TYPE(right) == AOP_CRY ) {
5141       pic14_emitcode("clrc","");
5142       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5143                AOP(left)->aopu.aop_dir,
5144                AOP(left)->aopu.aop_dir);
5145       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5146                AOP(right)->aopu.aop_dir,
5147                AOP(right)->aopu.aop_dir);
5148       pic14_emitcode("setc","");
5149
5150     } else {
5151         tlbl = newiTempLabel(NULL);
5152         pic14_toBoolean(left);
5153         emitSKPZ;
5154         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5155         pic14_toBoolean(right);
5156         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5157
5158         pic14_outBitAcc(result);
5159     }
5160
5161     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5162     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5163     freeAsmop(result,NULL,ic,TRUE);            
5164 }
5165
5166 /*-----------------------------------------------------------------*/
5167 /* isLiteralBit - test if lit == 2^n                               */
5168 /*-----------------------------------------------------------------*/
5169 static int isLiteralBit(unsigned long lit)
5170 {
5171     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5172     0x100L,0x200L,0x400L,0x800L,
5173     0x1000L,0x2000L,0x4000L,0x8000L,
5174     0x10000L,0x20000L,0x40000L,0x80000L,
5175     0x100000L,0x200000L,0x400000L,0x800000L,
5176     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5177     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5178     int idx;
5179     
5180     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5181     for(idx = 0; idx < 32; idx++)
5182         if(lit == pw[idx])
5183             return idx+1;
5184     return 0;
5185 }
5186
5187 /*-----------------------------------------------------------------*/
5188 /* continueIfTrue -                                                */
5189 /*-----------------------------------------------------------------*/
5190 static void continueIfTrue (iCode *ic)
5191 {
5192     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5193     if(IC_TRUE(ic))
5194         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5195     ic->generated = 1;
5196 }
5197
5198 /*-----------------------------------------------------------------*/
5199 /* jmpIfTrue -                                                     */
5200 /*-----------------------------------------------------------------*/
5201 static void jumpIfTrue (iCode *ic)
5202 {
5203     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5204     if(!IC_TRUE(ic))
5205         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5206     ic->generated = 1;
5207 }
5208
5209 /*-----------------------------------------------------------------*/
5210 /* jmpTrueOrFalse -                                                */
5211 /*-----------------------------------------------------------------*/
5212 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5213 {
5214     // ugly but optimized by peephole
5215     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5216     if(IC_TRUE(ic)){
5217         symbol *nlbl = newiTempLabel(NULL);
5218         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5219         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5220         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5221         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5222     }
5223     else{
5224         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5225         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5226     }
5227     ic->generated = 1;
5228 }
5229
5230 /*-----------------------------------------------------------------*/
5231 /* genAnd  - code for and                                          */
5232 /*-----------------------------------------------------------------*/
5233 static void genAnd (iCode *ic, iCode *ifx)
5234 {
5235   operand *left, *right, *result;
5236   int size, offset=0;  
5237   unsigned long lit = 0L;
5238   int bytelit = 0;
5239   resolvedIfx rIfx;
5240
5241
5242   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5243   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5244   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5245   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5246
5247   resolveIfx(&rIfx,ifx);
5248
5249   /* if left is a literal & right is not then exchange them */
5250   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5251       AOP_NEEDSACC(left)) {
5252     operand *tmp = right ;
5253     right = left;
5254     left = tmp;
5255   }
5256
5257   /* if result = right then exchange them */
5258   if(pic14_sameRegs(AOP(result),AOP(right))){
5259     operand *tmp = right ;
5260     right = left;
5261     left = tmp;
5262   }
5263
5264   /* if right is bit then exchange them */
5265   if (AOP_TYPE(right) == AOP_CRY &&
5266       AOP_TYPE(left) != AOP_CRY){
5267     operand *tmp = right ;
5268     right = left;
5269     left = tmp;
5270   }
5271   if(AOP_TYPE(right) == AOP_LIT)
5272     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5273
5274   size = AOP_SIZE(result);
5275
5276   DEBUGpic14_AopType(__LINE__,left,right,result);
5277
5278   // if(bit & yy)
5279   // result = bit & yy;
5280   if (AOP_TYPE(left) == AOP_CRY){
5281     // c = bit & literal;
5282     if(AOP_TYPE(right) == AOP_LIT){
5283       if(lit & 1) {
5284         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5285           // no change
5286           goto release;
5287         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5288       } else {
5289         // bit(result) = 0;
5290         if(size && (AOP_TYPE(result) == AOP_CRY)){
5291           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5292           goto release;
5293         }
5294         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5295           jumpIfTrue(ifx);
5296           goto release;
5297         }
5298         pic14_emitcode("clr","c");
5299       }
5300     } else {
5301       if (AOP_TYPE(right) == AOP_CRY){
5302         // c = bit & bit;
5303         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5304         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5305       } else {
5306         // c = bit & val;
5307         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5308         // c = lsb
5309         pic14_emitcode("rrc","a");
5310         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5311       }
5312     }
5313     // bit = c
5314     // val = c
5315     if(size)
5316       pic14_outBitC(result);
5317     // if(bit & ...)
5318     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5319       genIfxJump(ifx, "c");           
5320     goto release ;
5321   }
5322
5323   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5324   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5325   if((AOP_TYPE(right) == AOP_LIT) &&
5326      (AOP_TYPE(result) == AOP_CRY) &&
5327      (AOP_TYPE(left) != AOP_CRY)){
5328     int posbit = isLiteralBit(lit);
5329     /* left &  2^n */
5330     if(posbit){
5331       posbit--;
5332       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5333       // bit = left & 2^n
5334       if(size)
5335         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5336       // if(left &  2^n)
5337       else{
5338         if(ifx){
5339 /*
5340           if(IC_TRUE(ifx)) {
5341             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5342             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
5343           } else {
5344             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5345             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
5346           }
5347 */
5348           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5349                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5350           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5351           
5352           ifx->generated = 1;
5353         }
5354         goto release;
5355       }
5356     } else {
5357       symbol *tlbl = newiTempLabel(NULL);
5358       int sizel = AOP_SIZE(left);
5359       if(size)
5360         pic14_emitcode("setb","c");
5361       while(sizel--){
5362         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5363           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5364           // byte ==  2^n ?
5365           if((posbit = isLiteralBit(bytelit)) != 0)
5366             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5367           else{
5368             if(bytelit != 0x0FFL)
5369               pic14_emitcode("anl","a,%s",
5370                              aopGet(AOP(right),offset,FALSE,TRUE));
5371             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5372           }
5373         }
5374         offset++;
5375       }
5376       // bit = left & literal
5377       if(size){
5378         pic14_emitcode("clr","c");
5379         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5380       }
5381       // if(left & literal)
5382       else{
5383         if(ifx)
5384           jmpTrueOrFalse(ifx, tlbl);
5385         goto release ;
5386       }
5387     }
5388     pic14_outBitC(result);
5389     goto release ;
5390   }
5391
5392   /* if left is same as result */
5393   if(pic14_sameRegs(AOP(result),AOP(left))){
5394     int know_W = -1;
5395     for(;size--; offset++,lit>>=8) {
5396       if(AOP_TYPE(right) == AOP_LIT){
5397         switch(lit & 0xff) {
5398         case 0x00:
5399           /*  and'ing with 0 has clears the result */
5400           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5401           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5402           break;
5403         case 0xff:
5404           /* and'ing with 0xff is a nop when the result and left are the same */
5405           break;
5406
5407         default:
5408           {
5409             int p = my_powof2( (~lit) & 0xff );
5410             if(p>=0) {
5411               /* only one bit is set in the literal, so use a bcf instruction */
5412               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5413               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5414
5415             } else {
5416               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5417               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5418               if(know_W != (lit&0xff))
5419                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5420               know_W = lit &0xff;
5421               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5422             }
5423           }    
5424         }
5425       } else {
5426         if (AOP_TYPE(left) == AOP_ACC) {
5427           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5428         } else {                    
5429           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5430           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5431
5432         }
5433       }
5434     }
5435
5436   } else {
5437     // left & result in different registers
5438     if(AOP_TYPE(result) == AOP_CRY){
5439       // result = bit
5440       // if(size), result in bit
5441       // if(!size && ifx), conditional oper: if(left & right)
5442       symbol *tlbl = newiTempLabel(NULL);
5443       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5444       if(size)
5445         pic14_emitcode("setb","c");
5446       while(sizer--){
5447         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5448         pic14_emitcode("anl","a,%s",
5449                        aopGet(AOP(left),offset,FALSE,FALSE));
5450         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5451         offset++;
5452       }
5453       if(size){
5454         CLRC;
5455         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5456         pic14_outBitC(result);
5457       } else if(ifx)
5458         jmpTrueOrFalse(ifx, tlbl);
5459     } else {
5460       for(;(size--);offset++) {
5461         // normal case
5462         // result = left & right
5463         if(AOP_TYPE(right) == AOP_LIT){
5464           int t = (lit >> (offset*8)) & 0x0FFL;
5465           switch(t) { 
5466           case 0x00:
5467             pic14_emitcode("clrf","%s",
5468                            aopGet(AOP(result),offset,FALSE,FALSE));
5469             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5470             break;
5471           case 0xff:
5472             if(AOP_TYPE(left) == AOP_ACC) {
5473               emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5474             } else {
5475               pic14_emitcode("movf","%s,w",
5476                              aopGet(AOP(left),offset,FALSE,FALSE));
5477               pic14_emitcode("movwf","%s",
5478                              aopGet(AOP(result),offset,FALSE,FALSE));
5479               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5480               emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5481             }
5482             break;
5483           default:
5484             if(AOP_TYPE(left) == AOP_ACC) {
5485               emitpcode(POC_ANDLW, popGetLit(t));
5486               emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5487             } else {
5488               pic14_emitcode("movlw","0x%x",t);
5489               pic14_emitcode("andwf","%s,w",
5490                              aopGet(AOP(left),offset,FALSE,FALSE));
5491               pic14_emitcode("movwf","%s",
5492                              aopGet(AOP(result),offset,FALSE,FALSE));
5493               
5494               emitpcode(POC_MOVLW, popGetLit(t));
5495               emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5496               emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5497             }
5498           }
5499           continue;
5500         }
5501
5502         if (AOP_TYPE(left) == AOP_ACC) {
5503           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5504           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5505         } else {
5506           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5507           pic14_emitcode("andwf","%s,w",
5508                          aopGet(AOP(left),offset,FALSE,FALSE));
5509           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5510           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5511         }
5512         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5513         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5514       }
5515     }
5516   }
5517
5518   release :
5519     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5520   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5521   freeAsmop(result,NULL,ic,TRUE);     
5522 }
5523
5524 /*-----------------------------------------------------------------*/
5525 /* genOr  - code for or                                            */
5526 /*-----------------------------------------------------------------*/
5527 static void genOr (iCode *ic, iCode *ifx)
5528 {
5529     operand *left, *right, *result;
5530     int size, offset=0;
5531     unsigned long lit = 0L;
5532
5533     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5534
5535     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5536     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5537     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5538
5539     DEBUGpic14_AopType(__LINE__,left,right,result);
5540
5541     /* if left is a literal & right is not then exchange them */
5542     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5543         AOP_NEEDSACC(left)) {
5544         operand *tmp = right ;
5545         right = left;
5546         left = tmp;
5547     }
5548
5549     /* if result = right then exchange them */
5550     if(pic14_sameRegs(AOP(result),AOP(right))){
5551         operand *tmp = right ;
5552         right = left;
5553         left = tmp;
5554     }
5555
5556     /* if right is bit then exchange them */
5557     if (AOP_TYPE(right) == AOP_CRY &&
5558         AOP_TYPE(left) != AOP_CRY){
5559         operand *tmp = right ;
5560         right = left;
5561         left = tmp;
5562     }
5563
5564     DEBUGpic14_AopType(__LINE__,left,right,result);
5565
5566     if(AOP_TYPE(right) == AOP_LIT)
5567         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5568
5569     size = AOP_SIZE(result);
5570
5571     // if(bit | yy)
5572     // xx = bit | yy;
5573     if (AOP_TYPE(left) == AOP_CRY){
5574         if(AOP_TYPE(right) == AOP_LIT){
5575             // c = bit & literal;
5576             if(lit){
5577                 // lit != 0 => result = 1
5578                 if(AOP_TYPE(result) == AOP_CRY){
5579                   if(size)
5580                     emitpcode(POC_BSF, popGet(AOP(result),0));
5581                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5582                   //     AOP(result)->aopu.aop_dir,
5583                   //     AOP(result)->aopu.aop_dir);
5584                     else if(ifx)
5585                         continueIfTrue(ifx);
5586                     goto release;
5587                 }
5588             } else {
5589                 // lit == 0 => result = left
5590                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5591                     goto release;
5592                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5593             }
5594         } else {
5595             if (AOP_TYPE(right) == AOP_CRY){
5596               if(pic14_sameRegs(AOP(result),AOP(left))){
5597                 // c = bit | bit;
5598                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5599                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5600                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5601
5602                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5603                          AOP(result)->aopu.aop_dir,
5604                          AOP(result)->aopu.aop_dir);
5605                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5606                          AOP(right)->aopu.aop_dir,
5607                          AOP(right)->aopu.aop_dir);
5608                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5609                          AOP(result)->aopu.aop_dir,
5610                          AOP(result)->aopu.aop_dir);
5611               } else {
5612                 if( AOP_TYPE(result) == AOP_ACC) {
5613                   emitpcode(POC_MOVLW, popGetLit(0));
5614                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5615                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5616                   emitpcode(POC_MOVLW, popGetLit(1));
5617
5618                 } else {
5619
5620                   emitpcode(POC_BCF,   popGet(AOP(result),0));
5621                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5622                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5623                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5624
5625                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5626                                  AOP(result)->aopu.aop_dir,
5627                                  AOP(result)->aopu.aop_dir);
5628                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5629                                  AOP(right)->aopu.aop_dir,
5630                                  AOP(right)->aopu.aop_dir);
5631                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5632                                  AOP(left)->aopu.aop_dir,
5633                                  AOP(left)->aopu.aop_dir);
5634                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5635                                  AOP(result)->aopu.aop_dir,
5636                                  AOP(result)->aopu.aop_dir);
5637                 }
5638               }
5639             } else {
5640                 // c = bit | val;
5641                 symbol *tlbl = newiTempLabel(NULL);
5642                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5643
5644
5645                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5646                 if( AOP_TYPE(right) == AOP_ACC) {
5647                   emitpcode(POC_IORLW, popGetLit(0));
5648                   emitSKPNZ;
5649                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5650                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5651                 }
5652
5653
5654
5655                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5656                     pic14_emitcode(";XXX setb","c");
5657                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5658                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5659                 pic14_toBoolean(right);
5660                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5661                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5662                     jmpTrueOrFalse(ifx, tlbl);
5663                     goto release;
5664                 } else {
5665                     CLRC;
5666                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5667                 }
5668             }
5669         }
5670         // bit = c
5671         // val = c
5672         if(size)
5673             pic14_outBitC(result);
5674         // if(bit | ...)
5675         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5676             genIfxJump(ifx, "c");           
5677         goto release ;
5678     }
5679
5680     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5681     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5682     if((AOP_TYPE(right) == AOP_LIT) &&
5683        (AOP_TYPE(result) == AOP_CRY) &&
5684        (AOP_TYPE(left) != AOP_CRY)){
5685         if(lit){
5686           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5687             // result = 1
5688             if(size)
5689                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5690             else 
5691                 continueIfTrue(ifx);
5692             goto release;
5693         } else {
5694           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5695             // lit = 0, result = boolean(left)
5696             if(size)
5697                 pic14_emitcode(";XXX setb","c");
5698             pic14_toBoolean(right);
5699             if(size){
5700                 symbol *tlbl = newiTempLabel(NULL);
5701                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5702                 CLRC;
5703                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5704             } else {
5705                 genIfxJump (ifx,"a");
5706                 goto release;
5707             }
5708         }
5709         pic14_outBitC(result);
5710         goto release ;
5711     }
5712
5713     /* if left is same as result */
5714     if(pic14_sameRegs(AOP(result),AOP(left))){
5715       int know_W = -1;
5716       for(;size--; offset++,lit>>=8) {
5717         if(AOP_TYPE(right) == AOP_LIT){
5718           if((lit & 0xff) == 0)
5719             /*  or'ing with 0 has no effect */
5720             continue;
5721           else {
5722             int p = my_powof2(lit & 0xff);
5723             if(p>=0) {
5724               /* only one bit is set in the literal, so use a bsf instruction */
5725               emitpcode(POC_BSF,
5726                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5727             } else {
5728               if(know_W != (lit & 0xff))
5729                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5730               know_W = lit & 0xff;
5731               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5732             }
5733                     
5734           }
5735         } else {
5736           if (AOP_TYPE(left) == AOP_ACC) {
5737             emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5738             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5739           } else {                  
5740             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5741             emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5742
5743             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5744             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5745
5746           }
5747         }
5748       }
5749     } else {
5750         // left & result in different registers
5751         if(AOP_TYPE(result) == AOP_CRY){
5752             // result = bit
5753             // if(size), result in bit
5754             // if(!size && ifx), conditional oper: if(left | right)
5755             symbol *tlbl = newiTempLabel(NULL);
5756             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5757             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5758
5759
5760             if(size)
5761                 pic14_emitcode(";XXX setb","c");
5762             while(sizer--){
5763                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5764                 pic14_emitcode(";XXX orl","a,%s",
5765                          aopGet(AOP(left),offset,FALSE,FALSE));
5766                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5767                 offset++;
5768             }
5769             if(size){
5770                 CLRC;
5771                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5772                 pic14_outBitC(result);
5773             } else if(ifx)
5774                 jmpTrueOrFalse(ifx, tlbl);
5775         } else for(;(size--);offset++){
5776           // normal case
5777           // result = left & right
5778           if(AOP_TYPE(right) == AOP_LIT){
5779             int t = (lit >> (offset*8)) & 0x0FFL;
5780             switch(t) { 
5781             case 0x00:
5782               emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5783               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5784
5785               pic14_emitcode("movf","%s,w",
5786                        aopGet(AOP(left),offset,FALSE,FALSE));
5787               pic14_emitcode("movwf","%s",
5788                        aopGet(AOP(result),offset,FALSE,FALSE));
5789               break;
5790             default:
5791               emitpcode(POC_MOVLW,  popGetLit(t));
5792               emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5793               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5794
5795               pic14_emitcode("movlw","0x%x",t);
5796               pic14_emitcode("iorwf","%s,w",
5797                        aopGet(AOP(left),offset,FALSE,FALSE));
5798               pic14_emitcode("movwf","%s",
5799                        aopGet(AOP(result),offset,FALSE,FALSE));
5800               
5801             }
5802             continue;
5803           }
5804
5805           // faster than result <- left, anl result,right
5806           // and better if result is SFR
5807           if (AOP_TYPE(left) == AOP_ACC) {
5808             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5809             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5810           } else {
5811             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5812             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5813
5814             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5815             pic14_emitcode("iorwf","%s,w",
5816                      aopGet(AOP(left),offset,FALSE,FALSE));
5817           }
5818           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5819           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5820         }
5821     }
5822
5823 release :
5824     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5825     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5826     freeAsmop(result,NULL,ic,TRUE);     
5827 }
5828
5829 /*-----------------------------------------------------------------*/
5830 /* genXor - code for xclusive or                                   */
5831 /*-----------------------------------------------------------------*/
5832 static void genXor (iCode *ic, iCode *ifx)
5833 {
5834   operand *left, *right, *result;
5835   int size, offset=0;
5836   unsigned long lit = 0L;
5837
5838   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5839
5840   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5841   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5842   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5843
5844   /* if left is a literal & right is not ||
5845      if left needs acc & right does not */
5846   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5847       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5848     operand *tmp = right ;
5849     right = left;
5850     left = tmp;
5851   }
5852
5853   /* if result = right then exchange them */
5854   if(pic14_sameRegs(AOP(result),AOP(right))){
5855     operand *tmp = right ;
5856     right = left;
5857     left = tmp;
5858   }
5859
5860   /* if right is bit then exchange them */
5861   if (AOP_TYPE(right) == AOP_CRY &&
5862       AOP_TYPE(left) != AOP_CRY){
5863     operand *tmp = right ;
5864     right = left;
5865     left = tmp;
5866   }
5867   if(AOP_TYPE(right) == AOP_LIT)
5868     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5869
5870   size = AOP_SIZE(result);
5871
5872   // if(bit ^ yy)
5873   // xx = bit ^ yy;
5874   if (AOP_TYPE(left) == AOP_CRY){
5875     if(AOP_TYPE(right) == AOP_LIT){
5876       // c = bit & literal;
5877       if(lit>>1){
5878         // lit>>1  != 0 => result = 1
5879         if(AOP_TYPE(result) == AOP_CRY){
5880           if(size)
5881             {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5882             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5883           else if(ifx)
5884             continueIfTrue(ifx);
5885           goto release;
5886         }
5887         pic14_emitcode("setb","c");
5888       } else{
5889         // lit == (0 or 1)
5890         if(lit == 0){
5891           // lit == 0, result = left
5892           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5893             goto release;
5894           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5895         } else{
5896           // lit == 1, result = not(left)
5897           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5898             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5899             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5900             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5901             goto release;
5902           } else {
5903             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5904             pic14_emitcode("cpl","c");
5905           }
5906         }
5907       }
5908
5909     } else {
5910       // right != literal
5911       symbol *tlbl = newiTempLabel(NULL);
5912       if (AOP_TYPE(right) == AOP_CRY){
5913         // c = bit ^ bit;
5914         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5915       }
5916       else{
5917         int sizer = AOP_SIZE(right);
5918         // c = bit ^ val
5919         // if val>>1 != 0, result = 1
5920         pic14_emitcode("setb","c");
5921         while(sizer){
5922           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5923           if(sizer == 1)
5924             // test the msb of the lsb
5925             pic14_emitcode("anl","a,#0xfe");
5926           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5927           sizer--;
5928         }
5929         // val = (0,1)
5930         pic14_emitcode("rrc","a");
5931       }
5932       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5933       pic14_emitcode("cpl","c");
5934       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5935     }
5936     // bit = c
5937     // val = c
5938     if(size)
5939       pic14_outBitC(result);
5940     // if(bit | ...)
5941     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5942       genIfxJump(ifx, "c");           
5943     goto release ;
5944   }
5945
5946   if(pic14_sameRegs(AOP(result),AOP(left))){
5947     /* if left is same as result */
5948     for(;size--; offset++) {
5949       if(AOP_TYPE(right) == AOP_LIT){
5950         int t  = (lit >> (offset*8)) & 0x0FFL;
5951         if(t == 0x00L)
5952           continue;
5953         else
5954           if (IS_AOP_PREG(left)) {
5955             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5956             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5957             aopPut(AOP(result),"a",offset);
5958           } else {
5959             emitpcode(POC_MOVLW, popGetLit(t));
5960             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5961             pic14_emitcode("xrl","%s,%s",
5962                            aopGet(AOP(left),offset,FALSE,TRUE),
5963                            aopGet(AOP(right),offset,FALSE,FALSE));
5964           }
5965       } else {
5966         if (AOP_TYPE(left) == AOP_ACC)
5967           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5968         else {
5969           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5970           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5971 /*
5972           if (IS_AOP_PREG(left)) {
5973             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5974             aopPut(AOP(result),"a",offset);
5975           } else
5976             pic14_emitcode("xrl","%s,a",
5977                            aopGet(AOP(left),offset,FALSE,TRUE));
5978 */
5979         }
5980       }
5981     }
5982   } else {
5983     // left & result in different registers
5984     if(AOP_TYPE(result) == AOP_CRY){
5985       // result = bit
5986       // if(size), result in bit
5987       // if(!size && ifx), conditional oper: if(left ^ right)
5988       symbol *tlbl = newiTempLabel(NULL);
5989       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5990       if(size)
5991         pic14_emitcode("setb","c");
5992       while(sizer--){
5993         if((AOP_TYPE(right) == AOP_LIT) &&
5994            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5995           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5996         } else {
5997           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5998           pic14_emitcode("xrl","a,%s",
5999                          aopGet(AOP(left),offset,FALSE,FALSE));
6000         }
6001         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6002         offset++;
6003       }
6004       if(size){
6005         CLRC;
6006         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6007         pic14_outBitC(result);
6008       } else if(ifx)
6009         jmpTrueOrFalse(ifx, tlbl);
6010     } else for(;(size--);offset++){
6011       // normal case
6012       // result = left & right
6013       if(AOP_TYPE(right) == AOP_LIT){
6014         int t = (lit >> (offset*8)) & 0x0FFL;
6015         switch(t) { 
6016         case 0x00:
6017           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6018           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6019           pic14_emitcode("movf","%s,w",
6020                          aopGet(AOP(left),offset,FALSE,FALSE));
6021           pic14_emitcode("movwf","%s",
6022                          aopGet(AOP(result),offset,FALSE,FALSE));
6023           break;
6024         case 0xff:
6025           emitpcode(POC_COMFW,popGet(AOP(left),offset));
6026           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6027           pic14_emitcode("comf","%s,w",
6028                          aopGet(AOP(left),offset,FALSE,FALSE));
6029           pic14_emitcode("movwf","%s",
6030                          aopGet(AOP(result),offset,FALSE,FALSE));
6031           break;
6032         default:
6033           emitpcode(POC_MOVLW, popGetLit(t));
6034           emitpcode(POC_XORFW,popGet(AOP(left),offset));
6035           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6036           pic14_emitcode("movlw","0x%x",t);
6037           pic14_emitcode("xorwf","%s,w",
6038                          aopGet(AOP(left),offset,FALSE,FALSE));
6039           pic14_emitcode("movwf","%s",
6040                          aopGet(AOP(result),offset,FALSE,FALSE));
6041
6042         }
6043         continue;
6044       }
6045
6046       // faster than result <- left, anl result,right
6047       // and better if result is SFR
6048       if (AOP_TYPE(left) == AOP_ACC) {
6049         emitpcode(POC_XORFW,popGet(AOP(right),offset));
6050         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6051       } else {
6052         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6053         emitpcode(POC_XORFW,popGet(AOP(left),offset));
6054         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6055         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
6056       }
6057       if ( AOP_TYPE(result) != AOP_ACC){
6058         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6059         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
6060       }
6061     }
6062   }
6063
6064   release :
6065     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6066   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6067   freeAsmop(result,NULL,ic,TRUE);     
6068 }
6069
6070 /*-----------------------------------------------------------------*/
6071 /* genInline - write the inline code out                           */
6072 /*-----------------------------------------------------------------*/
6073 static void genInline (iCode *ic)
6074 {
6075     char *buffer, *bp, *bp1;
6076     
6077     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6078
6079     _G.inLine += (!options.asmpeep);
6080
6081     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6082     strcpy(buffer,IC_INLINE(ic));
6083
6084     /* emit each line as a code */
6085     while (*bp) {
6086         if (*bp == '\n') {
6087             *bp++ = '\0';
6088
6089             if(*bp1)
6090               addpCode2pBlock(pb,AssembleLine(bp1));
6091             bp1 = bp;
6092         } else {
6093             if (*bp == ':') {
6094                 bp++;
6095                 *bp = '\0';
6096                 bp++;
6097                 pic14_emitcode(bp1,"");
6098                 bp1 = bp;
6099             } else
6100                 bp++;
6101         }
6102     }
6103     if ((bp1 != bp) && *bp1)
6104       addpCode2pBlock(pb,AssembleLine(bp1));
6105
6106     Safe_free(buffer);
6107
6108     _G.inLine -= (!options.asmpeep);
6109 }
6110
6111 /*-----------------------------------------------------------------*/
6112 /* genRRC - rotate right with carry                                */
6113 /*-----------------------------------------------------------------*/
6114 static void genRRC (iCode *ic)
6115 {
6116   operand *left , *result ;
6117   int size, offset = 0, same;
6118
6119   /* rotate right with carry */
6120   left = IC_LEFT(ic);
6121   result=IC_RESULT(ic);
6122   aopOp (left,ic,FALSE);
6123   aopOp (result,ic,FALSE);
6124
6125   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6126
6127   same = pic14_sameRegs(AOP(result),AOP(left));
6128
6129   size = AOP_SIZE(result);    
6130
6131   /* get the lsb and put it into the carry */
6132   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6133
6134   offset = 0 ;
6135
6136   while(size--) {
6137
6138     if(same) {
6139       emitpcode(POC_RRF, popGet(AOP(left),offset));
6140     } else {
6141       emitpcode(POC_RRFW, popGet(AOP(left),offset));
6142       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6143     }
6144
6145     offset++;
6146   }
6147
6148   freeAsmop(left,NULL,ic,TRUE);
6149   freeAsmop(result,NULL,ic,TRUE);
6150 }
6151
6152 /*-----------------------------------------------------------------*/
6153 /* genRLC - generate code for rotate left with carry               */
6154 /*-----------------------------------------------------------------*/
6155 static void genRLC (iCode *ic)
6156 {    
6157   operand *left , *result ;
6158   int size, offset = 0;
6159   int same;
6160
6161   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6162   /* rotate right with carry */
6163   left = IC_LEFT(ic);
6164   result=IC_RESULT(ic);
6165   aopOp (left,ic,FALSE);
6166   aopOp (result,ic,FALSE);
6167
6168   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6169
6170   same = pic14_sameRegs(AOP(result),AOP(left));
6171
6172   /* move it to the result */
6173   size = AOP_SIZE(result);    
6174
6175   /* get the msb and put it into the carry */
6176   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6177
6178   offset = 0 ;
6179
6180   while(size--) {
6181
6182     if(same) {
6183       emitpcode(POC_RLF, popGet(AOP(left),offset));
6184     } else {
6185       emitpcode(POC_RLFW, popGet(AOP(left),offset));
6186       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6187     }
6188
6189     offset++;
6190   }
6191
6192
6193   freeAsmop(left,NULL,ic,TRUE);
6194   freeAsmop(result,NULL,ic,TRUE);
6195 }
6196
6197 /*-----------------------------------------------------------------*/
6198 /* genGetHbit - generates code get highest order bit               */
6199 /*-----------------------------------------------------------------*/
6200 static void genGetHbit (iCode *ic)
6201 {
6202     operand *left, *result;
6203     left = IC_LEFT(ic);
6204     result=IC_RESULT(ic);
6205     aopOp (left,ic,FALSE);
6206     aopOp (result,ic,FALSE);
6207
6208     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6209     /* get the highest order byte into a */
6210     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6211     if(AOP_TYPE(result) == AOP_CRY){
6212         pic14_emitcode("rlc","a");
6213         pic14_outBitC(result);
6214     }
6215     else{
6216         pic14_emitcode("rl","a");
6217         pic14_emitcode("anl","a,#0x01");
6218         pic14_outAcc(result);
6219     }
6220
6221
6222     freeAsmop(left,NULL,ic,TRUE);
6223     freeAsmop(result,NULL,ic,TRUE);
6224 }
6225
6226 /*-----------------------------------------------------------------*/
6227 /* AccRol - rotate left accumulator by known count                 */
6228 /*-----------------------------------------------------------------*/
6229 static void AccRol (int shCount)
6230 {
6231     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6232     shCount &= 0x0007;              // shCount : 0..7
6233     switch(shCount){
6234         case 0 :
6235             break;
6236         case 1 :
6237             pic14_emitcode("rl","a");
6238             break;
6239         case 2 :
6240             pic14_emitcode("rl","a");
6241             pic14_emitcode("rl","a");
6242             break;
6243         case 3 :
6244             pic14_emitcode("swap","a");
6245             pic14_emitcode("rr","a");
6246             break;
6247         case 4 :
6248             pic14_emitcode("swap","a");
6249             break;
6250         case 5 :
6251             pic14_emitcode("swap","a");
6252             pic14_emitcode("rl","a");
6253             break;
6254         case 6 :
6255             pic14_emitcode("rr","a");
6256             pic14_emitcode("rr","a");
6257             break;
6258         case 7 :
6259             pic14_emitcode("rr","a");
6260             break;
6261     }
6262 }
6263
6264 /*-----------------------------------------------------------------*/
6265 /* AccLsh - left shift accumulator by known count                  */
6266 /*-----------------------------------------------------------------*/
6267 static void AccLsh (int shCount)
6268 {
6269     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6270     if(shCount != 0){
6271         if(shCount == 1)
6272             pic14_emitcode("add","a,acc");
6273         else 
6274             if(shCount == 2) {
6275             pic14_emitcode("add","a,acc");
6276             pic14_emitcode("add","a,acc");
6277         } else {
6278             /* rotate left accumulator */
6279             AccRol(shCount);
6280             /* and kill the lower order bits */
6281             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6282         }
6283     }
6284 }
6285
6286 /*-----------------------------------------------------------------*/
6287 /* AccRsh - right shift accumulator by known count                 */
6288 /*-----------------------------------------------------------------*/
6289 static void AccRsh (int shCount)
6290 {
6291     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6292     if(shCount != 0){
6293         if(shCount == 1){
6294             CLRC;
6295             pic14_emitcode("rrc","a");
6296         } else {
6297             /* rotate right accumulator */
6298             AccRol(8 - shCount);
6299             /* and kill the higher order bits */
6300             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6301         }
6302     }
6303 }
6304
6305 #if 0
6306 /*-----------------------------------------------------------------*/
6307 /* AccSRsh - signed right shift accumulator by known count                 */
6308 /*-----------------------------------------------------------------*/
6309 static void AccSRsh (int shCount)
6310 {
6311     symbol *tlbl ;
6312     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6313     if(shCount != 0){
6314         if(shCount == 1){
6315             pic14_emitcode("mov","c,acc.7");
6316             pic14_emitcode("rrc","a");
6317         } else if(shCount == 2){
6318             pic14_emitcode("mov","c,acc.7");
6319             pic14_emitcode("rrc","a");
6320             pic14_emitcode("mov","c,acc.7");
6321             pic14_emitcode("rrc","a");
6322         } else {
6323             tlbl = newiTempLabel(NULL);
6324             /* rotate right accumulator */
6325             AccRol(8 - shCount);
6326             /* and kill the higher order bits */
6327             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6328             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6329             pic14_emitcode("orl","a,#0x%02x",
6330                      (unsigned char)~SRMask[shCount]);
6331             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6332         }
6333     }
6334 }
6335 #endif
6336 /*-----------------------------------------------------------------*/
6337 /* shiftR1Left2Result - shift right one byte from left to result   */
6338 /*-----------------------------------------------------------------*/
6339 static void shiftR1Left2ResultSigned (operand *left, int offl,
6340                                 operand *result, int offr,
6341                                 int shCount)
6342 {
6343   int same;
6344
6345   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6346
6347   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6348
6349   switch(shCount) {
6350   case 1:
6351     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6352     if(same) 
6353       emitpcode(POC_RRF, popGet(AOP(result),offr));
6354     else {
6355       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6356       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6357     }
6358
6359     break;
6360   case 2:
6361
6362     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6363     if(same) 
6364       emitpcode(POC_RRF, popGet(AOP(result),offr));
6365     else {
6366       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6367       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6368     }
6369     emitpcode(POC_RLFW, popGet(AOP(result),offr));
6370     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6371
6372     break;
6373
6374   case 3:
6375     if(same)
6376       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6377     else {
6378       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6379       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6380     }
6381
6382     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6383     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6384     emitpcode(POC_ANDLW, popGetLit(0x1f));
6385
6386     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6387     emitpcode(POC_IORLW, popGetLit(0xe0));
6388
6389     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6390     break;
6391
6392   case 4:
6393     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6394     emitpcode(POC_ANDLW,  popGetLit(0x0f));
6395     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6396     emitpcode(POC_IORLW,  popGetLit(0xf0));
6397     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6398     break;
6399   case 5:
6400     if(same) {
6401       emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6402     } else {
6403       emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6404       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6405     }
6406     emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6407     emitpcode(POC_ANDLW,  popGetLit(0x07));
6408     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6409     emitpcode(POC_IORLW,  popGetLit(0xf8));
6410     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6411     break;
6412
6413   case 6:
6414     if(same) {
6415       emitpcode(POC_MOVLW, popGetLit(0x00));
6416       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6417       emitpcode(POC_MOVLW, popGetLit(0xfe));
6418       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6419       emitpcode(POC_IORLW, popGetLit(0x01));
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       emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6426       emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6427     }
6428     break;
6429
6430   case 7:
6431     if(same) {
6432       emitpcode(POC_MOVLW, popGetLit(0x00));
6433       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6434       emitpcode(POC_MOVLW, popGetLit(0xff));
6435       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6436     } else {
6437       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6438       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6439       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6440     }
6441
6442   default:
6443     break;
6444   }
6445 }
6446
6447 /*-----------------------------------------------------------------*/
6448 /* shiftR1Left2Result - shift right one byte from left to result   */
6449 /*-----------------------------------------------------------------*/
6450 static void shiftR1Left2Result (operand *left, int offl,
6451                                 operand *result, int offr,
6452                                 int shCount, int sign)
6453 {
6454   int same;
6455
6456   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6457
6458   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6459
6460   /* Copy the msb into the carry if signed. */
6461   if(sign) {
6462     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6463     return;
6464   }
6465
6466
6467
6468   switch(shCount) {
6469   case 1:
6470     emitCLRC;
6471     if(same) 
6472       emitpcode(POC_RRF, popGet(AOP(result),offr));
6473     else {
6474       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6475       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6476     }
6477     break;
6478   case 2:
6479     emitCLRC;
6480     if(same) {
6481       emitpcode(POC_RRF, popGet(AOP(result),offr));
6482     } else {
6483       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6484       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6485     }
6486     emitCLRC;
6487     emitpcode(POC_RRF, popGet(AOP(result),offr));
6488
6489     break;
6490   case 3:
6491     if(same)
6492       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6493     else {
6494       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6495       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6496     }
6497
6498     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6499     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6500     emitpcode(POC_ANDLW, popGetLit(0x1f));
6501     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6502     break;
6503       
6504   case 4:
6505     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6506     emitpcode(POC_ANDLW, popGetLit(0x0f));
6507     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6508     break;
6509
6510   case 5:
6511     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6512     emitpcode(POC_ANDLW, popGetLit(0x0f));
6513     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6514     emitCLRC;
6515     emitpcode(POC_RRF, popGet(AOP(result),offr));
6516
6517     break;
6518   case 6:
6519
6520     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6521     emitpcode(POC_ANDLW, popGetLit(0x80));
6522     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6523     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6524     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6525     break;
6526
6527   case 7:
6528
6529     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6530     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6531     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6532
6533     break;
6534
6535   default:
6536     break;
6537   }
6538 }
6539
6540 /*-----------------------------------------------------------------*/
6541 /* shiftL1Left2Result - shift left one byte from left to result    */
6542 /*-----------------------------------------------------------------*/
6543 static void shiftL1Left2Result (operand *left, int offl,
6544                                 operand *result, int offr, int shCount)
6545 {
6546   int same;
6547
6548   //    char *l;
6549   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6550
6551   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6552   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6553     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6554     //    MOVA(l);
6555     /* shift left accumulator */
6556     //AccLsh(shCount); // don't comment out just yet...
6557   //    aopPut(AOP(result),"a",offr);
6558
6559   switch(shCount) {
6560   case 1:
6561     /* Shift left 1 bit position */
6562     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6563     if(same) {
6564       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6565     } else {
6566       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6567       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6568     }
6569     break;
6570   case 2:
6571     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6572     emitpcode(POC_ANDLW,popGetLit(0x7e));
6573     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6574     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6575     break;
6576   case 3:
6577     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6578     emitpcode(POC_ANDLW,popGetLit(0x3e));
6579     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6580     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6581     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6582     break;
6583   case 4:
6584     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6585     emitpcode(POC_ANDLW, popGetLit(0xf0));
6586     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6587     break;
6588   case 5:
6589     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6590     emitpcode(POC_ANDLW, popGetLit(0xf0));
6591     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6592     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6593     break;
6594   case 6:
6595     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6596     emitpcode(POC_ANDLW, popGetLit(0x30));
6597     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6598     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6599     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6600     break;
6601   case 7:
6602     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6603     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6604     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6605     break;
6606
6607   default:
6608     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6609   }
6610
6611 }
6612
6613 /*-----------------------------------------------------------------*/
6614 /* movLeft2Result - move byte from left to result                  */
6615 /*-----------------------------------------------------------------*/
6616 static void movLeft2Result (operand *left, int offl,
6617                             operand *result, int offr)
6618 {
6619   char *l;
6620   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6621   if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6622     l = aopGet(AOP(left),offl,FALSE,FALSE);
6623
6624     if (*l == '@' && (IS_AOP_PREG(result))) {
6625       pic14_emitcode("mov","a,%s",l);
6626       aopPut(AOP(result),"a",offr);
6627     } else {
6628       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6629       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6630     }
6631   }
6632 }
6633
6634 /*-----------------------------------------------------------------*/
6635 /* shiftL2Left2Result - shift left two bytes from left to result   */
6636 /*-----------------------------------------------------------------*/
6637 static void shiftL2Left2Result (operand *left, int offl,
6638                                 operand *result, int offr, int shCount)
6639 {
6640
6641
6642   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6643
6644   if(pic14_sameRegs(AOP(result), AOP(left))) {
6645     switch(shCount) {
6646     case 0:
6647       break;
6648     case 1:
6649     case 2:
6650     case 3:
6651
6652       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6653       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6654       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6655
6656       while(--shCount) {
6657         emitCLRC;
6658         emitpcode(POC_RLF, popGet(AOP(result),offr));
6659         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6660       }
6661
6662       break;
6663     case 4:
6664     case 5:
6665       emitpcode(POC_MOVLW, popGetLit(0x0f));
6666       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6667       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6668       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6669       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6670       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6671       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6672       if(shCount >=5) {
6673         emitpcode(POC_RLF, popGet(AOP(result),offr));
6674         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6675       }
6676       break;
6677     case 6:
6678       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6679       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6680       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6681       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6682       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6683       emitpcode(POC_ANDLW,popGetLit(0xc0));
6684       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6685       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6686       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6687       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6688       break;
6689     case 7:
6690       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6691       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6692       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6693       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6694       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6695     }
6696
6697   } else {
6698     switch(shCount) {
6699     case 0:
6700       break;
6701     case 1:
6702     case 2:
6703     case 3:
6704       /* note, use a mov/add for the shift since the mov has a
6705          chance of getting optimized out */
6706       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6707       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6708       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6709       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6710       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6711
6712       while(--shCount) {
6713         emitCLRC;
6714         emitpcode(POC_RLF, popGet(AOP(result),offr));
6715         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6716       }
6717       break;
6718
6719     case 4:
6720     case 5:
6721       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6722       emitpcode(POC_ANDLW, popGetLit(0xF0));
6723       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6724       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6725       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6726       emitpcode(POC_ANDLW, popGetLit(0xF0));
6727       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6728       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6729
6730
6731       if(shCount == 5) {
6732         emitpcode(POC_RLF, popGet(AOP(result),offr));
6733         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6734       }
6735       break;
6736     case 6:
6737       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6738       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6739       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6740       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6741
6742       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6743       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6744       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6745       emitpcode(POC_ANDLW,popGetLit(0xc0));
6746       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6747       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6748       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6749       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6750       break;
6751     case 7:
6752       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6753       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6754       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6755       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6756       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6757     }
6758   }
6759
6760 }
6761 /*-----------------------------------------------------------------*/
6762 /* shiftR2Left2Result - shift right two bytes from left to result  */
6763 /*-----------------------------------------------------------------*/
6764 static void shiftR2Left2Result (operand *left, int offl,
6765                                 operand *result, int offr,
6766                                 int shCount, int sign)
6767 {
6768   int same=0;
6769
6770   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6771   same = pic14_sameRegs(AOP(result), AOP(left));
6772
6773   if(same && ((offl + MSB16) == offr)){
6774     same=1;
6775     /* don't crash result[offr] */
6776     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6777     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6778   }
6779 /* else {
6780     movLeft2Result(left,offl, result, offr);
6781     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6782   }
6783 */
6784   /* a:x >> shCount (x = lsb(result))*/
6785 /*
6786   if(sign)
6787     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6788   else {
6789     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6790 */
6791   switch(shCount) {
6792   case 0:
6793     break;
6794   case 1:
6795   case 2:
6796   case 3:
6797     if(sign)
6798       emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6799     else
6800       emitCLRC;
6801
6802     if(same) {
6803       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6804       emitpcode(POC_RRF,popGet(AOP(result),offr));
6805     } else {
6806       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6807       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6808       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6809       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6810     }
6811
6812     while(--shCount) {
6813       if(sign)
6814         emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6815       else
6816         emitCLRC;
6817       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6818       emitpcode(POC_RRF,popGet(AOP(result),offr));
6819     }
6820     break;
6821   case 4:
6822   case 5:
6823     if(same) {
6824
6825       emitpcode(POC_MOVLW, popGetLit(0xf0));
6826       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6827       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6828
6829       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6830       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6831       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6832       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6833     } else {
6834       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6835       emitpcode(POC_ANDLW, popGetLit(0x0f));
6836       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6837
6838       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6839       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6840       emitpcode(POC_ANDLW, popGetLit(0xf0));
6841       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6842       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6843     }
6844
6845     if(shCount >=5) {
6846       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6847       emitpcode(POC_RRF, popGet(AOP(result),offr));
6848     }
6849
6850     if(sign) {
6851       emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6852       emitpcode(POC_BTFSC, 
6853                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6854       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6855     }
6856
6857     break;
6858
6859   case 6:
6860     if(same) {
6861
6862       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6863       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6864
6865       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6866       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6867       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6868       emitpcode(POC_ANDLW,popGetLit(0x03));
6869       if(sign) {
6870         emitpcode(POC_BTFSC, 
6871                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6872         emitpcode(POC_IORLW,popGetLit(0xfc));
6873       }
6874       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6875       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6876       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6877       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6878     } else {
6879       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6880       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6881       emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6882       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6883       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6884       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6885       emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6886       emitpcode(POC_ANDLW,popGetLit(0x03));
6887       if(sign) {
6888         emitpcode(POC_BTFSC, 
6889                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6890         emitpcode(POC_IORLW,popGetLit(0xfc));
6891       }
6892       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6893       //emitpcode(POC_RLF,  popGet(AOP(result),offr));
6894
6895         
6896     }
6897
6898     break;
6899   case 7:
6900     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6901     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6902     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6903     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6904     if(sign) {
6905       emitSKPNC;
6906       emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6907     } else 
6908       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6909   }
6910 }
6911
6912
6913 /*-----------------------------------------------------------------*/
6914 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6915 /*-----------------------------------------------------------------*/
6916 static void shiftLLeftOrResult (operand *left, int offl,
6917                                 operand *result, int offr, int shCount)
6918 {
6919     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6920     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6921     /* shift left accumulator */
6922     AccLsh(shCount);
6923     /* or with result */
6924     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6925     /* back to result */
6926     aopPut(AOP(result),"a",offr);
6927 }
6928
6929 /*-----------------------------------------------------------------*/
6930 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6931 /*-----------------------------------------------------------------*/
6932 static void shiftRLeftOrResult (operand *left, int offl,
6933                                 operand *result, int offr, int shCount)
6934 {
6935     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6936     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6937     /* shift right accumulator */
6938     AccRsh(shCount);
6939     /* or with result */
6940     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6941     /* back to result */
6942     aopPut(AOP(result),"a",offr);
6943 }
6944
6945 /*-----------------------------------------------------------------*/
6946 /* genlshOne - left shift a one byte quantity by known count       */
6947 /*-----------------------------------------------------------------*/
6948 static void genlshOne (operand *result, operand *left, int shCount)
6949 {       
6950     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6951     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6952 }
6953
6954 /*-----------------------------------------------------------------*/
6955 /* genlshTwo - left shift two bytes by known amount != 0           */
6956 /*-----------------------------------------------------------------*/
6957 static void genlshTwo (operand *result,operand *left, int shCount)
6958 {
6959     int size;
6960     
6961     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6962     size = pic14_getDataSize(result);
6963
6964     /* if shCount >= 8 */
6965     if (shCount >= 8) {
6966         shCount -= 8 ;
6967
6968         if (size > 1){
6969             if (shCount)
6970                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6971             else 
6972                 movLeft2Result(left, LSB, result, MSB16);
6973         }
6974         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6975     }
6976
6977     /*  1 <= shCount <= 7 */
6978     else {  
6979         if(size == 1)
6980             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6981         else 
6982             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6983     }
6984 }
6985
6986 /*-----------------------------------------------------------------*/
6987 /* shiftLLong - shift left one long from left to result            */
6988 /* offl = LSB or MSB16                                             */
6989 /*-----------------------------------------------------------------*/
6990 static void shiftLLong (operand *left, operand *result, int offr )
6991 {
6992     char *l;
6993     int size = AOP_SIZE(result);
6994
6995     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6996     if(size >= LSB+offr){
6997         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6998         MOVA(l);
6999         pic14_emitcode("add","a,acc");
7000         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7001             size >= MSB16+offr && offr != LSB )
7002             pic14_emitcode("xch","a,%s",
7003                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7004         else        
7005             aopPut(AOP(result),"a",LSB+offr);
7006     }
7007
7008     if(size >= MSB16+offr){
7009         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7010             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7011             MOVA(l);
7012         }
7013         pic14_emitcode("rlc","a");
7014         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7015             size >= MSB24+offr && offr != LSB)
7016             pic14_emitcode("xch","a,%s",
7017                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7018         else        
7019             aopPut(AOP(result),"a",MSB16+offr);
7020     }
7021
7022     if(size >= MSB24+offr){
7023         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7024             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7025             MOVA(l);
7026         }
7027         pic14_emitcode("rlc","a");
7028         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7029             size >= MSB32+offr && offr != LSB )
7030             pic14_emitcode("xch","a,%s",
7031                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7032         else        
7033             aopPut(AOP(result),"a",MSB24+offr);
7034     }
7035
7036     if(size > MSB32+offr){
7037         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7038             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7039             MOVA(l);    
7040         }
7041         pic14_emitcode("rlc","a");
7042         aopPut(AOP(result),"a",MSB32+offr);
7043     }
7044     if(offr != LSB)
7045         aopPut(AOP(result),zero,LSB);       
7046 }
7047
7048 /*-----------------------------------------------------------------*/
7049 /* genlshFour - shift four byte by a known amount != 0             */
7050 /*-----------------------------------------------------------------*/
7051 static void genlshFour (operand *result, operand *left, int shCount)
7052 {
7053     int size;
7054
7055     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7056     size = AOP_SIZE(result);
7057
7058     /* if shifting more that 3 bytes */
7059     if (shCount >= 24 ) {
7060         shCount -= 24;
7061         if (shCount)
7062             /* lowest order of left goes to the highest
7063             order of the destination */
7064             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7065         else
7066             movLeft2Result(left, LSB, result, MSB32);
7067         aopPut(AOP(result),zero,LSB);
7068         aopPut(AOP(result),zero,MSB16);
7069         aopPut(AOP(result),zero,MSB32);
7070         return;
7071     }
7072
7073     /* more than two bytes */
7074     else if ( shCount >= 16 ) {
7075         /* lower order two bytes goes to higher order two bytes */
7076         shCount -= 16;
7077         /* if some more remaining */
7078         if (shCount)
7079             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7080         else {
7081             movLeft2Result(left, MSB16, result, MSB32);
7082             movLeft2Result(left, LSB, result, MSB24);
7083         }
7084         aopPut(AOP(result),zero,MSB16);
7085         aopPut(AOP(result),zero,LSB);
7086         return;
7087     }    
7088
7089     /* if more than 1 byte */
7090     else if ( shCount >= 8 ) {
7091         /* lower order three bytes goes to higher order  three bytes */
7092         shCount -= 8;
7093         if(size == 2){
7094             if(shCount)
7095                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7096             else
7097                 movLeft2Result(left, LSB, result, MSB16);
7098         }
7099         else{   /* size = 4 */
7100             if(shCount == 0){
7101                 movLeft2Result(left, MSB24, result, MSB32);
7102                 movLeft2Result(left, MSB16, result, MSB24);
7103                 movLeft2Result(left, LSB, result, MSB16);
7104                 aopPut(AOP(result),zero,LSB);
7105             }
7106             else if(shCount == 1)
7107                 shiftLLong(left, result, MSB16);
7108             else{
7109                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7110                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7111                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7112                 aopPut(AOP(result),zero,LSB);
7113             }
7114         }
7115     }
7116
7117     /* 1 <= shCount <= 7 */
7118     else if(shCount <= 2){
7119         shiftLLong(left, result, LSB);
7120         if(shCount == 2)
7121             shiftLLong(result, result, LSB);
7122     }
7123     /* 3 <= shCount <= 7, optimize */
7124     else{
7125         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7126         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7127         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7128     }
7129 }
7130
7131 /*-----------------------------------------------------------------*/
7132 /* genLeftShiftLiteral - left shifting by known count              */
7133 /*-----------------------------------------------------------------*/
7134 static void genLeftShiftLiteral (operand *left,
7135                                  operand *right,
7136                                  operand *result,
7137                                  iCode *ic)
7138 {    
7139     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7140     int size;
7141
7142     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7143     freeAsmop(right,NULL,ic,TRUE);
7144
7145     aopOp(left,ic,FALSE);
7146     aopOp(result,ic,FALSE);
7147
7148     size = getSize(operandType(result));
7149
7150 #if VIEW_SIZE
7151     pic14_emitcode("; shift left ","result %d, left %d",size,
7152              AOP_SIZE(left));
7153 #endif
7154
7155     /* I suppose that the left size >= result size */
7156     if(shCount == 0){
7157         while(size--){
7158             movLeft2Result(left, size, result, size);
7159         }
7160     }
7161
7162     else if(shCount >= (size * 8))
7163         while(size--)
7164             aopPut(AOP(result),zero,size);
7165     else{
7166         switch (size) {
7167             case 1:
7168                 genlshOne (result,left,shCount);
7169                 break;
7170
7171             case 2:
7172             case 3:
7173                 genlshTwo (result,left,shCount);
7174                 break;
7175
7176             case 4:
7177                 genlshFour (result,left,shCount);
7178                 break;
7179         }
7180     }
7181     freeAsmop(left,NULL,ic,TRUE);
7182     freeAsmop(result,NULL,ic,TRUE);
7183 }
7184
7185 /*-----------------------------------------------------------------*
7186  * genMultiAsm - repeat assembly instruction for size of register.
7187  * if endian == 1, then the high byte (i.e base address + size of 
7188  * register) is used first else the low byte is used first;
7189  *-----------------------------------------------------------------*/
7190 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7191 {
7192
7193   int offset = 0;
7194
7195   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7196
7197   if(!reg)
7198     return;
7199
7200   if(!endian) {
7201     endian = 1;
7202   } else {
7203     endian = -1;
7204     offset = size-1;
7205   }
7206
7207   while(size--) {
7208     emitpcode(poc,    popGet(AOP(reg),offset));
7209     offset += endian;
7210   }
7211
7212 }
7213 /*-----------------------------------------------------------------*/
7214 /* genLeftShift - generates code for left shifting                 */
7215 /*-----------------------------------------------------------------*/
7216 static void genLeftShift (iCode *ic)
7217 {
7218   operand *left,*right, *result;
7219   int size, offset;
7220   char *l;
7221   symbol *tlbl , *tlbl1;
7222   pCodeOp *pctemp;
7223
7224   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7225
7226   right = IC_RIGHT(ic);
7227   left  = IC_LEFT(ic);
7228   result = IC_RESULT(ic);
7229
7230   aopOp(right,ic,FALSE);
7231
7232   /* if the shift count is known then do it 
7233      as efficiently as possible */
7234   if (AOP_TYPE(right) == AOP_LIT) {
7235     genLeftShiftLiteral (left,right,result,ic);
7236     return ;
7237   }
7238
7239   /* shift count is unknown then we have to form 
7240      a loop get the loop count in B : Note: we take
7241      only the lower order byte since shifting
7242      more that 32 bits make no sense anyway, ( the
7243      largest size of an object can be only 32 bits ) */  
7244
7245     
7246   aopOp(left,ic,FALSE);
7247   aopOp(result,ic,FALSE);
7248
7249   /* now move the left to the result if they are not the
7250      same */
7251   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7252       AOP_SIZE(result) > 1) {
7253
7254     size = AOP_SIZE(result);
7255     offset=0;
7256     while (size--) {
7257       l = aopGet(AOP(left),offset,FALSE,TRUE);
7258       if (*l == '@' && (IS_AOP_PREG(result))) {
7259
7260         pic14_emitcode("mov","a,%s",l);
7261         aopPut(AOP(result),"a",offset);
7262       } else {
7263         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7264         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7265         //aopPut(AOP(result),l,offset);
7266       }
7267       offset++;
7268     }
7269   }
7270
7271   size = AOP_SIZE(result);
7272
7273   /* if it is only one byte then */
7274   if (size == 1) {
7275     if(optimized_for_speed) {
7276       emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7277       emitpcode(POC_ANDLW,  popGetLit(0xf0));
7278       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7279       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7280       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7281       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7282       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7283       emitpcode(POC_RLFW,   popGet(AOP(result),0));
7284       emitpcode(POC_ANDLW,  popGetLit(0xfe));
7285       emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7286       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7287       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7288     } else {
7289
7290       tlbl = newiTempLabel(NULL);
7291       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7292         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7293         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7294       }
7295
7296       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7297       emitpcode(POC_RRF,    popGet(AOP(result),0));
7298       emitpLabel(tlbl->key);
7299       emitpcode(POC_RLF,    popGet(AOP(result),0));
7300       emitpcode(POC_ADDLW,  popGetLit(1));
7301       emitSKPC;
7302       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7303     }
7304     goto release ;
7305   }
7306     
7307   if (pic14_sameRegs(AOP(left),AOP(result))) {
7308
7309     tlbl = newiTempLabel(NULL);
7310     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7311     genMultiAsm(POC_RRF, result, size,1);
7312     emitpLabel(tlbl->key);
7313     genMultiAsm(POC_RLF, result, size,0);
7314     emitpcode(POC_ADDLW,  popGetLit(1));
7315     emitSKPC;
7316     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7317     goto release;
7318   }
7319
7320   //tlbl = newiTempLabel(NULL);
7321   //offset = 0 ;   
7322   //tlbl1 = newiTempLabel(NULL);
7323
7324   //reAdjustPreg(AOP(result));    
7325     
7326   //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7327   //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7328   //l = aopGet(AOP(result),offset,FALSE,FALSE);
7329   //MOVA(l);
7330   //pic14_emitcode("add","a,acc");         
7331   //aopPut(AOP(result),"a",offset++);
7332   //while (--size) {
7333   //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7334   //  MOVA(l);
7335   //  pic14_emitcode("rlc","a");         
7336   //  aopPut(AOP(result),"a",offset++);
7337   //}
7338   //reAdjustPreg(AOP(result));
7339
7340   //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7341   //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7342
7343
7344   tlbl = newiTempLabel(NULL);
7345   tlbl1= newiTempLabel(NULL);
7346
7347   size = AOP_SIZE(result);
7348   offset = 1;
7349
7350   pctemp = popGetTempReg();  /* grab a temporary working register. */
7351
7352   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7353
7354   /* offset should be 0, 1 or 3 */
7355   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7356   emitSKPNZ;
7357   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7358
7359   emitpcode(POC_MOVWF, pctemp);
7360
7361
7362   emitpLabel(tlbl->key);
7363
7364   emitCLRC;
7365   emitpcode(POC_RLF,  popGet(AOP(result),0));
7366   while(--size)
7367     emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7368
7369   emitpcode(POC_DECFSZ,  pctemp);
7370   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7371   emitpLabel(tlbl1->key);
7372
7373   popReleaseTempReg(pctemp);
7374
7375
7376  release:
7377   freeAsmop (right,NULL,ic,TRUE);
7378   freeAsmop(left,NULL,ic,TRUE);
7379   freeAsmop(result,NULL,ic,TRUE);
7380 }
7381
7382 /*-----------------------------------------------------------------*/
7383 /* genrshOne - right shift a one byte quantity by known count      */
7384 /*-----------------------------------------------------------------*/
7385 static void genrshOne (operand *result, operand *left,
7386                        int shCount, int sign)
7387 {
7388     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7389     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7390 }
7391
7392 /*-----------------------------------------------------------------*/
7393 /* genrshTwo - right shift two bytes by known amount != 0          */
7394 /*-----------------------------------------------------------------*/
7395 static void genrshTwo (operand *result,operand *left,
7396                        int shCount, int sign)
7397 {
7398   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7399   /* if shCount >= 8 */
7400   if (shCount >= 8) {
7401     shCount -= 8 ;
7402     if (shCount)
7403       shiftR1Left2Result(left, MSB16, result, LSB,
7404                          shCount, sign);
7405     else
7406       movLeft2Result(left, MSB16, result, LSB);
7407
7408     emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7409
7410     if(sign) {
7411       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7412       emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7413     }
7414   }
7415
7416   /*  1 <= shCount <= 7 */
7417   else
7418     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7419 }
7420
7421 /*-----------------------------------------------------------------*/
7422 /* shiftRLong - shift right one long from left to result           */
7423 /* offl = LSB or MSB16                                             */
7424 /*-----------------------------------------------------------------*/
7425 static void shiftRLong (operand *left, int offl,
7426                         operand *result, int sign)
7427 {
7428     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7429     if(!sign)
7430         pic14_emitcode("clr","c");
7431     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7432     if(sign)
7433         pic14_emitcode("mov","c,acc.7");
7434     pic14_emitcode("rrc","a");
7435     aopPut(AOP(result),"a",MSB32-offl);
7436     if(offl == MSB16)
7437         /* add sign of "a" */
7438         addSign(result, MSB32, sign);
7439
7440     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7441     pic14_emitcode("rrc","a");
7442     aopPut(AOP(result),"a",MSB24-offl);
7443
7444     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7445     pic14_emitcode("rrc","a");
7446     aopPut(AOP(result),"a",MSB16-offl);
7447
7448     if(offl == LSB){
7449         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7450         pic14_emitcode("rrc","a");
7451         aopPut(AOP(result),"a",LSB);
7452     }
7453 }
7454
7455 /*-----------------------------------------------------------------*/
7456 /* genrshFour - shift four byte by a known amount != 0             */
7457 /*-----------------------------------------------------------------*/
7458 static void genrshFour (operand *result, operand *left,
7459                         int shCount, int sign)
7460 {
7461   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7462   /* if shifting more that 3 bytes */
7463   if(shCount >= 24 ) {
7464     shCount -= 24;
7465     if(shCount)
7466       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7467     else
7468       movLeft2Result(left, MSB32, result, LSB);
7469
7470     addSign(result, MSB16, sign);
7471   }
7472   else if(shCount >= 16){
7473     shCount -= 16;
7474     if(shCount)
7475       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7476     else{
7477       movLeft2Result(left, MSB24, result, LSB);
7478       movLeft2Result(left, MSB32, result, MSB16);
7479     }
7480     addSign(result, MSB24, sign);
7481   }
7482   else if(shCount >= 8){
7483     shCount -= 8;
7484     if(shCount == 1)
7485       shiftRLong(left, MSB16, result, sign);
7486     else if(shCount == 0){
7487       movLeft2Result(left, MSB16, result, LSB);
7488       movLeft2Result(left, MSB24, result, MSB16);
7489       movLeft2Result(left, MSB32, result, MSB24);
7490       addSign(result, MSB32, sign);
7491     }
7492     else{
7493       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7494       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7495       /* the last shift is signed */
7496       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7497       addSign(result, MSB32, sign);
7498     }
7499   }
7500   else{   /* 1 <= shCount <= 7 */
7501     if(shCount <= 2){
7502       shiftRLong(left, LSB, result, sign);
7503       if(shCount == 2)
7504         shiftRLong(result, LSB, result, sign);
7505     }
7506     else{
7507       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7508       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7509       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7510     }
7511   }
7512 }
7513
7514 /*-----------------------------------------------------------------*/
7515 /* genRightShiftLiteral - right shifting by known count            */
7516 /*-----------------------------------------------------------------*/
7517 static void genRightShiftLiteral (operand *left,
7518                                   operand *right,
7519                                   operand *result,
7520                                   iCode *ic,
7521                                   int sign)
7522 {    
7523   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7524   int lsize,res_size;
7525
7526   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7527   freeAsmop(right,NULL,ic,TRUE);
7528
7529   aopOp(left,ic,FALSE);
7530   aopOp(result,ic,FALSE);
7531
7532 #if VIEW_SIZE
7533   pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7534                  AOP_SIZE(left));
7535 #endif
7536
7537   lsize = pic14_getDataSize(left);
7538   res_size = pic14_getDataSize(result);
7539   /* test the LEFT size !!! */
7540
7541   /* I suppose that the left size >= result size */
7542   if(shCount == 0){
7543     while(res_size--)
7544       movLeft2Result(left, lsize, result, res_size);
7545   }
7546
7547   else if(shCount >= (lsize * 8)){
7548
7549     if(res_size == 1) {
7550       emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7551       if(sign) {
7552         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7553         emitpcode(POC_DECF, popGet(AOP(result),LSB));
7554       }
7555     } else {
7556
7557       if(sign) {
7558         emitpcode(POC_MOVLW, popGetLit(0));
7559         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7560         emitpcode(POC_MOVLW, popGetLit(0xff));
7561         while(res_size--)
7562           emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7563
7564       } else {
7565
7566         while(res_size--)
7567           emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7568       }
7569     }
7570   } else {
7571
7572     switch (res_size) {
7573     case 1:
7574       genrshOne (result,left,shCount,sign);
7575       break;
7576
7577     case 2:
7578       genrshTwo (result,left,shCount,sign);
7579       break;
7580
7581     case 4:
7582       genrshFour (result,left,shCount,sign);
7583       break;
7584     default :
7585       break;
7586     }
7587
7588   }
7589
7590   freeAsmop(left,NULL,ic,TRUE);
7591   freeAsmop(result,NULL,ic,TRUE);
7592 }
7593
7594 /*-----------------------------------------------------------------*/
7595 /* genSignedRightShift - right shift of signed number              */
7596 /*-----------------------------------------------------------------*/
7597 static void genSignedRightShift (iCode *ic)
7598 {
7599   operand *right, *left, *result;
7600   int size, offset;
7601   //  char *l;
7602   symbol *tlbl, *tlbl1 ;
7603   pCodeOp *pctemp;
7604
7605   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7606
7607   /* we do it the hard way put the shift count in b
7608      and loop thru preserving the sign */
7609   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7610
7611   right = IC_RIGHT(ic);
7612   left  = IC_LEFT(ic);
7613   result = IC_RESULT(ic);
7614
7615   aopOp(right,ic,FALSE);  
7616   aopOp(left,ic,FALSE);
7617   aopOp(result,ic,FALSE);
7618
7619
7620   if ( AOP_TYPE(right) == AOP_LIT) {
7621     genRightShiftLiteral (left,right,result,ic,1);
7622     return ;
7623   }
7624   /* shift count is unknown then we have to form 
7625      a loop get the loop count in B : Note: we take
7626      only the lower order byte since shifting
7627      more that 32 bits make no sense anyway, ( the
7628      largest size of an object can be only 32 bits ) */  
7629
7630   //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7631   //pic14_emitcode("inc","b");
7632   //freeAsmop (right,NULL,ic,TRUE);
7633   //aopOp(left,ic,FALSE);
7634   //aopOp(result,ic,FALSE);
7635
7636   /* now move the left to the result if they are not the
7637      same */
7638   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7639       AOP_SIZE(result) > 1) {
7640
7641     size = AOP_SIZE(result);
7642     offset=0;
7643     while (size--) { 
7644       /*
7645         l = aopGet(AOP(left),offset,FALSE,TRUE);
7646         if (*l == '@' && IS_AOP_PREG(result)) {
7647
7648         pic14_emitcode("mov","a,%s",l);
7649         aopPut(AOP(result),"a",offset);
7650         } else
7651         aopPut(AOP(result),l,offset);
7652       */
7653       emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7654       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7655
7656       offset++;
7657     }
7658   }
7659
7660   /* mov the highest order bit to OVR */    
7661   tlbl = newiTempLabel(NULL);
7662   tlbl1= newiTempLabel(NULL);
7663
7664   size = AOP_SIZE(result);
7665   offset = size - 1;
7666
7667   pctemp = popGetTempReg();  /* grab a temporary working register. */
7668
7669   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7670
7671   /* offset should be 0, 1 or 3 */
7672   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7673   emitSKPNZ;
7674   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7675
7676   emitpcode(POC_MOVWF, pctemp);
7677
7678
7679   emitpLabel(tlbl->key);
7680
7681   emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7682   emitpcode(POC_RRF,   popGet(AOP(result),offset));
7683
7684   while(--size) {
7685     emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7686   }
7687
7688   emitpcode(POC_DECFSZ,  pctemp);
7689   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7690   emitpLabel(tlbl1->key);
7691
7692   popReleaseTempReg(pctemp);
7693 #if 0
7694   size = AOP_SIZE(result);
7695   offset = size - 1;
7696   pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7697   pic14_emitcode("rlc","a");
7698   pic14_emitcode("mov","ov,c");
7699   /* if it is only one byte then */
7700   if (size == 1) {
7701     l = aopGet(AOP(left),0,FALSE,FALSE);
7702     MOVA(l);
7703     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7704     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7705     pic14_emitcode("mov","c,ov");
7706     pic14_emitcode("rrc","a");
7707     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7708     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7709     aopPut(AOP(result),"a",0);
7710     goto release ;
7711   }
7712
7713   reAdjustPreg(AOP(result));
7714   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7715   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7716   pic14_emitcode("mov","c,ov");
7717   while (size--) {
7718     l = aopGet(AOP(result),offset,FALSE,FALSE);
7719     MOVA(l);
7720     pic14_emitcode("rrc","a");         
7721     aopPut(AOP(result),"a",offset--);
7722   }
7723   reAdjustPreg(AOP(result));
7724   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7725   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7726
7727  release:
7728 #endif
7729
7730   freeAsmop(left,NULL,ic,TRUE);
7731   freeAsmop(result,NULL,ic,TRUE);
7732   freeAsmop(right,NULL,ic,TRUE);
7733 }
7734
7735 /*-----------------------------------------------------------------*/
7736 /* genRightShift - generate code for right shifting                */
7737 /*-----------------------------------------------------------------*/
7738 static void genRightShift (iCode *ic)
7739 {
7740     operand *right, *left, *result;
7741     sym_link *retype ;
7742     int size, offset;
7743     char *l;
7744     symbol *tlbl, *tlbl1 ;
7745
7746     /* if signed then we do it the hard way preserve the
7747     sign bit moving it inwards */
7748     retype = getSpec(operandType(IC_RESULT(ic)));
7749     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7750
7751     if (!SPEC_USIGN(retype)) {
7752         genSignedRightShift (ic);
7753         return ;
7754     }
7755
7756     /* signed & unsigned types are treated the same : i.e. the
7757     signed is NOT propagated inwards : quoting from the
7758     ANSI - standard : "for E1 >> E2, is equivalent to division
7759     by 2**E2 if unsigned or if it has a non-negative value,
7760     otherwise the result is implementation defined ", MY definition
7761     is that the sign does not get propagated */
7762
7763     right = IC_RIGHT(ic);
7764     left  = IC_LEFT(ic);
7765     result = IC_RESULT(ic);
7766
7767     aopOp(right,ic,FALSE);
7768
7769     /* if the shift count is known then do it 
7770     as efficiently as possible */
7771     if (AOP_TYPE(right) == AOP_LIT) {
7772         genRightShiftLiteral (left,right,result,ic, 0);
7773         return ;
7774     }
7775
7776     /* shift count is unknown then we have to form 
7777     a loop get the loop count in B : Note: we take
7778     only the lower order byte since shifting
7779     more that 32 bits make no sense anyway, ( the
7780     largest size of an object can be only 32 bits ) */  
7781
7782     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7783     pic14_emitcode("inc","b");
7784     aopOp(left,ic,FALSE);
7785     aopOp(result,ic,FALSE);
7786
7787     /* now move the left to the result if they are not the
7788     same */
7789     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7790         AOP_SIZE(result) > 1) {
7791
7792         size = AOP_SIZE(result);
7793         offset=0;
7794         while (size--) {
7795             l = aopGet(AOP(left),offset,FALSE,TRUE);
7796             if (*l == '@' && IS_AOP_PREG(result)) {
7797
7798                 pic14_emitcode("mov","a,%s",l);
7799                 aopPut(AOP(result),"a",offset);
7800             } else
7801                 aopPut(AOP(result),l,offset);
7802             offset++;
7803         }
7804     }
7805
7806     tlbl = newiTempLabel(NULL);
7807     tlbl1= newiTempLabel(NULL);
7808     size = AOP_SIZE(result);
7809     offset = size - 1;
7810
7811     /* if it is only one byte then */
7812     if (size == 1) {
7813
7814       tlbl = newiTempLabel(NULL);
7815       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7816         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7817         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7818       }
7819
7820       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7821       emitpcode(POC_RLF,    popGet(AOP(result),0));
7822       emitpLabel(tlbl->key);
7823       emitpcode(POC_RRF,    popGet(AOP(result),0));
7824       emitpcode(POC_ADDLW,  popGetLit(1));
7825       emitSKPC;
7826       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7827
7828       goto release ;
7829     }
7830
7831     reAdjustPreg(AOP(result));
7832     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7833     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7834     CLRC;
7835     while (size--) {
7836         l = aopGet(AOP(result),offset,FALSE,FALSE);
7837         MOVA(l);
7838         pic14_emitcode("rrc","a");         
7839         aopPut(AOP(result),"a",offset--);
7840     }
7841     reAdjustPreg(AOP(result));
7842
7843     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7844     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7845
7846 release:
7847     freeAsmop(left,NULL,ic,TRUE);
7848     freeAsmop (right,NULL,ic,TRUE);
7849     freeAsmop(result,NULL,ic,TRUE);
7850 }
7851
7852 /*-----------------------------------------------------------------*/
7853 /* genUnpackBits - generates code for unpacking bits               */
7854 /*-----------------------------------------------------------------*/
7855 static void genUnpackBits (operand *result, char *rname, int ptype)
7856 {    
7857     int shCnt ;
7858     int rlen = 0 ;
7859     sym_link *etype;
7860     int offset = 0 ;
7861
7862     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7863     etype = getSpec(operandType(result));
7864
7865     /* read the first byte  */
7866     switch (ptype) {
7867
7868     case POINTER:
7869     case IPOINTER:
7870         pic14_emitcode("mov","a,@%s",rname);
7871         break;
7872         
7873     case PPOINTER:
7874         pic14_emitcode("movx","a,@%s",rname);
7875         break;
7876         
7877     case FPOINTER:
7878         pic14_emitcode("movx","a,@dptr");
7879         break;
7880
7881     case CPOINTER:
7882         pic14_emitcode("clr","a");
7883         pic14_emitcode("movc","a","@a+dptr");
7884         break;
7885
7886     case GPOINTER:
7887         pic14_emitcode("lcall","__gptrget");
7888         break;
7889     }
7890
7891     /* if we have bitdisplacement then it fits   */
7892     /* into this byte completely or if length is */
7893     /* less than a byte                          */
7894     if ((shCnt = SPEC_BSTR(etype)) || 
7895         (SPEC_BLEN(etype) <= 8))  {
7896
7897         /* shift right acc */
7898         AccRsh(shCnt);
7899
7900         pic14_emitcode("anl","a,#0x%02x",
7901                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7902         aopPut(AOP(result),"a",offset);
7903         return ;
7904     }
7905
7906     /* bit field did not fit in a byte  */
7907     rlen = SPEC_BLEN(etype) - 8;
7908     aopPut(AOP(result),"a",offset++);
7909
7910     while (1)  {
7911
7912         switch (ptype) {
7913         case POINTER:
7914         case IPOINTER:
7915             pic14_emitcode("inc","%s",rname);
7916             pic14_emitcode("mov","a,@%s",rname);
7917             break;
7918             
7919         case PPOINTER:
7920             pic14_emitcode("inc","%s",rname);
7921             pic14_emitcode("movx","a,@%s",rname);
7922             break;
7923
7924         case FPOINTER:
7925             pic14_emitcode("inc","dptr");
7926             pic14_emitcode("movx","a,@dptr");
7927             break;
7928             
7929         case CPOINTER:
7930             pic14_emitcode("clr","a");
7931             pic14_emitcode("inc","dptr");
7932             pic14_emitcode("movc","a","@a+dptr");
7933             break;
7934             
7935         case GPOINTER:
7936             pic14_emitcode("inc","dptr");
7937             pic14_emitcode("lcall","__gptrget");
7938             break;
7939         }
7940
7941         rlen -= 8;            
7942         /* if we are done */
7943         if ( rlen <= 0 )
7944             break ;
7945         
7946         aopPut(AOP(result),"a",offset++);
7947                               
7948     }
7949     
7950     if (rlen) {
7951         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7952         aopPut(AOP(result),"a",offset);        
7953     }
7954     
7955     return ;
7956 }
7957
7958 #if 0
7959 /*-----------------------------------------------------------------*/
7960 /* genDataPointerGet - generates code when ptr offset is known     */
7961 /*-----------------------------------------------------------------*/
7962 static void genDataPointerGet (operand *left, 
7963                                operand *result, 
7964                                iCode *ic)
7965 {
7966   int size , offset = 0;
7967
7968
7969   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7970
7971
7972   /* optimization - most of the time, left and result are the same
7973    * address, but different types. for the pic code, we could omit
7974    * the following
7975    */
7976
7977   aopOp(result,ic,TRUE);
7978
7979   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7980
7981   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7982
7983   size = AOP_SIZE(result);
7984
7985   while (size--) {
7986     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7987     offset++;
7988   }
7989
7990   freeAsmop(left,NULL,ic,TRUE);
7991   freeAsmop(result,NULL,ic,TRUE);
7992 }
7993 #endif
7994 /*-----------------------------------------------------------------*/
7995 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7996 /*-----------------------------------------------------------------*/
7997 static void genNearPointerGet (operand *left, 
7998                                operand *result, 
7999                                iCode *ic)
8000 {
8001     asmop *aop = NULL;
8002     //regs *preg = NULL ;
8003     char *rname ;
8004     sym_link *rtype, *retype;
8005     sym_link *ltype = operandType(left);    
8006     //char buffer[80];
8007
8008     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8009
8010     rtype = operandType(result);
8011     retype= getSpec(rtype);
8012     
8013     aopOp(left,ic,FALSE);
8014     
8015     /* if left is rematerialisable and
8016        result is not bit variable type and
8017        the left is pointer to data space i.e
8018        lower 128 bytes of space */
8019     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8020         !IS_BITVAR(retype)         &&
8021         DCL_TYPE(ltype) == POINTER) {
8022       //genDataPointerGet (left,result,ic);
8023         return ;
8024     }
8025     
8026     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8027
8028         /* if the value is already in a pointer register
8029        then don't need anything more */
8030     if (!AOP_INPREG(AOP(left))) {
8031         /* otherwise get a free pointer register */
8032     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8033 /*
8034         aop = newAsmop(0);
8035         preg = getFreePtr(ic,&aop,FALSE);
8036         pic14_emitcode("mov","%s,%s",
8037                 preg->name,
8038                 aopGet(AOP(left),0,FALSE,TRUE));
8039         rname = preg->name ;
8040 */
8041     rname ="BAD";
8042     } else
8043         rname = aopGet(AOP(left),0,FALSE,FALSE);
8044     
8045     aopOp (result,ic,FALSE);
8046     
8047       /* if bitfield then unpack the bits */
8048     if (IS_BITVAR(retype)) 
8049         genUnpackBits (result,rname,POINTER);
8050     else {
8051         /* we have can just get the values */
8052       int size = AOP_SIZE(result);
8053       int offset = 0 ;  
8054         
8055       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8056
8057       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8058       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8059       while(size--) {
8060         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8061         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8062         if(size)
8063           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8064       }
8065 /*
8066         while (size--) {
8067             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8068
8069                 pic14_emitcode("mov","a,@%s",rname);
8070                 aopPut(AOP(result),"a",offset);
8071             } else {
8072                 sprintf(buffer,"@%s",rname);
8073                 aopPut(AOP(result),buffer,offset);
8074             }
8075             offset++ ;
8076             if (size)
8077                 pic14_emitcode("inc","%s",rname);
8078         }
8079 */
8080     }
8081
8082     /* now some housekeeping stuff */
8083     if (aop) {
8084         /* we had to allocate for this iCode */
8085     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8086         freeAsmop(NULL,aop,ic,TRUE);
8087     } else { 
8088         /* we did not allocate which means left
8089            already in a pointer register, then
8090            if size > 0 && this could be used again
8091            we have to point it back to where it 
8092            belongs */
8093     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8094         if (AOP_SIZE(result) > 1 &&
8095             !OP_SYMBOL(left)->remat &&
8096             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8097               ic->depth )) {
8098             int size = AOP_SIZE(result) - 1;
8099             while (size--)
8100                 pic14_emitcode("dec","%s",rname);
8101         }
8102     }
8103
8104     /* done */
8105     freeAsmop(left,NULL,ic,TRUE);
8106     freeAsmop(result,NULL,ic,TRUE);
8107      
8108 }
8109
8110 /*-----------------------------------------------------------------*/
8111 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8112 /*-----------------------------------------------------------------*/
8113 static void genPagedPointerGet (operand *left, 
8114                                operand *result, 
8115                                iCode *ic)
8116 {
8117     asmop *aop = NULL;
8118     regs *preg = NULL ;
8119     char *rname ;
8120     sym_link *rtype, *retype;    
8121
8122     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8123
8124     rtype = operandType(result);
8125     retype= getSpec(rtype);
8126     
8127     aopOp(left,ic,FALSE);
8128
8129   /* if the value is already in a pointer register
8130        then don't need anything more */
8131     if (!AOP_INPREG(AOP(left))) {
8132         /* otherwise get a free pointer register */
8133         aop = newAsmop(0);
8134         preg = getFreePtr(ic,&aop,FALSE);
8135         pic14_emitcode("mov","%s,%s",
8136                 preg->name,
8137                 aopGet(AOP(left),0,FALSE,TRUE));
8138         rname = preg->name ;
8139     } else
8140         rname = aopGet(AOP(left),0,FALSE,FALSE);
8141     
8142     freeAsmop(left,NULL,ic,TRUE);
8143     aopOp (result,ic,FALSE);
8144
8145     /* if bitfield then unpack the bits */
8146     if (IS_BITVAR(retype)) 
8147         genUnpackBits (result,rname,PPOINTER);
8148     else {
8149         /* we have can just get the values */
8150         int size = AOP_SIZE(result);
8151         int offset = 0 ;        
8152         
8153         while (size--) {
8154             
8155             pic14_emitcode("movx","a,@%s",rname);
8156             aopPut(AOP(result),"a",offset);
8157             
8158             offset++ ;
8159             
8160             if (size)
8161                 pic14_emitcode("inc","%s",rname);
8162         }
8163     }
8164
8165     /* now some housekeeping stuff */
8166     if (aop) {
8167         /* we had to allocate for this iCode */
8168         freeAsmop(NULL,aop,ic,TRUE);
8169     } else { 
8170         /* we did not allocate which means left
8171            already in a pointer register, then
8172            if size > 0 && this could be used again
8173            we have to point it back to where it 
8174            belongs */
8175         if (AOP_SIZE(result) > 1 &&
8176             !OP_SYMBOL(left)->remat &&
8177             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8178               ic->depth )) {
8179             int size = AOP_SIZE(result) - 1;
8180             while (size--)
8181                 pic14_emitcode("dec","%s",rname);
8182         }
8183     }
8184
8185     /* done */
8186     freeAsmop(result,NULL,ic,TRUE);
8187     
8188         
8189 }
8190
8191 /*-----------------------------------------------------------------*/
8192 /* genFarPointerGet - gget value from far space                    */
8193 /*-----------------------------------------------------------------*/
8194 static void genFarPointerGet (operand *left,
8195                               operand *result, iCode *ic)
8196 {
8197     int size, offset ;
8198     sym_link *retype = getSpec(operandType(result));
8199
8200     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8201
8202     aopOp(left,ic,FALSE);
8203
8204     /* if the operand is already in dptr 
8205     then we do nothing else we move the value to dptr */
8206     if (AOP_TYPE(left) != AOP_STR) {
8207         /* if this is remateriazable */
8208         if (AOP_TYPE(left) == AOP_IMMD)
8209             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8210         else { /* we need to get it byte by byte */
8211             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8212             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8213             if (options.model == MODEL_FLAT24)
8214             {
8215                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8216             }
8217         }
8218     }
8219     /* so dptr know contains the address */
8220     freeAsmop(left,NULL,ic,TRUE);
8221     aopOp(result,ic,FALSE);
8222
8223     /* if bit then unpack */
8224     if (IS_BITVAR(retype)) 
8225         genUnpackBits(result,"dptr",FPOINTER);
8226     else {
8227         size = AOP_SIZE(result);
8228         offset = 0 ;
8229
8230         while (size--) {
8231             pic14_emitcode("movx","a,@dptr");
8232             aopPut(AOP(result),"a",offset++);
8233             if (size)
8234                 pic14_emitcode("inc","dptr");
8235         }
8236     }
8237
8238     freeAsmop(result,NULL,ic,TRUE);
8239 }
8240 #if 0
8241 /*-----------------------------------------------------------------*/
8242 /* genCodePointerGet - get value from code space                  */
8243 /*-----------------------------------------------------------------*/
8244 static void genCodePointerGet (operand *left,
8245                                 operand *result, iCode *ic)
8246 {
8247     int size, offset ;
8248     sym_link *retype = getSpec(operandType(result));
8249
8250     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8251
8252     aopOp(left,ic,FALSE);
8253
8254     /* if the operand is already in dptr 
8255     then we do nothing else we move the value to dptr */
8256     if (AOP_TYPE(left) != AOP_STR) {
8257         /* if this is remateriazable */
8258         if (AOP_TYPE(left) == AOP_IMMD)
8259             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8260         else { /* we need to get it byte by byte */
8261             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8262             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8263             if (options.model == MODEL_FLAT24)
8264             {
8265                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8266             }
8267         }
8268     }
8269     /* so dptr know contains the address */
8270     freeAsmop(left,NULL,ic,TRUE);
8271     aopOp(result,ic,FALSE);
8272
8273     /* if bit then unpack */
8274     if (IS_BITVAR(retype)) 
8275         genUnpackBits(result,"dptr",CPOINTER);
8276     else {
8277         size = AOP_SIZE(result);
8278         offset = 0 ;
8279
8280         while (size--) {
8281             pic14_emitcode("clr","a");
8282             pic14_emitcode("movc","a,@a+dptr");
8283             aopPut(AOP(result),"a",offset++);
8284             if (size)
8285                 pic14_emitcode("inc","dptr");
8286         }
8287     }
8288
8289     freeAsmop(result,NULL,ic,TRUE);
8290 }
8291 #endif
8292 /*-----------------------------------------------------------------*/
8293 /* genGenPointerGet - gget value from generic pointer space        */
8294 /*-----------------------------------------------------------------*/
8295 static void genGenPointerGet (operand *left,
8296                               operand *result, iCode *ic)
8297 {
8298   int size, offset ;
8299   sym_link *retype = getSpec(operandType(result));
8300
8301   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8302   aopOp(left,ic,FALSE);
8303   aopOp(result,ic,FALSE);
8304
8305
8306   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8307
8308   /* if the operand is already in dptr 
8309      then we do nothing else we move the value to dptr */
8310   //  if (AOP_TYPE(left) != AOP_STR) {
8311     /* if this is remateriazable */
8312     if (AOP_TYPE(left) == AOP_IMMD) {
8313       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8314       pic14_emitcode("mov","b,#%d",pointerCode(retype));
8315     }
8316     else { /* we need to get it byte by byte */
8317
8318       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8319       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8320
8321       size = AOP_SIZE(result);
8322       offset = 0 ;
8323
8324       while(size--) {
8325         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8326         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8327         if(size)
8328           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8329       }
8330       goto release;
8331     }
8332     //}
8333   /* so dptr know contains the address */
8334
8335   /* if bit then unpack */
8336   //if (IS_BITVAR(retype)) 
8337   //  genUnpackBits(result,"dptr",GPOINTER);
8338
8339  release:
8340   freeAsmop(left,NULL,ic,TRUE);
8341   freeAsmop(result,NULL,ic,TRUE);
8342
8343 }
8344
8345 /*-----------------------------------------------------------------*/
8346 /* genConstPointerGet - get value from const generic pointer space */
8347 /*-----------------------------------------------------------------*/
8348 static void genConstPointerGet (operand *left,
8349                                 operand *result, iCode *ic)
8350 {
8351   //sym_link *retype = getSpec(operandType(result));
8352   symbol *albl = newiTempLabel(NULL);
8353   symbol *blbl = newiTempLabel(NULL);
8354   PIC_OPCODE poc;
8355
8356   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8357   aopOp(left,ic,FALSE);
8358   aopOp(result,ic,FALSE);
8359
8360
8361   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8362
8363   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8364
8365   emitpcode(POC_CALL,popGetLabel(albl->key));
8366   emitpcode(POC_GOTO,popGetLabel(blbl->key));
8367   emitpLabel(albl->key);
8368
8369   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8370     
8371   emitpcode(poc,popGet(AOP(left),1));
8372   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8373   emitpcode(poc,popGet(AOP(left),0));
8374   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8375
8376   emitpLabel(blbl->key);
8377
8378   emitpcode(POC_MOVWF,popGet(AOP(result),0));
8379
8380
8381   freeAsmop(left,NULL,ic,TRUE);
8382   freeAsmop(result,NULL,ic,TRUE);
8383
8384 }
8385 /*-----------------------------------------------------------------*/
8386 /* genPointerGet - generate code for pointer get                   */
8387 /*-----------------------------------------------------------------*/
8388 static void genPointerGet (iCode *ic)
8389 {
8390     operand *left, *result ;
8391     sym_link *type, *etype;
8392     int p_type;
8393
8394     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8395
8396     left = IC_LEFT(ic);
8397     result = IC_RESULT(ic) ;
8398
8399     /* depending on the type of pointer we need to
8400     move it to the correct pointer register */
8401     type = operandType(left);
8402     etype = getSpec(type);
8403
8404     if (IS_PTR_CONST(type))
8405       DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8406
8407     /* if left is of type of pointer then it is simple */
8408     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8409         p_type = DCL_TYPE(type);
8410     else {
8411         /* we have to go by the storage class */
8412         p_type = PTR_TYPE(SPEC_OCLS(etype));
8413
8414         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8415
8416         if (SPEC_OCLS(etype)->codesp ) {
8417           DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8418           //p_type = CPOINTER ; 
8419         }
8420         else
8421             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8422               DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8423                /*p_type = FPOINTER ;*/ 
8424             else
8425                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8426                   DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8427 /*                  p_type = PPOINTER; */
8428                 else
8429                     if (SPEC_OCLS(etype) == idata )
8430                       DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8431 /*                      p_type = IPOINTER; */
8432                     else
8433                       DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8434 /*                      p_type = POINTER ; */
8435     }
8436
8437     /* now that we have the pointer type we assign
8438     the pointer values */
8439     switch (p_type) {
8440
8441     case POINTER:       
8442     case IPOINTER:
8443         genNearPointerGet (left,result,ic);
8444         break;
8445
8446     case PPOINTER:
8447         genPagedPointerGet(left,result,ic);
8448         break;
8449
8450     case FPOINTER:
8451         genFarPointerGet (left,result,ic);
8452         break;
8453
8454     case CPOINTER:
8455         genConstPointerGet (left,result,ic);
8456         //pic14_emitcodePointerGet (left,result,ic);
8457         break;
8458
8459     case GPOINTER:
8460       if (IS_PTR_CONST(type))
8461         genConstPointerGet (left,result,ic);
8462       else
8463         genGenPointerGet (left,result,ic);
8464       break;
8465     }
8466
8467 }
8468
8469 /*-----------------------------------------------------------------*/
8470 /* genPackBits - generates code for packed bit storage             */
8471 /*-----------------------------------------------------------------*/
8472 static void genPackBits (sym_link    *etype ,
8473                          operand *right ,
8474                          char *rname, int p_type)
8475 {
8476     int shCount = 0 ;
8477     int offset = 0  ;
8478     int rLen = 0 ;
8479     int blen, bstr ;   
8480     char *l ;
8481
8482     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8483     blen = SPEC_BLEN(etype);
8484     bstr = SPEC_BSTR(etype);
8485
8486     l = aopGet(AOP(right),offset++,FALSE,FALSE);
8487     MOVA(l);   
8488
8489     /* if the bit lenth is less than or    */
8490     /* it exactly fits a byte then         */
8491     if (SPEC_BLEN(etype) <= 8 )  {
8492         shCount = SPEC_BSTR(etype) ;
8493
8494         /* shift left acc */
8495         AccLsh(shCount);
8496
8497         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8498
8499
8500             switch (p_type) {
8501                 case POINTER:
8502                     pic14_emitcode ("mov","b,a");
8503                     pic14_emitcode("mov","a,@%s",rname);
8504                     break;
8505
8506                 case FPOINTER:
8507                     pic14_emitcode ("mov","b,a");
8508                     pic14_emitcode("movx","a,@dptr");
8509                     break;
8510
8511                 case GPOINTER:
8512                     pic14_emitcode ("push","b");
8513                     pic14_emitcode ("push","acc");
8514                     pic14_emitcode ("lcall","__gptrget");
8515                     pic14_emitcode ("pop","b");
8516                     break;
8517             }
8518
8519             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8520                       ((unsigned char)(0xFF << (blen+bstr)) | 
8521                        (unsigned char)(0xFF >> (8-bstr)) ) );
8522             pic14_emitcode ("orl","a,b");
8523             if (p_type == GPOINTER)
8524                 pic14_emitcode("pop","b");
8525         }
8526     }
8527
8528     switch (p_type) {
8529         case POINTER:
8530             pic14_emitcode("mov","@%s,a",rname);
8531             break;
8532
8533         case FPOINTER:
8534             pic14_emitcode("movx","@dptr,a");
8535             break;
8536
8537         case GPOINTER:
8538             DEBUGpic14_emitcode(";lcall","__gptrput");
8539             break;
8540     }
8541
8542     /* if we r done */
8543     if ( SPEC_BLEN(etype) <= 8 )
8544         return ;
8545
8546     pic14_emitcode("inc","%s",rname);
8547     rLen = SPEC_BLEN(etype) ;     
8548
8549     /* now generate for lengths greater than one byte */
8550     while (1) {
8551
8552         l = aopGet(AOP(right),offset++,FALSE,TRUE);
8553
8554         rLen -= 8 ;
8555         if (rLen <= 0 )
8556             break ;
8557
8558         switch (p_type) {
8559             case POINTER:
8560                 if (*l == '@') {
8561                     MOVA(l);
8562                     pic14_emitcode("mov","@%s,a",rname);
8563                 } else
8564                     pic14_emitcode("mov","@%s,%s",rname,l);
8565                 break;
8566
8567             case FPOINTER:
8568                 MOVA(l);
8569                 pic14_emitcode("movx","@dptr,a");
8570                 break;
8571
8572             case GPOINTER:
8573                 MOVA(l);
8574                 DEBUGpic14_emitcode(";lcall","__gptrput");
8575                 break;  
8576         }   
8577         pic14_emitcode ("inc","%s",rname);
8578     }
8579
8580     MOVA(l);
8581
8582     /* last last was not complete */
8583     if (rLen)   {
8584         /* save the byte & read byte */
8585         switch (p_type) {
8586             case POINTER:
8587                 pic14_emitcode ("mov","b,a");
8588                 pic14_emitcode("mov","a,@%s",rname);
8589                 break;
8590
8591             case FPOINTER:
8592                 pic14_emitcode ("mov","b,a");
8593                 pic14_emitcode("movx","a,@dptr");
8594                 break;
8595
8596             case GPOINTER:
8597                 pic14_emitcode ("push","b");
8598                 pic14_emitcode ("push","acc");
8599                 pic14_emitcode ("lcall","__gptrget");
8600                 pic14_emitcode ("pop","b");
8601                 break;
8602         }
8603
8604         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8605         pic14_emitcode ("orl","a,b");
8606     }
8607
8608     if (p_type == GPOINTER)
8609         pic14_emitcode("pop","b");
8610
8611     switch (p_type) {
8612
8613     case POINTER:
8614         pic14_emitcode("mov","@%s,a",rname);
8615         break;
8616         
8617     case FPOINTER:
8618         pic14_emitcode("movx","@dptr,a");
8619         break;
8620         
8621     case GPOINTER:
8622         DEBUGpic14_emitcode(";lcall","__gptrput");
8623         break;                  
8624     }
8625 }
8626 /*-----------------------------------------------------------------*/
8627 /* genDataPointerSet - remat pointer to data space                 */
8628 /*-----------------------------------------------------------------*/
8629 static void genDataPointerSet(operand *right,
8630                               operand *result,
8631                               iCode *ic)
8632 {
8633     int size, offset = 0 ;
8634     char *l, buffer[256];
8635
8636     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8637     aopOp(right,ic,FALSE);
8638     
8639     l = aopGet(AOP(result),0,FALSE,TRUE);
8640     size = AOP_SIZE(right);
8641 /*
8642     if ( AOP_TYPE(result) == AOP_PCODE) {
8643       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8644               AOP(result)->aopu.pcop->name,
8645               PCOI(AOP(result)->aopu.pcop)->offset);
8646     }
8647 */
8648
8649     // tsd, was l+1 - the underline `_' prefix was being stripped
8650     while (size--) {
8651       if (offset) {
8652         sprintf(buffer,"(%s + %d)",l,offset);
8653         fprintf(stderr,"oops  %s\n",buffer);
8654       } else
8655         sprintf(buffer,"%s",l);
8656
8657         if (AOP_TYPE(right) == AOP_LIT) {
8658           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8659           lit = lit >> (8*offset);
8660           if(lit&0xff) {
8661             pic14_emitcode("movlw","%d",lit);
8662             pic14_emitcode("movwf","%s",buffer);
8663
8664             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8665             //emitpcode(POC_MOVWF, popRegFromString(buffer));
8666             emitpcode(POC_MOVWF, popGet(AOP(result),0));
8667
8668           } else {
8669             pic14_emitcode("clrf","%s",buffer);
8670             //emitpcode(POC_CLRF, popRegFromString(buffer));
8671             emitpcode(POC_CLRF, popGet(AOP(result),0));
8672           }
8673         }else {
8674           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8675           pic14_emitcode("movwf","%s",buffer);
8676
8677           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8678           //emitpcode(POC_MOVWF, popRegFromString(buffer));
8679           emitpcode(POC_MOVWF, popGet(AOP(result),0));
8680
8681         }
8682
8683         offset++;
8684     }
8685
8686     freeAsmop(right,NULL,ic,TRUE);
8687     freeAsmop(result,NULL,ic,TRUE);
8688 }
8689
8690 /*-----------------------------------------------------------------*/
8691 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8692 /*-----------------------------------------------------------------*/
8693 static void genNearPointerSet (operand *right,
8694                                operand *result, 
8695                                iCode *ic)
8696 {
8697   asmop *aop = NULL;
8698   char *l;
8699   sym_link *retype;
8700   sym_link *ptype = operandType(result);
8701
8702     
8703   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8704   retype= getSpec(operandType(right));
8705
8706   aopOp(result,ic,FALSE);
8707
8708     
8709   /* if the result is rematerializable &
8710      in data space & not a bit variable */
8711   //if (AOP_TYPE(result) == AOP_IMMD &&
8712   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8713       DCL_TYPE(ptype) == POINTER   &&
8714       !IS_BITVAR(retype)) {
8715     genDataPointerSet (right,result,ic);
8716     freeAsmop(result,NULL,ic,TRUE);
8717     return;
8718   }
8719
8720   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8721   aopOp(right,ic,FALSE);
8722   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8723
8724   /* if the value is already in a pointer register
8725      then don't need anything more */
8726   if (!AOP_INPREG(AOP(result))) {
8727     /* otherwise get a free pointer register */
8728     //aop = newAsmop(0);
8729     //preg = getFreePtr(ic,&aop,FALSE);
8730     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8731     //pic14_emitcode("mov","%s,%s",
8732     //         preg->name,
8733     //         aopGet(AOP(result),0,FALSE,TRUE));
8734     //rname = preg->name ;
8735     //pic14_emitcode("movwf","fsr");
8736     emitpcode(POC_MOVFW, popGet(AOP(result),0));
8737     emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8738     emitpcode(POC_MOVFW, popGet(AOP(right),0));
8739     emitpcode(POC_MOVWF, popCopyReg(&pc_indf));
8740     goto release;
8741
8742   }// else
8743   //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8744
8745
8746   /* if bitfield then unpack the bits */
8747   if (IS_BITVAR(retype)) {
8748     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8749            "The programmer is obviously confused");
8750     //genPackBits (retype,right,rname,POINTER);
8751     exit(1);
8752   }
8753   else {
8754     /* we have can just get the values */
8755     int size = AOP_SIZE(right);
8756     int offset = 0 ;    
8757
8758     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8759     while (size--) {
8760       l = aopGet(AOP(right),offset,FALSE,TRUE);
8761       if (*l == '@' ) {
8762         //MOVA(l);
8763         //pic14_emitcode("mov","@%s,a",rname);
8764         pic14_emitcode("movf","indf,w ;1");
8765       } else {
8766
8767         if (AOP_TYPE(right) == AOP_LIT) {
8768           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8769           if(lit) {
8770             pic14_emitcode("movlw","%s",l);
8771             pic14_emitcode("movwf","indf ;2");
8772           } else 
8773             pic14_emitcode("clrf","indf");
8774         }else {
8775           pic14_emitcode("movf","%s,w",l);
8776           pic14_emitcode("movwf","indf ;2");
8777         }
8778         //pic14_emitcode("mov","@%s,%s",rname,l);
8779       }
8780       if (size)
8781         pic14_emitcode("incf","fsr,f ;3");
8782       //pic14_emitcode("inc","%s",rname);
8783       offset++;
8784     }
8785   }
8786
8787   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8788   /* now some housekeeping stuff */
8789   if (aop) {
8790     /* we had to allocate for this iCode */
8791     freeAsmop(NULL,aop,ic,TRUE);
8792   } else { 
8793     /* we did not allocate which means left
8794        already in a pointer register, then
8795        if size > 0 && this could be used again
8796        we have to point it back to where it 
8797        belongs */
8798     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8799     if (AOP_SIZE(right) > 1 &&
8800         !OP_SYMBOL(result)->remat &&
8801         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8802           ic->depth )) {
8803       int size = AOP_SIZE(right) - 1;
8804       while (size--)
8805         pic14_emitcode("decf","fsr,f");
8806       //pic14_emitcode("dec","%s",rname);
8807     }
8808   }
8809
8810   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8811   /* done */
8812  release:
8813   freeAsmop(right,NULL,ic,TRUE);
8814   freeAsmop(result,NULL,ic,TRUE);
8815 }
8816
8817 /*-----------------------------------------------------------------*/
8818 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8819 /*-----------------------------------------------------------------*/
8820 static void genPagedPointerSet (operand *right,
8821                                operand *result, 
8822                                iCode *ic)
8823 {
8824     asmop *aop = NULL;
8825     regs *preg = NULL ;
8826     char *rname , *l;
8827     sym_link *retype;
8828        
8829     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8830
8831     retype= getSpec(operandType(right));
8832     
8833     aopOp(result,ic,FALSE);
8834     
8835     /* if the value is already in a pointer register
8836        then don't need anything more */
8837     if (!AOP_INPREG(AOP(result))) {
8838         /* otherwise get a free pointer register */
8839         aop = newAsmop(0);
8840         preg = getFreePtr(ic,&aop,FALSE);
8841         pic14_emitcode("mov","%s,%s",
8842                 preg->name,
8843                 aopGet(AOP(result),0,FALSE,TRUE));
8844         rname = preg->name ;
8845     } else
8846         rname = aopGet(AOP(result),0,FALSE,FALSE);
8847     
8848     freeAsmop(result,NULL,ic,TRUE);
8849     aopOp (right,ic,FALSE);
8850
8851     /* if bitfield then unpack the bits */
8852     if (IS_BITVAR(retype)) 
8853         genPackBits (retype,right,rname,PPOINTER);
8854     else {
8855         /* we have can just get the values */
8856         int size = AOP_SIZE(right);
8857         int offset = 0 ;        
8858         
8859         while (size--) {
8860             l = aopGet(AOP(right),offset,FALSE,TRUE);
8861             
8862             MOVA(l);
8863             pic14_emitcode("movx","@%s,a",rname);
8864
8865             if (size)
8866                 pic14_emitcode("inc","%s",rname);
8867
8868             offset++;
8869         }
8870     }
8871     
8872     /* now some housekeeping stuff */
8873     if (aop) {
8874         /* we had to allocate for this iCode */
8875         freeAsmop(NULL,aop,ic,TRUE);
8876     } else { 
8877         /* we did not allocate which means left
8878            already in a pointer register, then
8879            if size > 0 && this could be used again
8880            we have to point it back to where it 
8881            belongs */
8882         if (AOP_SIZE(right) > 1 &&
8883             !OP_SYMBOL(result)->remat &&
8884             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8885               ic->depth )) {
8886             int size = AOP_SIZE(right) - 1;
8887             while (size--)
8888                 pic14_emitcode("dec","%s",rname);
8889         }
8890     }
8891
8892     /* done */
8893     freeAsmop(right,NULL,ic,TRUE);
8894     
8895         
8896 }
8897
8898 /*-----------------------------------------------------------------*/
8899 /* genFarPointerSet - set value from far space                     */
8900 /*-----------------------------------------------------------------*/
8901 static void genFarPointerSet (operand *right,
8902                               operand *result, iCode *ic)
8903 {
8904     int size, offset ;
8905     sym_link *retype = getSpec(operandType(right));
8906
8907     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8908     aopOp(result,ic,FALSE);
8909
8910     /* if the operand is already in dptr 
8911     then we do nothing else we move the value to dptr */
8912     if (AOP_TYPE(result) != AOP_STR) {
8913         /* if this is remateriazable */
8914         if (AOP_TYPE(result) == AOP_IMMD)
8915             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8916         else { /* we need to get it byte by byte */
8917             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8918             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8919             if (options.model == MODEL_FLAT24)
8920             {
8921                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8922             }
8923         }
8924     }
8925     /* so dptr know contains the address */
8926     freeAsmop(result,NULL,ic,TRUE);
8927     aopOp(right,ic,FALSE);
8928
8929     /* if bit then unpack */
8930     if (IS_BITVAR(retype)) 
8931         genPackBits(retype,right,"dptr",FPOINTER);
8932     else {
8933         size = AOP_SIZE(right);
8934         offset = 0 ;
8935
8936         while (size--) {
8937             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8938             MOVA(l);
8939             pic14_emitcode("movx","@dptr,a");
8940             if (size)
8941                 pic14_emitcode("inc","dptr");
8942         }
8943     }
8944
8945     freeAsmop(right,NULL,ic,TRUE);
8946 }
8947
8948 /*-----------------------------------------------------------------*/
8949 /* genGenPointerSet - set value from generic pointer space         */
8950 /*-----------------------------------------------------------------*/
8951 static void genGenPointerSet (operand *right,
8952                               operand *result, iCode *ic)
8953 {
8954   int size, offset ;
8955   sym_link *retype = getSpec(operandType(right));
8956
8957   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8958
8959   aopOp(result,ic,FALSE);
8960   aopOp(right,ic,FALSE);
8961   size = AOP_SIZE(right);
8962
8963   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8964
8965   /* if the operand is already in dptr 
8966      then we do nothing else we move the value to dptr */
8967   if (AOP_TYPE(result) != AOP_STR) {
8968     /* if this is remateriazable */
8969     if (AOP_TYPE(result) == AOP_IMMD) {
8970       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8971       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8972     }
8973     else { /* we need to get it byte by byte */
8974       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8975       size = AOP_SIZE(right);
8976       offset = 0 ;
8977
8978       /* hack hack! see if this the FSR. If so don't load W */
8979       if(AOP_TYPE(right) != AOP_ACC) {
8980
8981
8982         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8983         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8984
8985         if(AOP_SIZE(result) > 1) {
8986           emitpcode(POC_BCF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8987           emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8988           emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8989
8990         }
8991
8992         //if(size==2)
8993         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8994         //if(size==4) {
8995         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8996         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8997         //}
8998
8999         while(size--) {
9000           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
9001           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9002           
9003           if(size)
9004             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9005         }
9006
9007
9008         goto release;
9009       } 
9010
9011       if(aopIdx(AOP(result),0) != 4) {
9012
9013         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9014         goto release;
9015       }
9016
9017       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9018       goto release;
9019
9020     }
9021   }
9022   /* so dptr know contains the address */
9023
9024
9025   /* if bit then unpack */
9026   if (IS_BITVAR(retype)) 
9027     genPackBits(retype,right,"dptr",GPOINTER);
9028   else {
9029     size = AOP_SIZE(right);
9030     offset = 0 ;
9031
9032   DEBUGpic14_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9033
9034     while (size--) {
9035
9036       emitpcode(POC_MOVFW,popGet(AOP(result),offset));
9037       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9038
9039       if (AOP_TYPE(right) == AOP_LIT) 
9040         emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9041       else
9042         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9043
9044       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9045
9046       offset++;
9047     }
9048   }
9049
9050  release:
9051   freeAsmop(right,NULL,ic,TRUE);
9052   freeAsmop(result,NULL,ic,TRUE);
9053 }
9054
9055 /*-----------------------------------------------------------------*/
9056 /* genPointerSet - stores the value into a pointer location        */
9057 /*-----------------------------------------------------------------*/
9058 static void genPointerSet (iCode *ic)
9059 {    
9060     operand *right, *result ;
9061     sym_link *type, *etype;
9062     int p_type;
9063
9064     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9065
9066     right = IC_RIGHT(ic);
9067     result = IC_RESULT(ic) ;
9068
9069     /* depending on the type of pointer we need to
9070     move it to the correct pointer register */
9071     type = operandType(result);
9072     etype = getSpec(type);
9073     /* if left is of type of pointer then it is simple */
9074     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9075         p_type = DCL_TYPE(type);
9076     }
9077     else {
9078         /* we have to go by the storage class */
9079         p_type = PTR_TYPE(SPEC_OCLS(etype));
9080
9081 /*      if (SPEC_OCLS(etype)->codesp ) { */
9082 /*          p_type = CPOINTER ;  */
9083 /*      } */
9084 /*      else */
9085 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9086 /*              p_type = FPOINTER ; */
9087 /*          else */
9088 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9089 /*                  p_type = PPOINTER ; */
9090 /*              else */
9091 /*                  if (SPEC_OCLS(etype) == idata ) */
9092 /*                      p_type = IPOINTER ; */
9093 /*                  else */
9094 /*                      p_type = POINTER ; */
9095     }
9096
9097     /* now that we have the pointer type we assign
9098     the pointer values */
9099     switch (p_type) {
9100
9101     case POINTER:
9102     case IPOINTER:
9103         genNearPointerSet (right,result,ic);
9104         break;
9105
9106     case PPOINTER:
9107         genPagedPointerSet (right,result,ic);
9108         break;
9109
9110     case FPOINTER:
9111         genFarPointerSet (right,result,ic);
9112         break;
9113
9114     case GPOINTER:
9115         genGenPointerSet (right,result,ic);
9116         break;
9117
9118     default:
9119       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9120               "genPointerSet: illegal pointer type");
9121     }
9122 }
9123
9124 /*-----------------------------------------------------------------*/
9125 /* genIfx - generate code for Ifx statement                        */
9126 /*-----------------------------------------------------------------*/
9127 static void genIfx (iCode *ic, iCode *popIc)
9128 {
9129   operand *cond = IC_COND(ic);
9130   int isbit =0;
9131
9132   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9133
9134   aopOp(cond,ic,FALSE);
9135
9136   /* get the value into acc */
9137   if (AOP_TYPE(cond) != AOP_CRY)
9138     pic14_toBoolean(cond);
9139   else
9140     isbit = 1;
9141   /* the result is now in the accumulator */
9142   freeAsmop(cond,NULL,ic,TRUE);
9143
9144   /* if there was something to be popped then do it */
9145   if (popIc)
9146     genIpop(popIc);
9147
9148   /* if the condition is  a bit variable */
9149   if (isbit && IS_ITEMP(cond) && 
9150       SPIL_LOC(cond)) {
9151     genIfxJump(ic,SPIL_LOC(cond)->rname);
9152     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9153   }
9154   else {
9155     if (isbit && !IS_ITEMP(cond))
9156       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9157     else
9158       genIfxJump(ic,"a");
9159   }
9160   ic->generated = 1;
9161
9162 }
9163
9164 /*-----------------------------------------------------------------*/
9165 /* genAddrOf - generates code for address of                       */
9166 /*-----------------------------------------------------------------*/
9167 static void genAddrOf (iCode *ic)
9168 {
9169   operand *right, *result, *left;
9170   int size, offset ;
9171
9172   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9173
9174
9175   //aopOp(IC_RESULT(ic),ic,FALSE);
9176
9177   aopOp((left=IC_LEFT(ic)),ic,FALSE);
9178   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9179   aopOp((result=IC_RESULT(ic)),ic,TRUE);
9180
9181   DEBUGpic14_AopType(__LINE__,left,right,result);
9182
9183   size = AOP_SIZE(IC_RESULT(ic));
9184   offset = 0;
9185
9186   while (size--) {
9187     emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9188     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9189     offset++;
9190   }
9191
9192   freeAsmop(left,NULL,ic,FALSE);
9193   freeAsmop(result,NULL,ic,TRUE);
9194
9195 }
9196
9197 #if 0
9198 /*-----------------------------------------------------------------*/
9199 /* genFarFarAssign - assignment when both are in far space         */
9200 /*-----------------------------------------------------------------*/
9201 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9202 {
9203     int size = AOP_SIZE(right);
9204     int offset = 0;
9205     char *l ;
9206     /* first push the right side on to the stack */
9207     while (size--) {
9208         l = aopGet(AOP(right),offset++,FALSE,FALSE);
9209         MOVA(l);
9210         pic14_emitcode ("push","acc");
9211     }
9212     
9213     freeAsmop(right,NULL,ic,FALSE);
9214     /* now assign DPTR to result */
9215     aopOp(result,ic,FALSE);
9216     size = AOP_SIZE(result);
9217     while (size--) {
9218         pic14_emitcode ("pop","acc");
9219         aopPut(AOP(result),"a",--offset);
9220     }
9221     freeAsmop(result,NULL,ic,FALSE);
9222         
9223 }
9224 #endif
9225
9226 /*-----------------------------------------------------------------*/
9227 /* genAssign - generate code for assignment                        */
9228 /*-----------------------------------------------------------------*/
9229 static void genAssign (iCode *ic)
9230 {
9231   operand *result, *right;
9232   int size, offset,know_W;
9233   unsigned long lit = 0L;
9234
9235   result = IC_RESULT(ic);
9236   right  = IC_RIGHT(ic) ;
9237
9238   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9239
9240   /* if they are the same */
9241   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9242     return ;
9243
9244   aopOp(right,ic,FALSE);
9245   aopOp(result,ic,TRUE);
9246
9247   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9248
9249   /* if they are the same registers */
9250   if (pic14_sameRegs(AOP(right),AOP(result)))
9251     goto release;
9252
9253   /* if the result is a bit */
9254   if (AOP_TYPE(result) == AOP_CRY) {
9255
9256     /* if the right size is a literal then
9257        we know what the value is */
9258     if (AOP_TYPE(right) == AOP_LIT) {
9259           
9260       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9261                   popGet(AOP(result),0));
9262
9263       if (((int) operandLitValue(right))) 
9264         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9265                        AOP(result)->aopu.aop_dir,
9266                        AOP(result)->aopu.aop_dir);
9267       else
9268         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9269                        AOP(result)->aopu.aop_dir,
9270                        AOP(result)->aopu.aop_dir);
9271       goto release;
9272     }
9273
9274     /* the right is also a bit variable */
9275     if (AOP_TYPE(right) == AOP_CRY) {
9276       emitpcode(POC_BCF,    popGet(AOP(result),0));
9277       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9278       emitpcode(POC_BSF,    popGet(AOP(result),0));
9279
9280       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9281                      AOP(result)->aopu.aop_dir,
9282                      AOP(result)->aopu.aop_dir);
9283       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9284                      AOP(right)->aopu.aop_dir,
9285                      AOP(right)->aopu.aop_dir);
9286       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9287                      AOP(result)->aopu.aop_dir,
9288                      AOP(result)->aopu.aop_dir);
9289       goto release ;
9290     }
9291
9292     /* we need to or */
9293     emitpcode(POC_BCF,    popGet(AOP(result),0));
9294     pic14_toBoolean(right);
9295     emitSKPZ;
9296     emitpcode(POC_BSF,    popGet(AOP(result),0));
9297     //aopPut(AOP(result),"a",0);
9298     goto release ;
9299   }
9300
9301   /* bit variables done */
9302   /* general case */
9303   size = AOP_SIZE(result);
9304   offset = 0 ;
9305   if(AOP_TYPE(right) == AOP_LIT)
9306     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9307
9308   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9309   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9310     if(aopIdx(AOP(result),0) == 4) {
9311   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9312       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9313       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9314       goto release;
9315     } else
9316       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9317   }
9318
9319   know_W=-1;
9320   while (size--) {
9321   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9322     if(AOP_TYPE(right) == AOP_LIT) {
9323       if(lit&0xff) {
9324         if(know_W != (lit&0xff))
9325           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9326         know_W = lit&0xff;
9327         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9328       } else
9329         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9330
9331       lit >>= 8;
9332
9333     } else if (AOP_TYPE(right) == AOP_CRY) {
9334       emitpcode(POC_CLRF, popGet(AOP(result),offset));
9335       if(offset == 0) {
9336         emitpcode(POC_BTFSS, popGet(AOP(right),0));
9337         emitpcode(POC_INCF, popGet(AOP(result),0));
9338       }
9339     } else {
9340   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9341       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9342       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9343     }
9344             
9345     offset++;
9346   }
9347
9348     
9349  release:
9350   freeAsmop (right,NULL,ic,FALSE);
9351   freeAsmop (result,NULL,ic,TRUE);
9352 }   
9353
9354 /*-----------------------------------------------------------------*/
9355 /* genJumpTab - genrates code for jump table                       */
9356 /*-----------------------------------------------------------------*/
9357 static void genJumpTab (iCode *ic)
9358 {
9359     symbol *jtab;
9360     char *l;
9361
9362     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9363
9364     aopOp(IC_JTCOND(ic),ic,FALSE);
9365     /* get the condition into accumulator */
9366     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9367     MOVA(l);
9368     /* multiply by three */
9369     pic14_emitcode("add","a,acc");
9370     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9371
9372     jtab = newiTempLabel(NULL);
9373     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9374     pic14_emitcode("jmp","@a+dptr");
9375     pic14_emitcode("","%05d_DS_:",jtab->key+100);
9376
9377     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9378     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9379     emitSKPNC;
9380     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9381     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9382     emitpLabel(jtab->key);
9383
9384     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9385
9386     /* now generate the jump labels */
9387     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9388          jtab = setNextItem(IC_JTLABELS(ic))) {
9389         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9390         emitpcode(POC_GOTO,popGetLabel(jtab->key));
9391         
9392     }
9393
9394 }
9395
9396 /*-----------------------------------------------------------------*/
9397 /* genMixedOperation - gen code for operators between mixed types  */
9398 /*-----------------------------------------------------------------*/
9399 /*
9400   TSD - Written for the PIC port - but this unfortunately is buggy.
9401   This routine is good in that it is able to efficiently promote 
9402   types to different (larger) sizes. Unfortunately, the temporary
9403   variables that are optimized out by this routine are sometimes
9404   used in other places. So until I know how to really parse the 
9405   iCode tree, I'm going to not be using this routine :(.
9406 */
9407 static int genMixedOperation (iCode *ic)
9408 {
9409 #if 0
9410   operand *result = IC_RESULT(ic);
9411   sym_link *ctype = operandType(IC_LEFT(ic));
9412   operand *right = IC_RIGHT(ic);
9413   int ret = 0;
9414   int big,small;
9415   int offset;
9416
9417   iCode *nextic;
9418   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9419
9420   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9421
9422   nextic = ic->next;
9423   if(!nextic)
9424     return 0;
9425
9426   nextright = IC_RIGHT(nextic);
9427   nextleft  = IC_LEFT(nextic);
9428   nextresult = IC_RESULT(nextic);
9429
9430   aopOp(right,ic,FALSE);
9431   aopOp(result,ic,FALSE);
9432   aopOp(nextright,  nextic, FALSE);
9433   aopOp(nextleft,   nextic, FALSE);
9434   aopOp(nextresult, nextic, FALSE);
9435
9436   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9437
9438     operand *t = right;
9439     right = nextright;
9440     nextright = t; 
9441
9442     pic14_emitcode(";remove right +","");
9443
9444   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9445 /*
9446     operand *t = right;
9447     right = nextleft;
9448     nextleft = t; 
9449 */
9450     pic14_emitcode(";remove left +","");
9451   } else
9452     return 0;
9453
9454   big = AOP_SIZE(nextleft);
9455   small = AOP_SIZE(nextright);
9456
9457   switch(nextic->op) {
9458
9459   case '+':
9460     pic14_emitcode(";optimize a +","");
9461     /* if unsigned or not an integral type */
9462     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9463       pic14_emitcode(";add a bit to something","");
9464     } else {
9465
9466       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9467
9468       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9469         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9470         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9471       } else
9472         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9473
9474       offset = 0;
9475       while(--big) {
9476
9477         offset++;
9478
9479         if(--small) {
9480           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9481             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9482             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9483           }
9484
9485           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9486           emitSKPNC;
9487           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9488                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9489                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9490           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9491           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9492
9493         } else {
9494           pic14_emitcode("rlf","known_zero,w");
9495
9496           /*
9497             if right is signed
9498               btfsc  right,7
9499                addlw ff
9500           */
9501           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9502             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9503             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9504           } else {
9505             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9506           }
9507         }
9508       }
9509       ret = 1;
9510     }
9511   }
9512   ret = 1;
9513
9514 release:
9515   freeAsmop(right,NULL,ic,TRUE);
9516   freeAsmop(result,NULL,ic,TRUE);
9517   freeAsmop(nextright,NULL,ic,TRUE);
9518   freeAsmop(nextleft,NULL,ic,TRUE);
9519   if(ret)
9520     nextic->generated = 1;
9521
9522   return ret;
9523 #else
9524   return 0;
9525 #endif
9526 }
9527 /*-----------------------------------------------------------------*/
9528 /* genCast - gen code for casting                                  */
9529 /*-----------------------------------------------------------------*/
9530 static void genCast (iCode *ic)
9531 {
9532     operand *result = IC_RESULT(ic);
9533     sym_link *ctype = operandType(IC_LEFT(ic));
9534     sym_link *rtype = operandType(IC_RIGHT(ic));
9535     operand *right = IC_RIGHT(ic);
9536     int size, offset ;
9537
9538     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9539     /* if they are equivalent then do nothing */
9540     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9541         return ;
9542
9543     aopOp(right,ic,FALSE) ;
9544     aopOp(result,ic,FALSE);
9545
9546     DEBUGpic14_AopType(__LINE__,NULL,right,result);
9547
9548     /* if the result is a bit */
9549     if (AOP_TYPE(result) == AOP_CRY) {
9550         /* if the right size is a literal then
9551         we know what the value is */
9552       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9553         if (AOP_TYPE(right) == AOP_LIT) {
9554
9555           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9556                       popGet(AOP(result),0));
9557
9558             if (((int) operandLitValue(right))) 
9559               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9560                        AOP(result)->aopu.aop_dir,
9561                        AOP(result)->aopu.aop_dir);
9562             else
9563               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9564                        AOP(result)->aopu.aop_dir,
9565                        AOP(result)->aopu.aop_dir);
9566
9567             goto release;
9568         }
9569
9570         /* the right is also a bit variable */
9571         if (AOP_TYPE(right) == AOP_CRY) {
9572
9573           emitCLRC;
9574           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9575
9576           pic14_emitcode("clrc","");
9577           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9578                    AOP(right)->aopu.aop_dir,
9579                    AOP(right)->aopu.aop_dir);
9580             aopPut(AOP(result),"c",0);
9581             goto release ;
9582         }
9583
9584         /* we need to or */
9585         if (AOP_TYPE(right) == AOP_REG) {
9586           emitpcode(POC_BCF,    popGet(AOP(result),0));
9587           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9588           emitpcode(POC_BSF,    popGet(AOP(result),0));
9589         }
9590         pic14_toBoolean(right);
9591         aopPut(AOP(result),"a",0);
9592         goto release ;
9593     }
9594
9595     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9596       int offset = 1;
9597       size = AOP_SIZE(result);
9598
9599       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9600
9601       emitpcode(POC_CLRF,   popGet(AOP(result),0));
9602       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9603       emitpcode(POC_INCF,   popGet(AOP(result),0));
9604
9605       while (size--)
9606         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9607
9608       goto release;
9609     }
9610
9611     /* if they are the same size : or less */
9612     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9613
9614         /* if they are in the same place */
9615       if (pic14_sameRegs(AOP(right),AOP(result)))
9616         goto release;
9617
9618       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9619       if (IS_PTR_CONST(rtype))
9620         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9621       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9622         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9623
9624       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9625         emitpcode(POC_MOVLW, popGet(AOP(right),0));
9626         emitpcode(POC_MOVWF, popGet(AOP(result),0));
9627         emitpcode(POC_MOVLW, popGet(AOP(right),1));
9628         emitpcode(POC_MOVWF, popGet(AOP(result),1));
9629         if(AOP_SIZE(result) <2)
9630           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9631
9632       } else {
9633
9634         /* if they in different places then copy */
9635         size = AOP_SIZE(result);
9636         offset = 0 ;
9637         while (size--) {
9638           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9639           emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9640
9641           //aopPut(AOP(result),
9642           // aopGet(AOP(right),offset,FALSE,FALSE),
9643           // offset);
9644
9645           offset++;
9646         }
9647       }
9648       goto release;
9649     }
9650
9651
9652     /* if the result is of type pointer */
9653     if (IS_PTR(ctype)) {
9654
9655         int p_type;
9656         sym_link *type = operandType(right);
9657         sym_link *etype = getSpec(type);
9658       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9659
9660         /* pointer to generic pointer */
9661         if (IS_GENPTR(ctype)) {
9662             char *l = zero;
9663             
9664             if (IS_PTR(type)) 
9665                 p_type = DCL_TYPE(type);
9666             else {
9667                 /* we have to go by the storage class */
9668                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9669
9670 /*              if (SPEC_OCLS(etype)->codesp )  */
9671 /*                  p_type = CPOINTER ;  */
9672 /*              else */
9673 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9674 /*                      p_type = FPOINTER ; */
9675 /*                  else */
9676 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9677 /*                          p_type = PPOINTER; */
9678 /*                      else */
9679 /*                          if (SPEC_OCLS(etype) == idata ) */
9680 /*                              p_type = IPOINTER ; */
9681 /*                          else */
9682 /*                              p_type = POINTER ; */
9683             }
9684                 
9685             /* the first two bytes are known */
9686       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9687             size = GPTRSIZE - 1; 
9688             offset = 0 ;
9689             while (size--) {
9690               if(offset < AOP_SIZE(right)) {
9691       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9692                 if ((AOP_TYPE(right) == AOP_PCODE) && 
9693                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9694                   emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9695                   emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9696                 } else { 
9697                   aopPut(AOP(result),
9698                          aopGet(AOP(right),offset,FALSE,FALSE),
9699                          offset);
9700                 }
9701               } else 
9702                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
9703               offset++;
9704             }
9705             /* the last byte depending on type */
9706             switch (p_type) {
9707             case IPOINTER:
9708             case POINTER:
9709                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9710                 break;
9711             case FPOINTER:
9712               pic14_emitcode(";BUG!? ","%d",__LINE__);
9713                 l = one;
9714                 break;
9715             case CPOINTER:
9716               pic14_emitcode(";BUG!? ","%d",__LINE__);
9717                 l = "#0x02";
9718                 break;                          
9719             case PPOINTER:
9720               pic14_emitcode(";BUG!? ","%d",__LINE__);
9721                 l = "#0x03";
9722                 break;
9723                 
9724             default:
9725                 /* this should never happen */
9726                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9727                        "got unknown pointer type");
9728                 exit(1);
9729             }
9730             //aopPut(AOP(result),l, GPTRSIZE - 1);          
9731             goto release ;
9732         }
9733         
9734         /* just copy the pointers */
9735         size = AOP_SIZE(result);
9736         offset = 0 ;
9737         while (size--) {
9738             aopPut(AOP(result),
9739                    aopGet(AOP(right),offset,FALSE,FALSE),
9740                    offset);
9741             offset++;
9742         }
9743         goto release ;
9744     }
9745     
9746
9747
9748     /* so we now know that the size of destination is greater
9749     than the size of the source.
9750     Now, if the next iCode is an operator then we might be
9751     able to optimize the operation without performing a cast.
9752     */
9753     if(genMixedOperation(ic))
9754       goto release;
9755
9756     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9757     
9758     /* we move to result for the size of source */
9759     size = AOP_SIZE(right);
9760     offset = 0 ;
9761     while (size--) {
9762       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9763       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9764       offset++;
9765     }
9766
9767     /* now depending on the sign of the destination */
9768     size = AOP_SIZE(result) - AOP_SIZE(right);
9769     /* if unsigned or not an integral type */
9770     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9771       while (size--)
9772         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9773     } else {
9774       /* we need to extend the sign :{ */
9775
9776       if(size == 1) {
9777         /* Save one instruction of casting char to int */
9778         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9779         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9780         emitpcode(POC_DECF,   popGet(AOP(result),offset));
9781       } else {
9782         emitpcodeNULLop(POC_CLRW);
9783
9784         if(offset)
9785           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9786         else
9787           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9788         
9789         emitpcode(POC_MOVLW,   popGetLit(0xff));
9790
9791         while (size--)
9792           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9793       }
9794     }
9795
9796 release:
9797     freeAsmop(right,NULL,ic,TRUE);
9798     freeAsmop(result,NULL,ic,TRUE);
9799
9800 }
9801
9802 /*-----------------------------------------------------------------*/
9803 /* genDjnz - generate decrement & jump if not zero instrucion      */
9804 /*-----------------------------------------------------------------*/
9805 static int genDjnz (iCode *ic, iCode *ifx)
9806 {
9807     symbol *lbl, *lbl1;
9808     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9809
9810     if (!ifx)
9811         return 0;
9812     
9813     /* if the if condition has a false label
9814        then we cannot save */
9815     if (IC_FALSE(ifx))
9816         return 0;
9817
9818     /* if the minus is not of the form 
9819        a = a - 1 */
9820     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9821         !IS_OP_LITERAL(IC_RIGHT(ic)))
9822         return 0;
9823
9824     if (operandLitValue(IC_RIGHT(ic)) != 1)
9825         return 0;
9826
9827     /* if the size of this greater than one then no
9828        saving */
9829     if (getSize(operandType(IC_RESULT(ic))) > 1)
9830         return 0;
9831
9832     /* otherwise we can save BIG */
9833     lbl = newiTempLabel(NULL);
9834     lbl1= newiTempLabel(NULL);
9835
9836     aopOp(IC_RESULT(ic),ic,FALSE);
9837     
9838     if (IS_AOP_PREG(IC_RESULT(ic))) {
9839         pic14_emitcode("dec","%s",
9840                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9841         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9842         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9843     } else {    
9844
9845
9846       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9847       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9848
9849       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9850       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9851
9852     }
9853 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9854 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9855 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9856 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9857
9858     
9859     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9860     ifx->generated = 1;
9861     return 1;
9862 }
9863
9864 /*-----------------------------------------------------------------*/
9865 /* genReceive - generate code for a receive iCode                  */
9866 /*-----------------------------------------------------------------*/
9867 static void genReceive (iCode *ic)
9868 {    
9869   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9870
9871   if (isOperandInFarSpace(IC_RESULT(ic)) && 
9872       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9873         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9874
9875     int size = getSize(operandType(IC_RESULT(ic)));
9876     int offset =  fReturnSizePic - size;
9877     while (size--) {
9878       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9879                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9880       offset++;
9881     }
9882     aopOp(IC_RESULT(ic),ic,FALSE);  
9883     size = AOP_SIZE(IC_RESULT(ic));
9884     offset = 0;
9885     while (size--) {
9886       pic14_emitcode ("pop","acc");
9887       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9888     }
9889         
9890   } else {
9891     _G.accInUse++;
9892     aopOp(IC_RESULT(ic),ic,FALSE);  
9893     _G.accInUse--;
9894     assignResultValue(IC_RESULT(ic));   
9895   }
9896
9897   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9898 }
9899
9900 /*-----------------------------------------------------------------*/
9901 /* genpic14Code - generate code for pic14 based controllers        */
9902 /*-----------------------------------------------------------------*/
9903 /*
9904  * At this point, ralloc.c has gone through the iCode and attempted
9905  * to optimize in a way suitable for a PIC. Now we've got to generate
9906  * PIC instructions that correspond to the iCode.
9907  *
9908  * Once the instructions are generated, we'll pass through both the
9909  * peep hole optimizer and the pCode optimizer.
9910  *-----------------------------------------------------------------*/
9911
9912 void genpic14Code (iCode *lic)
9913 {
9914     iCode *ic;
9915     int cln = 0;
9916
9917     lineHead = lineCurr = NULL;
9918
9919     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9920     addpBlock(pb);
9921
9922     /* if debug information required */
9923     if (options.debug && currFunc) { 
9924       if (currFunc) {
9925         debugFile->writeFunction(currFunc);
9926         _G.debugLine = 1;
9927         if (IS_STATIC(currFunc->etype)) {
9928           pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9929           //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9930         } else {
9931           pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9932           //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9933         }
9934         _G.debugLine = 0;
9935       }
9936     }
9937
9938
9939     for (ic = lic ; ic ; ic = ic->next ) {
9940
9941       DEBUGpic14_emitcode(";ic","");
9942         if ( cln != ic->lineno ) {
9943             if ( options.debug ) {
9944                 _G.debugLine = 1;
9945                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9946                          FileBaseName(ic->filename),ic->lineno,
9947                          ic->level,ic->block);
9948                 _G.debugLine = 0;
9949             }
9950             /*
9951               pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9952               pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9953               printCLine(ic->filename, ic->lineno));
9954             */
9955             if (!options.noCcodeInAsm) {
9956               addpCode2pBlock(pb,
9957                               newpCodeCSource(ic->lineno, 
9958                                               ic->filename, 
9959                                               printCLine(ic->filename, ic->lineno)));
9960             }
9961
9962             cln = ic->lineno ;
9963         }
9964
9965         // if you want printILine too, look at ../mcs51/gen.c, i don't understand this :)
9966
9967         /* if the result is marked as
9968            spilt and rematerializable or code for
9969            this has already been generated then
9970            do nothing */
9971         if (resultRemat(ic) || ic->generated ) 
9972             continue ;
9973         
9974         /* depending on the operation */
9975         switch (ic->op) {
9976         case '!' :
9977             genNot(ic);
9978             break;
9979             
9980         case '~' :
9981             genCpl(ic);
9982             break;
9983             
9984         case UNARYMINUS:
9985             genUminus (ic);
9986             break;
9987             
9988         case IPUSH:
9989             genIpush (ic);
9990             break;
9991             
9992         case IPOP:
9993             /* IPOP happens only when trying to restore a 
9994                spilt live range, if there is an ifx statement
9995                following this pop then the if statement might
9996                be using some of the registers being popped which
9997                would destory the contents of the register so
9998                we need to check for this condition and handle it */
9999             if (ic->next            && 
10000                 ic->next->op == IFX &&
10001                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10002                 genIfx (ic->next,ic);
10003             else
10004                 genIpop (ic);
10005             break; 
10006             
10007         case CALL:
10008             genCall (ic);
10009             break;
10010             
10011         case PCALL:
10012             genPcall (ic);
10013             break;
10014             
10015         case FUNCTION:
10016             genFunction (ic);
10017             break;
10018             
10019         case ENDFUNCTION:
10020             genEndFunction (ic);
10021             break;
10022             
10023         case RETURN:
10024             genRet (ic);
10025             break;
10026             
10027         case LABEL:
10028             genLabel (ic);
10029             break;
10030             
10031         case GOTO:
10032             genGoto (ic);
10033             break;
10034             
10035         case '+' :
10036             genPlus (ic) ;
10037             break;
10038             
10039         case '-' :
10040             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10041                 genMinus (ic);
10042             break;
10043             
10044         case '*' :
10045             genMult (ic);
10046             break;
10047             
10048         case '/' :
10049             genDiv (ic) ;
10050             break;
10051             
10052         case '%' :
10053             genMod (ic);
10054             break;
10055             
10056         case '>' :
10057             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10058             break;
10059             
10060         case '<' :
10061             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10062             break;
10063             
10064         case LE_OP:
10065         case GE_OP:
10066         case NE_OP:
10067             
10068             /* note these two are xlated by algebraic equivalence
10069                during parsing SDCC.y */
10070             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10071                    "got '>=' or '<=' shouldn't have come here");
10072             break;      
10073             
10074         case EQ_OP:
10075             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10076             break;          
10077             
10078         case AND_OP:
10079             genAndOp (ic);
10080             break;
10081             
10082         case OR_OP:
10083             genOrOp (ic);
10084             break;
10085             
10086         case '^' :
10087             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10088             break;
10089             
10090         case '|' :
10091                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10092             break;
10093             
10094         case BITWISEAND:
10095             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10096             break;
10097             
10098         case INLINEASM:
10099             genInline (ic);
10100             break;
10101             
10102         case RRC:
10103             genRRC (ic);
10104             break;
10105             
10106         case RLC:
10107             genRLC (ic);
10108             break;
10109             
10110         case GETHBIT:
10111             genGetHbit (ic);
10112             break;
10113             
10114         case LEFT_OP:
10115             genLeftShift (ic);
10116             break;
10117             
10118         case RIGHT_OP:
10119             genRightShift (ic);
10120             break;
10121             
10122         case GET_VALUE_AT_ADDRESS:
10123             genPointerGet(ic);
10124             break;
10125             
10126         case '=' :
10127             if (POINTER_SET(ic))
10128                 genPointerSet(ic);
10129             else
10130                 genAssign(ic);
10131             break;
10132             
10133         case IFX:
10134             genIfx (ic,NULL);
10135             break;
10136             
10137         case ADDRESS_OF:
10138             genAddrOf (ic);
10139             break;
10140             
10141         case JUMPTABLE:
10142             genJumpTab (ic);
10143             break;
10144             
10145         case CAST:
10146             genCast (ic);
10147             break;
10148             
10149         case RECEIVE:
10150             genReceive(ic);
10151             break;
10152             
10153         case SEND:
10154             addSet(&_G.sendSet,ic);
10155             break;
10156
10157         default :
10158             ic = ic;
10159         }
10160     }
10161     
10162
10163     /* now we are ready to call the 
10164        peep hole optimizer */
10165     if (!options.nopeep) {
10166       peepHole (&lineHead);
10167     }
10168     /* now do the actual printing */
10169     printLine (lineHead,codeOutFile);
10170
10171 #ifdef PCODE_DEBUG
10172     DFPRINTF((stderr,"printing pBlock\n\n"));
10173     printpBlock(stdout,pb);
10174 #endif
10175
10176     return;
10177 }